mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
ITS#5369 SASL/GSSAPi refactoring from Stefan Metzmacher <metze@samba.org>
and Rafal Szczeniak <mimir@samba.org>, with minor cleanups
This commit is contained in:
parent
b2432fdbf2
commit
f7484f78e6
18 changed files with 607 additions and 295 deletions
|
|
@ -186,9 +186,10 @@ KRB4_LIBS = @KRB4_LIBS@
|
||||||
KRB5_LIBS = @KRB5_LIBS@
|
KRB5_LIBS = @KRB5_LIBS@
|
||||||
KRB_LIBS = @KRB4_LIBS@ @KRB5_LIBS@
|
KRB_LIBS = @KRB4_LIBS@ @KRB5_LIBS@
|
||||||
SASL_LIBS = @SASL_LIBS@
|
SASL_LIBS = @SASL_LIBS@
|
||||||
|
GSSAPI_LIBS = @GSSAPI_LIBS@
|
||||||
TLS_LIBS = @TLS_LIBS@
|
TLS_LIBS = @TLS_LIBS@
|
||||||
AUTH_LIBS = @AUTH_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@
|
ICU_LIBS = @ICU_LIBS@
|
||||||
|
|
||||||
MODULES_CPPFLAGS = @SLAPD_MODULES_CPPFLAGS@
|
MODULES_CPPFLAGS = @SLAPD_MODULES_CPPFLAGS@
|
||||||
|
|
|
||||||
56
configure.in
56
configure.in
|
|
@ -242,6 +242,8 @@ OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support],
|
||||||
auto, [auto yes no] )
|
auto, [auto yes no] )
|
||||||
OL_ARG_WITH(fetch,[ --with-fetch with fetch(3) URL support],
|
OL_ARG_WITH(fetch,[ --with-fetch with fetch(3) URL support],
|
||||||
auto, [auto yes no] )
|
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],
|
OL_ARG_WITH(threads,[ --with-threads with threads],
|
||||||
auto, [auto nt posix mach pth lwp yes no manual] )
|
auto, [auto nt posix mach pth lwp yes no manual] )
|
||||||
OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support auto|openssl|gnutls],
|
OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support auto|openssl|gnutls],
|
||||||
|
|
@ -576,6 +578,7 @@ SLAPD_SQL_INCLUDES=
|
||||||
KRB4_LIBS=
|
KRB4_LIBS=
|
||||||
KRB5_LIBS=
|
KRB5_LIBS=
|
||||||
SASL_LIBS=
|
SASL_LIBS=
|
||||||
|
GSSAPI_LIBS=
|
||||||
TLS_LIBS=
|
TLS_LIBS=
|
||||||
MODULES_LIBS=
|
MODULES_LIBS=
|
||||||
SLAPI_LIBS=
|
SLAPI_LIBS=
|
||||||
|
|
@ -1120,6 +1123,58 @@ if test $ol_enable_local != no ; then
|
||||||
fi
|
fi
|
||||||
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 ----------------------------------------------------------------
|
||||||
dnl TLS/SSL
|
dnl TLS/SSL
|
||||||
|
|
||||||
|
|
@ -3048,6 +3103,7 @@ AC_SUBST(MOD_PERL_LDFLAGS)
|
||||||
AC_SUBST(KRB4_LIBS)
|
AC_SUBST(KRB4_LIBS)
|
||||||
AC_SUBST(KRB5_LIBS)
|
AC_SUBST(KRB5_LIBS)
|
||||||
AC_SUBST(SASL_LIBS)
|
AC_SUBST(SASL_LIBS)
|
||||||
|
AC_SUBST(GSSAPI_LIBS)
|
||||||
AC_SUBST(TLS_LIBS)
|
AC_SUBST(TLS_LIBS)
|
||||||
AC_SUBST(MODULES_LIBS)
|
AC_SUBST(MODULES_LIBS)
|
||||||
AC_SUBST(SLAPI_LIBS)
|
AC_SUBST(SLAPI_LIBS)
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,22 @@ description). The default is
|
||||||
specifies the maximum security layer receive buffer
|
specifies the maximum security layer receive buffer
|
||||||
size allowed. 0 disables security layers. The default is 65536.
|
size allowed. 0 disables security layers. The default is 65536.
|
||||||
.RE
|
.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
|
.SH TLS OPTIONS
|
||||||
If OpenLDAP is built with Transport Layer Security support, there
|
If OpenLDAP is built with Transport Layer Security support, there
|
||||||
are more options you can specify. These options are used when an
|
are more options you can specify. These options are used when an
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,17 @@ LDAP_BEGIN_DECL
|
||||||
#define LDAP_OPT_ERROR_STRING LDAP_OPT_DIAGNOSTIC_MESSAGE
|
#define LDAP_OPT_ERROR_STRING LDAP_OPT_DIAGNOSTIC_MESSAGE
|
||||||
#define LDAP_OPT_MATCHED_DN 0x0033
|
#define LDAP_OPT_MATCHED_DN 0x0033
|
||||||
/* 0x0034 - 0x3fff not defined */
|
/* 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 */
|
/* API Extensions */
|
||||||
#define LDAP_OPT_API_EXTENSION_BASE 0x4000 /* 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_MAXBUFSIZE 0x6109
|
||||||
#define LDAP_OPT_X_SASL_MECHLIST 0x610a /* read-only */
|
#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 */
|
/* Private API Extensions -- reserved for application use */
|
||||||
#define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x7000 /* Private API inclusive */
|
#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_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */
|
||||||
#define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* 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 */
|
/* filter types */
|
||||||
#define LDAP_FILTER_AND ((ber_tag_t) 0xa0U) /* context specific + constructed */
|
#define LDAP_FILTER_AND ((ber_tag_t) 0xa0U) /* context specific + constructed */
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#define _LDAP_PVT_H 1
|
#define _LDAP_PVT_H 1
|
||||||
|
|
||||||
#include <lber.h> /* get ber_slen_t */
|
#include <lber.h> /* get ber_slen_t */
|
||||||
|
#include <lber_pvt.h> /* get Sockbuf_Buf */
|
||||||
|
|
||||||
LDAP_BEGIN_DECL
|
LDAP_BEGIN_DECL
|
||||||
|
|
||||||
|
|
@ -217,11 +218,51 @@ 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_lock LDAP_P((void *mutex));
|
||||||
LDAP_F (int) ldap_pvt_sasl_mutex_unlock 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));
|
LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex));
|
||||||
|
#endif /* HAVE_CYRUS_SASL */
|
||||||
|
|
||||||
struct sockbuf; /* avoid pulling in <lber.h> */
|
struct sockbuf; /* avoid pulling in <lber.h> */
|
||||||
LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * ));
|
LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * ));
|
||||||
LDAP_F (void) ldap_pvt_sasl_remove LDAP_P(( struct sockbuf * ));
|
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
|
#ifndef LDAP_PVT_SASL_LOCAL_SSF
|
||||||
#define LDAP_PVT_SASL_LOCAL_SSF 71 /* SSF for Unix Domain Sockets */
|
#define LDAP_PVT_SASL_LOCAL_SSF 71 /* SSF for Unix Domain Sockets */
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,18 @@
|
||||||
/* Define to 1 if you have the <grp.h> header file. */
|
/* Define to 1 if you have the <grp.h> header file. */
|
||||||
#undef HAVE_GRP_H
|
#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. */
|
/* Define to 1 if you have the `hstrerror' function. */
|
||||||
#undef HAVE_HSTRERROR
|
#undef HAVE_HSTRERROR
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ PROGRAMS = apitest dntest ftest ltest urltest
|
||||||
SRCS = bind.c open.c result.c error.c compare.c search.c \
|
SRCS = bind.c open.c result.c error.c compare.c search.c \
|
||||||
controls.c messages.c references.c extended.c cyrus.c \
|
controls.c messages.c references.c extended.c cyrus.c \
|
||||||
modify.c add.c modrdn.c delete.c abandon.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 \
|
filter.c free.c sort.c passwd.c whoami.c \
|
||||||
getdn.c getentry.c getattr.c getvalues.c addentry.c \
|
getdn.c getentry.c getattr.c getvalues.c addentry.c \
|
||||||
request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.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 \
|
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
||||||
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
||||||
modify.lo add.lo modrdn.lo delete.lo abandon.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 \
|
filter.lo free.lo sort.lo passwd.lo whoami.lo \
|
||||||
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
|
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
|
||||||
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
|
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,11 @@ ldap_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *passwd, int authmetho
|
||||||
case LDAP_AUTH_SIMPLE:
|
case LDAP_AUTH_SIMPLE:
|
||||||
return( ldap_simple_bind( ld, dn, passwd ) );
|
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:
|
case LDAP_AUTH_SASL:
|
||||||
/* user must use ldap_sasl_bind */
|
/* user must use ldap_sasl_bind */
|
||||||
/* FALL-THRU */
|
/* FALL-THRU */
|
||||||
|
|
@ -107,6 +112,11 @@ ldap_bind_s(
|
||||||
case LDAP_AUTH_SIMPLE:
|
case LDAP_AUTH_SIMPLE:
|
||||||
return( ldap_simple_bind_s( ld, dn, passwd ) );
|
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:
|
case LDAP_AUTH_SASL:
|
||||||
/* user must use ldap_sasl_bind */
|
/* user must use ldap_sasl_bind */
|
||||||
/* FALL-THRU */
|
/* FALL-THRU */
|
||||||
|
|
|
||||||
|
|
@ -133,53 +133,97 @@ int ldap_int_sasl_init( void )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* SASL encryption support for LBER Sockbufs
|
sb_sasl_cyrus_init(
|
||||||
*/
|
struct sb_sasl_generic_data *p,
|
||||||
|
ber_len_t *min_send,
|
||||||
struct sb_sasl_data {
|
ber_len_t *max_send,
|
||||||
sasl_conn_t *sasl_context;
|
ber_len_t *max_recv)
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
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 ) );
|
*min_send = SASL_MIN_BUFF_SIZE;
|
||||||
if ( p == NULL )
|
*max_send = maxbuf;
|
||||||
return -1;
|
*max_recv = SASL_MAX_BUFF_SIZE;
|
||||||
p->sasl_context = (sasl_conn_t *)arg;
|
}
|
||||||
ber_pvt_sb_buf_init( &p->sec_buf_in );
|
|
||||||
ber_pvt_sb_buf_init( &p->buf_in );
|
static ber_int_t
|
||||||
ber_pvt_sb_buf_init( &p->buf_out );
|
sb_sasl_cyrus_encode(
|
||||||
if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, SASL_MIN_BUFF_SIZE ) < 0 ) {
|
struct sb_sasl_generic_data *p,
|
||||||
LBER_FREE( p );
|
unsigned char *buf,
|
||||||
sock_errset(ENOMEM);
|
ber_len_t len,
|
||||||
|
Sockbuf_Buf *dst)
|
||||||
|
{
|
||||||
|
sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private;
|
||||||
|
ber_int_t ret;
|
||||||
|
unsigned tmpsize = dst->buf_size;
|
||||||
|
|
||||||
|
ret = sasl_encode( sasl_context, buf, len,
|
||||||
|
(SASL_CONST char **)&dst->buf_base,
|
||||||
|
&tmpsize );
|
||||||
|
|
||||||
|
dst->buf_size = tmpsize;
|
||||||
|
dst->buf_end = dst->buf_size;
|
||||||
|
|
||||||
|
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 -1;
|
||||||
}
|
}
|
||||||
sasl_getprop( p->sasl_context, SASL_MAXOUTBUF,
|
|
||||||
(SASL_CONST void **)(char *) &p->sasl_maxbuf );
|
|
||||||
|
|
||||||
sbiod->sbiod_pvt = p;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static ber_int_t
|
||||||
sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
|
sb_sasl_cyrus_decode(
|
||||||
|
struct sb_sasl_generic_data *p,
|
||||||
|
const Sockbuf_Buf *src,
|
||||||
|
Sockbuf_Buf *dst)
|
||||||
{
|
{
|
||||||
struct sb_sasl_data *p;
|
sasl_conn_t *sasl_context = (sasl_conn_t *)p->ops_private;
|
||||||
|
ber_int_t ret;
|
||||||
|
unsigned tmpsize = dst->buf_size;
|
||||||
|
|
||||||
assert( sbiod != NULL );
|
ret = sasl_decode( sasl_context,
|
||||||
|
src->buf_base, src->buf_end,
|
||||||
|
(SASL_CONST char **)&dst->buf_base,
|
||||||
|
(unsigned *)&tmpsize );
|
||||||
|
|
||||||
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
|
|
||||||
|
dst->buf_size = tmpsize;
|
||||||
|
dst->buf_end = dst->buf_size;
|
||||||
|
|
||||||
|
if ( ret != SASL_OK ) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sb_sasl_cyrus_reset_buf(
|
||||||
|
struct sb_sasl_generic_data *p,
|
||||||
|
Sockbuf_Buf *buf)
|
||||||
|
{
|
||||||
|
#if SASL_VERSION_MAJOR >= 2
|
||||||
|
ber_pvt_sb_buf_init( buf );
|
||||||
|
#else
|
||||||
|
ber_pvt_sb_buf_destroy( buf );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sb_sasl_cyrus_fini(
|
||||||
|
struct sb_sasl_generic_data *p)
|
||||||
|
{
|
||||||
#if SASL_VERSION_MAJOR >= 2
|
#if SASL_VERSION_MAJOR >= 2
|
||||||
/*
|
/*
|
||||||
* SASLv2 encode/decode buffers are managed by
|
* SASLv2 encode/decode buffers are managed by
|
||||||
|
|
@ -188,266 +232,29 @@ sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
|
||||||
p->buf_in.buf_base = NULL;
|
p->buf_in.buf_base = NULL;
|
||||||
p->buf_out.buf_base = NULL;
|
p->buf_out.buf_base = NULL;
|
||||||
#endif
|
#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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ber_len_t
|
static const struct sb_sasl_generic_ops sb_sasl_cyrus_ops = {
|
||||||
sb_sasl_pkt_length( const unsigned char *buf, int debuglevel )
|
sb_sasl_cyrus_init,
|
||||||
{
|
sb_sasl_cyrus_encode,
|
||||||
ber_len_t size;
|
sb_sasl_cyrus_decode,
|
||||||
|
sb_sasl_cyrus_reset_buf,
|
||||||
assert( buf != NULL );
|
sb_sasl_cyrus_fini
|
||||||
|
};
|
||||||
size = buf[0] << 24
|
|
||||||
| buf[1] << 16
|
|
||||||
| buf[2] << 8
|
|
||||||
| buf[3];
|
|
||||||
|
|
||||||
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. */
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#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 );
|
|
||||||
|
|
||||||
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);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* 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 );
|
|
||||||
#else
|
|
||||||
ber_pvt_sb_buf_destroy( &p->buf_out );
|
|
||||||
#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 )
|
|
||||||
{
|
|
||||||
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 )
|
int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
|
||||||
{
|
{
|
||||||
Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n",
|
struct sb_sasl_generic_install install_arg;
|
||||||
0, 0, 0 );
|
|
||||||
|
|
||||||
/* 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,
|
return ldap_pvt_sasl_generic_install( sb, &install_arg );
|
||||||
&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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ldap_pvt_sasl_remove( Sockbuf *sb )
|
void ldap_pvt_sasl_remove( Sockbuf *sb )
|
||||||
{
|
{
|
||||||
ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_sasl,
|
ldap_pvt_sasl_generic_remove( sb );
|
||||||
LBER_SBIOD_LEVEL_APPLICATION );
|
|
||||||
#ifdef LDAP_DEBUG
|
|
||||||
ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
|
|
||||||
LBER_SBIOD_LEVEL_APPLICATION );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 ( option == LDAP_OPT_X_SASL_MECHLIST ) {
|
||||||
if ( ldap_int_sasl_init() )
|
if ( ldap_int_sasl_init() )
|
||||||
return -1;
|
return -1;
|
||||||
*(char ***)arg = sasl_global_listmech();
|
*(char ***)arg = (char **)sasl_global_listmech();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ struct ldapoptions ldap_int_global_options =
|
||||||
#define ATTR_OPT_TV 8
|
#define ATTR_OPT_TV 8
|
||||||
#define ATTR_OPT_INT 9
|
#define ATTR_OPT_INT 9
|
||||||
|
|
||||||
|
#define ATTR_GSSAPI 10
|
||||||
|
|
||||||
struct ol_keyvalue {
|
struct ol_keyvalue {
|
||||||
const char * key;
|
const char * key;
|
||||||
int value;
|
int value;
|
||||||
|
|
@ -102,6 +104,12 @@ static const struct ol_attribute {
|
||||||
{0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS},
|
{0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS},
|
||||||
#endif
|
#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
|
#ifdef HAVE_TLS
|
||||||
{1, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE},
|
{1, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE},
|
||||||
{1, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE},
|
{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}
|
{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
|
#define MAX_LDAP_ENV_PREFIX_LEN 8
|
||||||
|
|
||||||
static void openldap_ldap_init_w_conf(
|
static void openldap_ldap_init_w_conf(
|
||||||
|
|
@ -252,6 +260,11 @@ static void openldap_ldap_init_w_conf(
|
||||||
case ATTR_SASL:
|
case ATTR_SASL:
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
ldap_int_sasl_config( gopts, attrs[i].offset, opt );
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
case ATTR_TLS:
|
case ATTR_TLS:
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,15 @@ struct ldapoptions {
|
||||||
struct sasl_security_properties ldo_sasl_secprops;
|
struct sasl_security_properties ldo_sasl_secprops;
|
||||||
#endif
|
#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 */
|
int ldo_refhoplimit; /* limit on referral nesting */
|
||||||
|
|
||||||
/* LDAPv3 server and client controls */
|
/* LDAPv3 server and client controls */
|
||||||
|
|
@ -257,6 +266,9 @@ typedef struct ldap_conn {
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
void *lconn_sasl_authctx; /* context for bind */
|
void *lconn_sasl_authctx; /* context for bind */
|
||||||
void *lconn_sasl_sockctx; /* for security layer */
|
void *lconn_sasl_sockctx; /* for security layer */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
void *lconn_gss_ctx; /* gss_ctx_id_t */
|
||||||
#endif
|
#endif
|
||||||
int lconn_refcnt;
|
int lconn_refcnt;
|
||||||
time_t lconn_created; /* time */
|
time_t lconn_created; /* time */
|
||||||
|
|
@ -402,6 +414,9 @@ LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex;
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_sasl_mutex;
|
LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_sasl_mutex;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_gssapi_mutex;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LDAP_R_COMPILE
|
#ifdef LDAP_R_COMPILE
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,11 @@ ldap_get_option(
|
||||||
if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
|
if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
|
||||||
return LDAP_OPT_SUCCESS;
|
return LDAP_OPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
|
||||||
|
return LDAP_OPT_SUCCESS;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* bad param */
|
/* bad param */
|
||||||
break;
|
break;
|
||||||
|
|
@ -690,6 +695,10 @@ ldap_set_option(
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
|
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
|
||||||
return LDAP_OPT_SUCCESS;
|
return LDAP_OPT_SUCCESS;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 )
|
||||||
|
return LDAP_OPT_SUCCESS;
|
||||||
#endif
|
#endif
|
||||||
/* bad param */
|
/* bad param */
|
||||||
return LDAP_OPT_ERROR;
|
return LDAP_OPT_ERROR;
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
|
||||||
== AC_SOCKET_ERROR )
|
== AC_SOCKET_ERROR )
|
||||||
{
|
{
|
||||||
/* XXX: needs to be replace with ber_stream_read() */
|
/* XXX: needs to be replace with ber_stream_read() */
|
||||||
read(s, &ch, 1);
|
int rc = read(s, &ch, 1);
|
||||||
TRACE;
|
TRACE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
|
||||||
== AC_SOCKET_ERROR )
|
== AC_SOCKET_ERROR )
|
||||||
{
|
{
|
||||||
/* XXX: needs to be replace with ber_stream_read() */
|
/* XXX: needs to be replace with ber_stream_read() */
|
||||||
read(s, &ch, 1);
|
int rc = read(s, &ch, 1);
|
||||||
TRACE;
|
TRACE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -736,6 +736,9 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_int_sasl_close( ld, lc );
|
ldap_int_sasl_close( ld, lc );
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
ldap_int_gssapi_close( ld, lc );
|
||||||
|
#endif
|
||||||
|
|
||||||
ldap_free_urllist( lc->lconn_server );
|
ldap_free_urllist( lc->lconn_server );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -473,3 +473,311 @@ done:
|
||||||
|
|
||||||
return rc;
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,9 @@ void ldap_int_utils_init( void )
|
||||||
#ifdef HAVE_CYRUS_SASL
|
#ifdef HAVE_CYRUS_SASL
|
||||||
ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex );
|
ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex );
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
ldap_pvt_thread_mutex_init( &ldap_int_gssapi_mutex );
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* call other module init functions here... */
|
/* call other module init functions here... */
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ XXSRCS = apitest.c test.c \
|
||||||
bind.c open.c result.c error.c compare.c search.c \
|
bind.c open.c result.c error.c compare.c search.c \
|
||||||
controls.c messages.c references.c extended.c cyrus.c \
|
controls.c messages.c references.c extended.c cyrus.c \
|
||||||
modify.c add.c modrdn.c delete.c abandon.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 \
|
filter.c free.c sort.c passwd.c whoami.c \
|
||||||
getdn.c getentry.c getattr.c getvalues.c addentry.c \
|
getdn.c getentry.c getattr.c getvalues.c addentry.c \
|
||||||
request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.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 \
|
bind.lo open.lo result.lo error.lo compare.lo search.lo \
|
||||||
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
controls.lo messages.lo references.lo extended.lo cyrus.lo \
|
||||||
modify.lo add.lo modrdn.lo delete.lo abandon.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 \
|
filter.lo free.lo sort.lo passwd.lo whoami.lo \
|
||||||
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
|
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
|
||||||
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
|
request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue