]> git.sur5r.net Git - openldap/commitdiff
ITS#5369 SASL/GSSAPi refactoring from Stefan Metzmacher <metze@samba.org>
authorHoward Chu <hyc@openldap.org>
Thu, 9 Oct 2008 10:51:28 +0000 (10:51 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 9 Oct 2008 10:51:28 +0000 (10:51 +0000)
and Rafal Szczeniak <mimir@samba.org>, with minor cleanups

18 files changed:
build/top.mk
configure.in
doc/man/man5/ldap.conf.5
include/ldap.h
include/ldap_pvt.h
include/portable.hin
libraries/libldap/Makefile.in
libraries/libldap/bind.c
libraries/libldap/cyrus.c
libraries/libldap/init.c
libraries/libldap/ldap-int.h
libraries/libldap/options.c
libraries/libldap/os-ip.c
libraries/libldap/os-local.c
libraries/libldap/request.c
libraries/libldap/sasl.c
libraries/libldap/util-int.c
libraries/libldap_r/Makefile.in

index 468dd5e482238be88fe7d961ab9a00c5b618d7a1..32ddf2b11970228aab6da03c52120cffb29f0f03 100644 (file)
@@ -186,9 +186,10 @@ KRB4_LIBS = @KRB4_LIBS@
 KRB5_LIBS = @KRB5_LIBS@
 KRB_LIBS = @KRB4_LIBS@ @KRB5_LIBS@
 SASL_LIBS = @SASL_LIBS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
 TLS_LIBS = @TLS_LIBS@
 AUTH_LIBS = @AUTH_LIBS@
-SECURITY_LIBS = $(SASL_LIBS) $(KRB_LIBS) $(TLS_LIBS) $(AUTH_LIBS)
+SECURITY_LIBS = $(SASL_LIBS) $(KRB_LIBS) $(GSSAPI_LIBS) $(TLS_LIBS) $(AUTH_LIBS)
 ICU_LIBS = @ICU_LIBS@
 
 MODULES_CPPFLAGS = @SLAPD_MODULES_CPPFLAGS@
index 905665e6d6dca748f1f37de006700e9ab35c0754..b4618fdcae24a9e7593cb3f3aff6a77ab6508c77 100644 (file)
@@ -242,6 +242,8 @@ OL_ARG_WITH(cyrus_sasl,[  --with-cyrus-sasl   with Cyrus SASL support],
        auto, [auto yes no] )
 OL_ARG_WITH(fetch,[  --with-fetch                with fetch(3) URL support],
        auto, [auto yes no] )
+OL_ARG_WITH(gssapi,[  --with-gssapi              with GSSAPI support],
+       auto, [auto yes no] )
 OL_ARG_WITH(threads,[  --with-threads    with threads],
        auto, [auto nt posix mach pth lwp yes no manual] )
 OL_ARG_WITH(tls,[  --with-tls            with TLS/SSL support auto|openssl|gnutls],
@@ -576,6 +578,7 @@ SLAPD_SQL_INCLUDES=
 KRB4_LIBS=
 KRB5_LIBS=
 SASL_LIBS=
+GSSAPI_LIBS=
 TLS_LIBS=
 MODULES_LIBS=
 SLAPI_LIBS=
@@ -1120,6 +1123,58 @@ if test $ol_enable_local != no ; then
        fi
 fi
 
+dnl ----------------------------------------------------------------
+dnl GSSAPI
+ol_link_gssapi=no
+
+case $ol_with_gssapi in yes | auto)
+
+       ol_header_gssapi=no
+       AC_CHECK_HEADERS(gssapi/gssapi.h)
+       if test $ac_cv_header_gssapi_gssapi_h = yes ; then
+               ol_header_gssapi=yes
+       else
+               AC_CHECK_HEADERS(gssapi.h)
+               if test $ac_cv_header_gssapi_h = yes ; then
+                       ol_header_gssapi=yes
+               fi
+
+               dnl## not every gssapi has gss_oid_to_str()
+               dnl## as it's not defined in the GSSAPI V2 API
+               dnl## anymore
+               saveLIBS="$LIBS"
+               LIBS="$LIBS $GSSAPI_LIBS"
+               AC_CHECK_FUNCS(gss_oid_to_str)
+               LIBS="$saveLIBS"
+       fi
+
+       if test $ol_header_gssapi = yes ; then
+               dnl## we check for gss_wrap
+               dnl## as it's new to the GSSAPI V2 API
+               AC_CHECK_LIB(gssapi, gss_wrap,
+                            [ol_link_gssapi=yes;GSSAPI_LIBS="-lgssapi"],
+                            [ol_link_gssapi=no])
+               if test $ol_link_gssapi != yes ; then
+                       AC_CHECK_LIB(gssapi_krb5, gss_wrap,
+                                    [ol_link_gssapi=yes;GSSAPI_LIBS="-lgssapi_krb5"],
+                                    [ol_link_gssapi=no])
+               fi
+       fi
+
+       ;;
+esac
+
+WITH_GSSAPI=no
+if test $ol_link_gssapi = yes; then
+       AC_DEFINE(HAVE_GSSAPI, 1, [define if you have GSSAPI])
+       WITH_GSSAPI=yes
+elif test $ol_with_gssapi = auto ; then
+       AC_MSG_WARN([Could not locate GSSAPI package])
+       AC_MSG_WARN([GSSAPI authentication not supported!])
+elif test $ol_with_gssapi = yes ; then
+       AC_MSG_ERROR([GSSAPI detection failed])
+fi
+
 dnl ----------------------------------------------------------------
 dnl TLS/SSL
        
@@ -3048,6 +3103,7 @@ AC_SUBST(MOD_PERL_LDFLAGS)
 AC_SUBST(KRB4_LIBS)
 AC_SUBST(KRB5_LIBS)
 AC_SUBST(SASL_LIBS)
+AC_SUBST(GSSAPI_LIBS)
 AC_SUBST(TLS_LIBS)
 AC_SUBST(MODULES_LIBS)
 AC_SUBST(SLAPI_LIBS)
index d8ac6f6e6161584c677dc3ac67420954dcd35b51..ecb87d7fe2dcac16daa514badc6a4f726920ccaf 100644 (file)
@@ -272,6 +272,22 @@ description).  The default is
 specifies the maximum security layer receive buffer
 size allowed.  0 disables security layers.  The default is 65536.
 .RE
+.SH GSSAPI OPTIONS
+If OpenLDAP is built with Generic Security Services Application Programming Interface support,
+there are more options you can specify.
+.TP
+.B GSSAPI_SIGN <on/true/yes/off/false/no>
+Specifies if GSSAPI signing (GSS_C_INTEG_FLAG) should be used.
+The default is off.
+.TP
+.B GSSAPI_ENCRYPT <on/true/yes/off/false/no>
+Specifies if GSSAPI encryption (GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG)
+should be used. The default is off.
+.TP
+.B GSSAPI_ALLOW_REMOTE_PRINCIPAL <on/true/yes/off/false/no>
+Specifies if GSSAPI based authentification should try to form the
+target principal name out of the ldapServiceName or dnsHostName
+attribute of the targets RootDSE entry. The default is off.
 .SH TLS OPTIONS
 If OpenLDAP is built with Transport Layer Security support, there
 are more options you can specify.  These options are used when an
index fb66dbb569d35c0258636848ce084bdd165e0f32..b86071aadbcf8f546b09a6a271272a4f236ddbf7 100644 (file)
@@ -108,6 +108,17 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_ERROR_STRING                  LDAP_OPT_DIAGNOSTIC_MESSAGE
 #define LDAP_OPT_MATCHED_DN                    0x0033
 /* 0x0034 - 0x3fff not defined */
+/* 0x0091 used by Microsoft for LDAP_OPT_AUTO_RECONNECT */
+#define LDAP_OPT_SSPI_FLAGS                    0x0092
+/* 0x0093 used by Microsoft for LDAP_OPT_SSL_INFO */
+/* 0x0094 used by Microsoft for LDAP_OPT_REF_DEREF_CONN_PER_MSG */
+#define LDAP_OPT_SIGN                          0x0095
+#define LDAP_OPT_ENCRYPT                       0x0096
+#define LDAP_OPT_SASL_METHOD                   0x0097
+/* 0x0098 used by Microsoft for LDAP_OPT_AREC_EXCLUSIVE */
+#define LDAP_OPT_SECURITY_CONTEXT              0x0099
+/* 0x009A used by Microsoft for LDAP_OPT_ROOTDSE_CACHE */
+/* 0x009B - 0x3fff not defined */
 
 /* API Extensions */
 #define LDAP_OPT_API_EXTENSION_BASE 0x4000  /* API extensions */
@@ -167,6 +178,11 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_SASL_MAXBUFSIZE             0x6109
 #define LDAP_OPT_X_SASL_MECHLIST               0x610a /* read-only */
 
+/* OpenLDAP GSSAPI options */
+#define LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT      0x6200
+#define LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL   0x6201
+
+
 /* Private API Extensions -- reserved for application use */
 #define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000  /* Private API inclusive */
 
@@ -482,6 +498,8 @@ typedef struct ldapcontrol {
 #define LDAP_AUTH_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */
 #define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* context specific + primitive */
 
+/* used by the Windows API but not used on the wire */
+#define LDAP_AUTH_NEGOTIATE ((ber_tag_t) 0x04FFU)
 
 /* filter types */
 #define LDAP_FILTER_AND        ((ber_tag_t) 0xa0U)     /* context specific + constructed */
index f26889af743e8e75c9106f9fa3d56e6db49f51f6..6c36d1af8830a51884d6e2c0f25946a303e8998a 100644 (file)
@@ -21,6 +21,7 @@
 #define _LDAP_PVT_H 1
 
 #include <lber.h>                              /* get ber_slen_t */
+#include <lber_pvt.h>                          /* get Sockbuf_Buf */
 
 LDAP_BEGIN_DECL
 
@@ -217,12 +218,52 @@ LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void));
 LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex));
 LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex));
 LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex));
+#endif /* HAVE_CYRUS_SASL */
 
 struct sockbuf; /* avoid pulling in <lber.h> */
 LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * ));
 LDAP_F (void) ldap_pvt_sasl_remove LDAP_P(( struct sockbuf * ));
-#endif /* HAVE_CYRUS_SASL */
 
+/*
+ * SASL encryption support for LBER Sockbufs
+ */
+
+struct sb_sasl_generic_data;
+
+struct sb_sasl_generic_ops {
+       void (*init)(struct sb_sasl_generic_data *p,
+                    ber_len_t *min_send,
+                    ber_len_t *max_send,
+                    ber_len_t *max_recv);
+       ber_int_t (*encode)(struct sb_sasl_generic_data *p,
+                           unsigned char *buf,
+                           ber_len_t len,
+                           Sockbuf_Buf *dst);
+       ber_int_t (*decode)(struct sb_sasl_generic_data *p,
+                           const Sockbuf_Buf *src,
+                           Sockbuf_Buf *dst);
+       void (*reset_buf)(struct sb_sasl_generic_data *p,
+                         Sockbuf_Buf *buf);
+       void (*fini)(struct sb_sasl_generic_data *p);
+};
+
+struct sb_sasl_generic_install {
+       const struct sb_sasl_generic_ops        *ops;
+       void                                    *ops_private;
+};
+
+struct sb_sasl_generic_data {
+       const struct sb_sasl_generic_ops        *ops;
+       void                                    *ops_private;
+       Sockbuf_IO_Desc                         *sbiod;
+       ber_len_t                               min_send;
+       ber_len_t                               max_send;
+       ber_len_t                               max_recv;
+       Sockbuf_Buf                             sec_buf_in;
+       Sockbuf_Buf                             buf_in;
+       Sockbuf_Buf                             buf_out;
+};
 #ifndef LDAP_PVT_SASL_LOCAL_SSF
 #define LDAP_PVT_SASL_LOCAL_SSF        71      /* SSF for Unix Domain Sockets */
 #endif /* ! LDAP_PVT_SASL_LOCAL_SSF */
index fbdb2b848dab2906231f7cf5ef3f984f94bd11ba..eaaaa3aeb52992002640fc14479f127d8f630bfc 100644 (file)
 /* Define to 1 if you have the <grp.h> header file. */
 #undef HAVE_GRP_H
 
+/* define if you have GSSAPI */
+#undef HAVE_GSSAPI
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define to 1 if you have the `gss_oid_to_str' function. */
+#undef HAVE_GSS_OID_TO_STR
+
 /* Define to 1 if you have the `hstrerror' function. */
 #undef HAVE_HSTRERROR
 
index e0d0aabe2c9c22357f2b77359b3c699950ead982..c62e56ffc0627fc48e8cfff41a7b9738a11f75dd 100644 (file)
@@ -20,7 +20,7 @@ PROGRAMS = apitest dntest ftest ltest urltest
 SRCS   = bind.c open.c result.c error.c compare.c search.c \
        controls.c messages.c references.c extended.c cyrus.c \
        modify.c add.c modrdn.c delete.c abandon.c \
-       sasl.c sbind.c unbind.c cancel.c  \
+       sasl.c gssapi.c sbind.c unbind.c cancel.c  \
        filter.c free.c sort.c passwd.c whoami.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
        request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \
@@ -32,7 +32,7 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo cyrus.lo \
        modify.lo add.lo modrdn.lo delete.lo abandon.lo \
-       sasl.lo sbind.lo unbind.lo cancel.lo \
+       sasl.lo gssapi.lo sbind.lo unbind.lo cancel.lo \
        filter.lo free.lo sort.lo passwd.lo whoami.lo \
        getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
        request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
index a9d21e41c43dcf944d26f1efa125f25045d10efa..22cb60d3818d6658cf4946dbdee6bd64f6533372 100644 (file)
@@ -71,6 +71,11 @@ ldap_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmetho
        case LDAP_AUTH_SIMPLE:
                return( ldap_simple_bind( ld, dn, passwd ) );
 
+#ifdef HAVE_GSSAPI
+       case LDAP_AUTH_NEGOTIATE:
+               return( ldap_gssapi_bind_s( ld, dn, passwd) );
+#endif
+
        case LDAP_AUTH_SASL:
                /* user must use ldap_sasl_bind */
                /* FALL-THRU */
@@ -107,6 +112,11 @@ ldap_bind_s(
        case LDAP_AUTH_SIMPLE:
                return( ldap_simple_bind_s( ld, dn, passwd ) );
 
+#ifdef HAVE_GSSAPI
+       case LDAP_AUTH_NEGOTIATE:
+               return( ldap_gssapi_bind_s( ld, dn, passwd) );
+#endif
+
        case LDAP_AUTH_SASL:
                /* user must use ldap_sasl_bind */
                /* FALL-THRU */
index d5779fd71fc3048a460f696d46a1776f25412576..0aee1c8a68a90debe190870336b5dc7b70b8e333 100644 (file)
@@ -133,321 +133,128 @@ int ldap_int_sasl_init( void )
        return -1;
 }
 
-/*
- * SASL encryption support for LBER Sockbufs
- */
-
-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;
-};
-
-static int
-sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+static void
+sb_sasl_cyrus_init(
+       struct sb_sasl_generic_data *p,
+       ber_len_t *min_send,
+       ber_len_t *max_send,
+       ber_len_t *max_recv)
 {
-       struct sb_sasl_data     *p;
+       sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private;
+       ber_len_t maxbuf;
 
-       assert( sbiod != NULL );
+       sasl_getprop( sasl_context, SASL_MAXOUTBUF,
+                     (SASL_CONST void **)(char *) &maxbuf );
 
-       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, SASL_MIN_BUFF_SIZE ) < 0 ) {
-               LBER_FREE( p );
-               sock_errset(ENOMEM);
-               return -1;
-       }
-       sasl_getprop( p->sasl_context, SASL_MAXOUTBUF,
-               (SASL_CONST void **)(char *) &p->sasl_maxbuf );
-           
-       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;
-#if SASL_VERSION_MAJOR >= 2
-       /*
-        * SASLv2 encode/decode buffers are managed by
-        * libsasl2. Ensure they are not freed by liblber.
-        */
-       p->buf_in.buf_base = NULL;
-       p->buf_out.buf_base = NULL;
-#endif
-       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;
+       *min_send = SASL_MIN_BUFF_SIZE;
+       *max_send = maxbuf;
+       *max_recv = SASL_MAX_BUFF_SIZE;
 }
 
-static ber_len_t
-sb_sasl_pkt_length( const unsigned char *buf, int debuglevel )
+static ber_int_t
+sb_sasl_cyrus_encode(
+       struct sb_sasl_generic_data *p,
+       unsigned char *buf,
+       ber_len_t len,
+       Sockbuf_Buf *dst)
 {
-       ber_len_t               size;
+       sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private;
+       ber_int_t ret;
+       unsigned tmpsize = dst->buf_size;
 
-       assert( buf != NULL );
+       ret = sasl_encode( sasl_context, buf, len,
+                          (SASL_CONST char **)&dst->buf_base,
+                          &tmpsize );
 
-       size = buf[0] << 24
-               | buf[1] << 16
-               | buf[2] << 8
-               | buf[3];
+       dst->buf_size = tmpsize;
+       dst->buf_end = dst->buf_size;
 
-       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. */
+       if ( ret != SASL_OK ) {
+               ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
+                               "sb_sasl_cyrus_encode: failed to encode packet: %s\n",
+                               sasl_errstring( ret, NULL, NULL ) );
+               return -1;
        }
 
-       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 )
-               AC_MEMCPY( 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(
-                       (unsigned char *) sec_buf_in->buf_base, debuglevel);
-       }
-       else {
-               sec_buf_in->buf_end = 0;
-       }
-       sec_buf_in->buf_ptr = len;
+       return 0;
 }
 
-static ber_slen_t
-sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+static ber_int_t
+sb_sasl_cyrus_decode(
+       struct sb_sasl_generic_data *p,
+       const Sockbuf_Buf *src,
+       Sockbuf_Buf *dst)
 {
-       struct sb_sasl_data     *p;
-       ber_slen_t              ret, bufptr;
-   
-       assert( sbiod != NULL );
-       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+       sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private;
+       ber_int_t ret;
+       unsigned tmpsize = dst->buf_size;
 
-       p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+       ret = sasl_decode( sasl_context,
+                          src->buf_base, src->buf_end,
+                          (SASL_CONST char **)&dst->buf_base,
+                          (unsigned *)&tmpsize );
 
-       /* 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;
-
-#if SASL_VERSION_MAJOR >= 2
-       ber_pvt_sb_buf_init( &p->buf_in );
-#else
-       ber_pvt_sb_buf_destroy( &p->buf_in );
-#endif
-
-       /* 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 +
-                       p->sec_buf_in.buf_ptr,
-                       4 - p->sec_buf_in.buf_ptr );
-#ifdef EINTR
-               if ( ( ret < 0 ) && ( errno == EINTR ) )
-                       continue;
-#endif
-               if ( ret <= 0 )
-                       return bufptr ? bufptr : 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( (unsigned char *) p->sec_buf_in.buf_base,
-               sbiod->sbiod_sb->sb_debug );
-
-       /* Grow the packet buffer if neccessary */
-       if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) && 
-               ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 )
-       {
-               sock_errset(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 bufptr ? bufptr : ret;
-
-               p->sec_buf_in.buf_ptr += ret;
-       }
-
-       /* Decode the packet */
-       {
-               unsigned tmpsize = p->buf_in.buf_end;
-               ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
-                       p->sec_buf_in.buf_end,
-                       (SASL_CONST char **)&p->buf_in.buf_base,
-                       (unsigned *)&tmpsize );
-               p->buf_in.buf_end = tmpsize;
-       }
-
-       /* Drop the packet from the input buffer */
-       sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
+       dst->buf_size = tmpsize;
+       dst->buf_end = dst->buf_size;
 
        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 ) );
-               sock_errset(EIO);
+               ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
+                               "sb_sasl_cyrus_decode: failed to decode packet: %s\n",
+                               sasl_errstring( ret, NULL, NULL ) );
                return -1;
        }
-       
-       p->buf_in.buf_size = p->buf_in.buf_end;
 
-       bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
-
-       return bufptr;
+       return 0;
 }
 
-static ber_slen_t
-sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+static void
+sb_sasl_cyrus_reset_buf(
+       struct sb_sasl_generic_data *p,
+       Sockbuf_Buf *buf)
 {
-       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;
-
-               /* Still have something left?? */
-               if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
-                       sock_errset(EAGAIN);
-                       return -1;
-               }
-       }
-
-       /* now encode the next packet. */
 #if SASL_VERSION_MAJOR >= 2
-       ber_pvt_sb_buf_init( &p->buf_out );
+       ber_pvt_sb_buf_init( buf );
 #else
-       ber_pvt_sb_buf_destroy( &p->buf_out );
+       ber_pvt_sb_buf_destroy( buf );
 #endif
-       if ( len > *p->sasl_maxbuf - 100 ) {
-               len = *p->sasl_maxbuf - 100;    /* For safety margin */
-       }
-
-       {
-               unsigned tmpsize = p->buf_out.buf_size;
-               ret = sasl_encode( p->sasl_context, buf, len,
-                       (SASL_CONST char **)&p->buf_out.buf_base,
-                       &tmpsize );
-               p->buf_out.buf_size = tmpsize;
-       }
-
-       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 ) );
-               sock_errset(EIO);
-               return -1;
-       }
-       p->buf_out.buf_end = p->buf_out.buf_size;
-
-       ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
-
-       /* return number of bytes encoded, not written, to ensure
-        * no byte is encoded twice (even if only sent once).
-        */
-       return len;
 }
 
-static int
-sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+static void
+sb_sasl_cyrus_fini(
+       struct sb_sasl_generic_data *p)
 {
-       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 );
+#if SASL_VERSION_MAJOR >= 2
+       /*
+        * SASLv2 encode/decode buffers are managed by
+        * libsasl2. Ensure they are not freed by liblber.
+        */
+       p->buf_in.buf_base = NULL;
+       p->buf_out.buf_base = NULL;
+#endif
 }
 
-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 */
-};
+static const struct sb_sasl_generic_ops sb_sasl_cyrus_ops = {
+       sb_sasl_cyrus_init,
+       sb_sasl_cyrus_encode,
+       sb_sasl_cyrus_decode,
+       sb_sasl_cyrus_reset_buf,
+       sb_sasl_cyrus_fini
+ };
 
 int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
 {
-       Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n",
-               0, 0, 0 );
+       struct sb_sasl_generic_install install_arg;
 
-       /* don't install the stuff unless security has been negotiated */
+       install_arg.ops         = &sb_sasl_cyrus_ops;
+       install_arg.ops_private = ctx_arg;
 
-       if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
-                       &ldap_pvt_sockbuf_io_sasl ) )
-       {
-#ifdef LDAP_DEBUG
-               ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
-                       LBER_SBIOD_LEVEL_APPLICATION, (void *)"sasl_" );
-#endif
-               ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
-                       LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
-       }
-
-       return LDAP_SUCCESS;
+       return ldap_pvt_sasl_generic_install( sb, &install_arg );
 }
 
 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
+       ldap_pvt_sasl_generic_remove( sb );
 }
 
 static int
@@ -1126,7 +933,7 @@ ldap_int_sasl_get_option( LDAP *ld, int option, void *arg )
        if ( option == LDAP_OPT_X_SASL_MECHLIST ) {
                if ( ldap_int_sasl_init() )
                        return -1;
-               *(char ***)arg = sasl_global_listmech();
+               *(char ***)arg = (char **)sasl_global_listmech();
                return 0;
        }
 
index 13daaaf1aae1e89d69e96bc6d99c65e8c18fc897..4109b7eb7490b544e23983d5033e94fa9390f5cd 100644 (file)
@@ -47,6 +47,8 @@ struct ldapoptions ldap_int_global_options =
 #define ATTR_OPT_TV    8
 #define ATTR_OPT_INT   9
 
+#define ATTR_GSSAPI    10
+
 struct ol_keyvalue {
        const char *            key;
        int                     value;
@@ -102,6 +104,12 @@ static const struct ol_attribute {
        {0, ATTR_SASL,          "SASL_SECPROPS",        NULL,   LDAP_OPT_X_SASL_SECPROPS},
 #endif
 
+#ifdef HAVE_GSSAPI
+       {0, ATTR_GSSAPI,"GSSAPI_SIGN",                  NULL,   LDAP_OPT_SIGN},
+       {0, ATTR_GSSAPI,"GSSAPI_ENCRYPT",               NULL,   LDAP_OPT_ENCRYPT},
+       {0, ATTR_GSSAPI,"GSSAPI_ALLOW_REMOTE_PRINCIPAL",NULL,   LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL},
+#endif
+
 #ifdef HAVE_TLS
        {1, ATTR_TLS,   "TLS_CERT",                     NULL,   LDAP_OPT_X_TLS_CERTFILE},
        {1, ATTR_TLS,   "TLS_KEY",                      NULL,   LDAP_OPT_X_TLS_KEYFILE},
@@ -123,7 +131,7 @@ static const struct ol_attribute {
        {0, ATTR_NONE,          NULL,           NULL,   0}
 };
 
-#define MAX_LDAP_ATTR_LEN  sizeof("TLS_CIPHER_SUITE")
+#define MAX_LDAP_ATTR_LEN  sizeof("GSSAPI_ALLOW_REMOTE_PRINCIPAL")
 #define MAX_LDAP_ENV_PREFIX_LEN 8
 
 static void openldap_ldap_init_w_conf(
@@ -252,6 +260,11 @@ static void openldap_ldap_init_w_conf(
                        case ATTR_SASL:
 #ifdef HAVE_CYRUS_SASL
                                ldap_int_sasl_config( gopts, attrs[i].offset, opt );
+#endif
+                               break;
+                       case ATTR_GSSAPI:
+#ifdef HAVE_GSSAPI
+                               ldap_int_gssapi_config( gopts, attrs[i].offset, opt );
 #endif
                                break;
                        case ATTR_TLS:
index e9e1921de460356c227439907e6029afa5b2061f..0ec5600724868649a4406dc791eb461533cdf63e 100644 (file)
@@ -228,6 +228,15 @@ struct ldapoptions {
        struct sasl_security_properties ldo_sasl_secprops;
 #endif
 
+#ifdef HAVE_GSSAPI
+       unsigned gssapi_flags;
+
+       unsigned ldo_gssapi_flags;
+#define LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT        0x0001
+#define LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL 0x0002
+       unsigned ldo_gssapi_options;
+#endif
+
        int             ldo_refhoplimit;        /* limit on referral nesting */
 
        /* LDAPv3 server and client controls */
@@ -257,6 +266,9 @@ typedef struct ldap_conn {
 #ifdef HAVE_CYRUS_SASL
        void            *lconn_sasl_authctx;    /* context for bind */
        void            *lconn_sasl_sockctx;    /* for security layer */
+#endif
+#ifdef HAVE_GSSAPI
+       void            *lconn_gss_ctx;         /* gss_ctx_id_t */
 #endif
        int                     lconn_refcnt;
        time_t          lconn_created;  /* time */
@@ -402,6 +414,9 @@ LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex;
 #ifdef HAVE_CYRUS_SASL
 LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_sasl_mutex;
 #endif
+#ifdef HAVE_GSSAPI
+LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_gssapi_mutex;
+#endif
 #endif
 
 #ifdef LDAP_R_COMPILE
index 8903c61404025b1f57cf8137febb94115df5ec89..329047143100d217e65b86d92375d97f974727fb 100644 (file)
@@ -353,6 +353,11 @@ ldap_get_option(
                if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
                        return LDAP_OPT_SUCCESS;
                }
+#endif
+#ifdef HAVE_GSSAPI
+               if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
+                       return LDAP_OPT_SUCCESS;
+               }
 #endif
                /* bad param */
                break;
@@ -690,6 +695,10 @@ ldap_set_option(
 #ifdef HAVE_CYRUS_SASL
                if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
                        return LDAP_OPT_SUCCESS;
+#endif
+#ifdef HAVE_GSSAPI
+               if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 )
+                       return LDAP_OPT_SUCCESS;
 #endif
                /* bad param */
                return LDAP_OPT_ERROR;
index b5beacf2529c04bf099e557219a7c345974862d6..4092b742facd7a275b85e2edb8035a9a33a30735 100644 (file)
@@ -207,7 +207,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
                == AC_SOCKET_ERROR )
        {
                /* XXX: needs to be replace with ber_stream_read() */
-               read(s, &ch, 1);
+               int rc = read(s, &ch, 1);
                TRACE;
                return -1;
        }
index 047151e626b31ff00158fa16b425d0a1164f64aa..486d590f3cde70ebf6b9bfd345d15dc30d18b9cd 100644 (file)
@@ -149,7 +149,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
                == AC_SOCKET_ERROR )
        {
                /* XXX: needs to be replace with ber_stream_read() */
-               read(s, &ch, 1);
+               int rc = read(s, &ch, 1);
                TRACE;
                return -1;
        }
index a7784771dc22c9234775e3d5b103ea0f49f89d5e..80304118869b0b64cfff412960bf7d2226082b15 100644 (file)
@@ -736,6 +736,9 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
                }
 
                ldap_int_sasl_close( ld, lc );
+#ifdef HAVE_GSSAPI
+               ldap_int_gssapi_close( ld, lc );
+#endif
 
                ldap_free_urllist( lc->lconn_server );
 
index d58d2c5d9e42e7f939c9e648e25c7b17c44fe6e3..1764eabe121c6b4511550195148ee4ae2373a7da 100644 (file)
@@ -473,3 +473,311 @@ done:
 
        return rc;
 }
+
+#ifdef HAVE_CYRUS_SASL
+
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#else
+#include <sasl.h>
+#endif
+
+#if SASL_VERSION_MAJOR >= 2
+#define SASL_CONST const
+#else
+#define SASL_CONST
+#endif
+
+#endif /* HAVE_CYRUS_SASL */
+
+static int
+sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod );
+
+static int
+sb_sasl_generic_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+       struct sb_sasl_generic_data     *p;
+       struct sb_sasl_generic_install  *i;
+
+       assert( sbiod != NULL );
+
+       i = (struct sb_sasl_generic_install *)arg;
+
+       p = LBER_MALLOC( sizeof( *p ) );
+       if ( p == NULL )
+               return -1;
+       p->ops = i->ops;
+       p->ops_private = i->ops_private;
+       p->sbiod = sbiod;
+       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 );
+
+       sbiod->sbiod_pvt = p;
+
+       p->ops->init( p, &p->min_send, &p->max_send, &p->max_recv );
+
+       if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, p->min_send ) < 0 ) {
+               sb_sasl_generic_remove( sbiod );
+               sock_errset(ENOMEM);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+sb_sasl_generic_remove( Sockbuf_IO_Desc *sbiod )
+{
+       struct sb_sasl_generic_data     *p;
+
+       assert( sbiod != NULL );
+
+       p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt;
+
+       p->ops->fini(p);
+
+       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_generic_pkt_length(
+       struct sb_sasl_generic_data *p,
+       const unsigned char *buf,
+       int debuglevel )
+{
+       ber_len_t               size;
+
+       assert( buf != NULL );
+
+       size = buf[0] << 24
+               | buf[1] << 16
+               | buf[2] << 8
+               | buf[3];
+
+       if ( size > p->max_recv ) {
+               /* somebody is trying to mess me up. */
+               ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
+                       "sb_sasl_generic_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_generic_drop_packet (
+       struct sb_sasl_generic_data *p,
+       int debuglevel )
+{
+       ber_slen_t                      len;
+
+       len = p->sec_buf_in.buf_ptr - p->sec_buf_in.buf_end;
+       if ( len > 0 )
+               AC_MEMCPY( p->sec_buf_in.buf_base, p->sec_buf_in.buf_base +
+                       p->sec_buf_in.buf_end, len );
+
+       if ( len >= 4 ) {
+               p->sec_buf_in.buf_end = sb_sasl_generic_pkt_length(p,
+                       (unsigned char *) p->sec_buf_in.buf_base, debuglevel);
+       }
+       else {
+               p->sec_buf_in.buf_end = 0;
+       }
+       p->sec_buf_in.buf_ptr = len;
+}
+
+static ber_slen_t
+sb_sasl_generic_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct sb_sasl_generic_data     *p;
+       ber_slen_t                      ret, bufptr;
+
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct sb_sasl_generic_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;
+
+       p->ops->reset_buf( p, &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 +
+                       p->sec_buf_in.buf_ptr,
+                       4 - p->sec_buf_in.buf_ptr );
+#ifdef EINTR
+               if ( ( ret < 0 ) && ( errno == EINTR ) )
+                       continue;
+#endif
+               if ( ret <= 0 )
+                       return bufptr ? bufptr : ret;
+
+               p->sec_buf_in.buf_ptr += ret;
+       }
+
+       /* The new packet always starts at p->sec_buf_in.buf_base */
+       ret = sb_sasl_generic_pkt_length(p, (unsigned char *) p->sec_buf_in.buf_base,
+               sbiod->sbiod_sb->sb_debug );
+
+       /* Grow the packet buffer if neccessary */
+       if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) && 
+               ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 )
+       {
+               sock_errset(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 bufptr ? bufptr : ret;
+
+               p->sec_buf_in.buf_ptr += ret;
+       }
+
+       /* Decode the packet */
+       ret = p->ops->decode( p, &p->sec_buf_in, &p->buf_in );
+
+       /* Drop the packet from the input buffer */
+       sb_sasl_generic_drop_packet( p, sbiod->sbiod_sb->sb_debug );
+
+       if ( ret != 0 ) {
+               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+                       "sb_sasl_generic_read: failed to decode packet\n" );
+               sock_errset(EIO);
+               return -1;
+       }
+
+       bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
+
+       return bufptr;
+}
+
+static ber_slen_t
+sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+       struct sb_sasl_generic_data     *p;
+       int                             ret;
+
+       assert( sbiod != NULL );
+       assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+       p = (struct sb_sasl_generic_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;
+
+               /* Still have something left?? */
+               if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
+                       sock_errset(EAGAIN);
+                       return -1;
+               }
+       }
+
+       /* now encode the next packet. */
+       p->ops->reset_buf( p, &p->buf_out );
+
+       if ( len > p->max_send - 100 ) {
+               len = p->max_send - 100;        /* For safety margin */
+       }
+
+       ret = p->ops->encode( p, buf, len, &p->buf_out );
+
+       if ( ret != 0 ) {
+               ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+                       "sb_sasl_generic_write: failed to encode packet\n" );
+               sock_errset(EIO);
+               return -1;
+       }
+
+       ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
+
+       /* return number of bytes encoded, not written, to ensure
+        * no byte is encoded twice (even if only sent once).
+        */
+       return len;
+}
+
+static int
+sb_sasl_generic_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+       struct sb_sasl_generic_data     *p;
+
+       p = (struct sb_sasl_generic_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_generic = {
+       sb_sasl_generic_setup,          /* sbi_setup */
+       sb_sasl_generic_remove,         /* sbi_remove */
+       sb_sasl_generic_ctrl,           /* sbi_ctrl */
+       sb_sasl_generic_read,           /* sbi_read */
+       sb_sasl_generic_write,          /* sbi_write */
+       NULL                    /* sbi_close */
+};
+
+int ldap_pvt_sasl_generic_install(
+       Sockbuf *sb,
+       struct sb_sasl_generic_install *install_arg )
+{
+       Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_generic_install\n",
+               0, 0, 0 );
+
+       /* don't install the stuff unless security has been negotiated */
+
+       if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
+                       &ldap_pvt_sockbuf_io_sasl_generic ) )
+       {
+#ifdef LDAP_DEBUG
+               ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
+                       LBER_SBIOD_LEVEL_APPLICATION, (void *)"sasl_generic_" );
+#endif
+               ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl_generic,
+                       LBER_SBIOD_LEVEL_APPLICATION, install_arg );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+void ldap_pvt_sasl_generic_remove( Sockbuf *sb )
+{
+       ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_sasl_generic,
+               LBER_SBIOD_LEVEL_APPLICATION );
+#ifdef LDAP_DEBUG
+       ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
+               LBER_SBIOD_LEVEL_APPLICATION );
+#endif
+}
index 1ce1dbf43bfa449ec7f6b78624579a5ff68d40b7..65eae574225690791da9ab46f5754ca405b21afd 100644 (file)
@@ -411,6 +411,9 @@ void ldap_int_utils_init( void )
 #ifdef HAVE_CYRUS_SASL
        ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex );
 #endif
+#ifdef HAVE_GSSAPI
+       ldap_pvt_thread_mutex_init( &ldap_int_gssapi_mutex );
+#endif
 #endif
 
        /* call other module init functions here... */
index 03b99d419764327425b979e1026062eeab5655f3..0d6cf22efe769983c7e86f4b749e653f66244d39 100644 (file)
@@ -22,7 +22,7 @@ XXSRCS    = apitest.c test.c \
        bind.c open.c result.c error.c compare.c search.c \
        controls.c messages.c references.c extended.c cyrus.c \
        modify.c add.c modrdn.c delete.c abandon.c \
-       sasl.c sbind.c unbind.c cancel.c \
+       sasl.c gssapi.c sbind.c unbind.c cancel.c \
        filter.c free.c sort.c passwd.c whoami.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
        request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \
@@ -39,7 +39,7 @@ OBJS  = threads.lo rdwr.lo rmutex.lo tpool.lo  rq.lo \
        bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo cyrus.lo \
        modify.lo add.lo modrdn.lo delete.lo abandon.lo \
-       sasl.lo sbind.lo unbind.lo cancel.lo \
+       sasl.lo gssapi.lo sbind.lo unbind.lo cancel.lo \
        filter.lo free.lo sort.lo passwd.lo whoami.lo \
        getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
        request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \