--enable-referrals enable V2 Referrals extension (yes)"
ac_help="$ac_help
--enable-cldap enable connectionless ldap (no)"
+ac_help="$ac_help
+ --enable-ldapi enable domain socket (PF_LOCAL) transport (no)"
ac_help="$ac_help
--enable-x-compile enable cross compiling (no)"
ac_help="$ac_help
ol_enable_cldap="no"
fi
# end --enable-cldap
+# OpenLDAP --enable-ldapi
+ # Check whether --enable-ldapi or --disable-ldapi was given.
+if test "${enable_ldapi+set}" = set; then
+ enableval="$enable_ldapi"
+
+ ol_arg=invalid
+ for ol_val in auto yes no ; do
+ if test "$enableval" = "$ol_val" ; then
+ ol_arg="$ol_val"
+ fi
+ done
+ if test "$ol_arg" = "invalid" ; then
+ { echo "configure: error: bad value $enableval for --enable-ldapi" 1>&2; exit 1; }
+ fi
+ ol_enable_ldapi="$ol_arg"
+
+else
+ ol_enable_ldapi="no"
+fi
+# end --enable-ldapi
# OpenLDAP --enable-x_compile
# Check whether --enable-x_compile or --disable-x_compile was given.
if test "${enable_x_compile+set}" = set; then
fi
# end --enable-dmalloc
-# OpenLDAP --with-cyrus_sasl
- # Check whether --with-cyrus_sasl or --without-cyrus_sasl was given.
+# OpenLDAP --with-cyrus-sasl
+ # Check whether --with-cyrus-sasl or --without-cyrus_sasl was given.
if test "${with_cyrus_sasl+set}" = set; then
withval="$with_cyrus_sasl"
fi
done
if test "$ol_arg" = "invalid" ; then
- { echo "configure: error: bad value $withval for --with-cyrus_sasl" 1>&2; exit 1; }
+ { echo "configure: error: bad value $withval for --with-cyrus-sasl" 1>&2; exit 1; }
fi
ol_with_cyrus_sasl="$ol_arg"
else
ol_with_cyrus_sasl="auto"
fi
-# end --with-cyrus_sasl
+# end --with-cyrus-sasl
# OpenLDAP --with-fetch
# Check whether --with-fetch or --without-fetch was given.
sys/resource.h \
sys/select.h \
sys/socket.h \
+ sys/un.h \
sys/syslog.h \
sys/time.h \
sys/types.h \
EOF
fi
+if test "$ol_enable_ldapi" != no ; then
+ cat >> confdefs.h <<\EOF
+#define LDAP_PF_LOCAL 1
+EOF
+fi
if test "$ol_enable_crypt" != no ; then
cat >> confdefs.h <<\EOF
#define SLAPD_CRYPT 1
OL_ARG_ENABLE(dns,[ --enable-dns enable V2 DX Referrals extension], no)dnl
OL_ARG_ENABLE(referrals,[ --enable-referrals enable V2 Referrals extension], yes)dnl
OL_ARG_ENABLE(cldap,[ --enable-cldap enable connectionless ldap], no)dnl
+OL_ARG_ENABLE(ldapi,[ --enable-ldapi enable domain socket (PF_LOCAL) ldap], no)dnl
OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling],
no, [yes no])dnl
if test "$ol_enable_cldap" != no ; then
AC_DEFINE(LDAP_CONNECTIONLESS,1,[define to support CLDAP])
fi
+if test "$ol_enable_ldapi" != no; then
+ AC_DEFINE(USE_PF_LOCAL,1,[define to support PF_LOCAL transport])
+fi
if test "$ol_enable_crypt" != no ; then
AC_DEFINE(SLAPD_CRYPT,1,[define to support crypt(3) passwords])
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
* types for ldap URL handling
*/
typedef struct ldap_url_desc {
- struct ldap_url_desc *lud_next;
- int lud_ldaps;
+ struct ldap_url_desc *lud_next;
+ unsigned long lud_properties;
+ int lud_protocol;
char *lud_host;
int lud_port;
char *lud_dn;
char **lud_attrs;
int lud_scope;
char *lud_filter;
- char **lud_exts;
+ char **lud_exts;
} LDAPURLDesc;
+/* lud_properties */
+#define LDAP_URL_USE_SSL 0x00000001
+#define LDAP_URL_USE_SSL_UNSPECIFIED 0x00000002
+
+/* lud_protocol */
+#define LDAP_PROTO_TCP 0x00
+#define LDAP_PROTO_UDP 0x01
+#define LDAP_PROTO_LOCAL 0x02
+
#define LDAP_URL_SUCCESS 0x00 /* Success */
#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */
#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */
LDAPControl **clientctrls,
int *msgidp ));
+LIBLDAP_F( int )
+ldap_negotiated_sasl_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn, /* usually NULL */
+ LDAP_CONST char *authorizationId,
+ LDAP_CONST char *authenticationId, /* usually NULL */
+ LDAP_CONST char *saslMechanism,
+ struct berval *passPhrase,
+ LDAPControl **serverControls,
+ LDAPControl **clientControls ));
+
LIBLDAP_F( int )
ldap_sasl_bind_s LDAP_P((
LDAP *ld,
ldap_is_dns_dn LDAP_P(( /* deprecated */
LDAP_CONST char *dn ));
+LIBLDAP_F( char * )
+ldap_dn2dcedn LDAP_P(( LDAP_CONST char *dn ));
+
+LIBLDAP_F( char * )
+ldap_dcedn2dn LDAP_P(( LDAP_CONST char *dce ));
/*
* in getattr.c
#define LDAP_NEEDSESCAPE(c) ((c) == '\\' || (c) == '"')
+#ifdef HAVE_CYRUS_SASL
+/* sasl.c */
+LIBLDAP_F (int) ldap_pvt_sasl_init LDAP_P(( void )); /* clientside init */
+LIBLDAP_F (int) ldap_pvt_sasl_install LDAP_P(( Sockbuf *, void * ));
+LIBLDAP_F (int) ldap_pvt_sasl_err2ldap LDAP_P(( int ));
+#endif /* HAVE_CYRUS_SASL */
+
/* search.c */
LIBLDAP_F( char * )
ldap_pvt_find_wildcard LDAP_P(( char *s ));
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
/* Define if you have the <sysexits.h> header file. */
#undef HAVE_SYSEXITS_H
/* define to support CLDAP */
#undef LDAP_CONNECTIONLESS
+/* define to support domain sockets */
+#undef LDAP_PF_LOCAL
+
/* define to support crypt(3) passwords */
#undef SLAPD_CRYPT
getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c getdxbyname.c os-ip.c url.c charset.c \
init.c options.c print.c string.c util-int.c schema.c \
- charray.c digest.c tls.c dn.c
+ charray.c digest.c tls.c dn.c os-local.c
OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
controls.lo messages.lo references.lo extended.lo \
modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
request.lo getdxbyname.lo os-ip.lo url.lo charset.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
- charray.lo digest.lo tls.lo dn.lo
+ charray.lo digest.lo tls.lo dn.lo os-local.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
#include "ldap-int.h"
+#define DN_TYPE_LDAP_RDN 0
+#define DN_TYPE_LDAP_DN 1
+#define DN_TYPE_DCE_DN 2
+
static char **explode_name( const char *name, int notypes, int is_dn );
char *
if ( ldap_is_dns_dn( dn ) ) {
return( ldap_explode_dns( dn ) );
}
- return explode_name( dn, notypes, 1 );
+ return explode_name( dn, notypes, DN_TYPE_LDAP_DN );
}
char **
ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
{
Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
- return explode_name( rdn, notypes, 0 );
+ return explode_name( rdn, notypes, DN_TYPE_LDAP_RDN );
+}
+
+char *
+ldap_dn2dcedn( LDAP_CONST char *dn )
+{
+ char *dce, *q, **rdns, **p;
+ int len = 0;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
+
+ rdns = explode_name( dn, 0, DN_TYPE_LDAP_DN );
+ if ( rdns == NULL ) {
+ return NULL;
+ }
+
+ for ( p = rdns; *p != NULL; p++ ) {
+ len += strlen( *p ) + 1;
+ }
+
+ q = dce = LDAP_MALLOC( len + 1 );
+ if ( dce == NULL ) {
+ return NULL;
+ }
+
+ p--; /* get back past NULL */
+
+ for ( ; p != rdns; p-- ) {
+ strcpy( q, "/" );
+ q++;
+ strcpy( q, *p );
+ q += strlen( *p );
+ }
+
+ strcpy( q, "/" );
+ q++;
+ strcpy( q, *p );
+
+ return dce;
+}
+
+char *
+ldap_dcedn2dn( LDAP_CONST char *dce )
+{
+ char *dn, *q, **rdns, **p;
+ int len;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
+
+ rdns = explode_name( dce, 0, DN_TYPE_DCE_DN );
+ if ( rdns == NULL ) {
+ return NULL;
+ }
+
+ len = 0;
+
+ for ( p = rdns; *p != NULL; p++ ) {
+ len += strlen( *p ) + 1;
+ }
+
+ q = dn = LDAP_MALLOC( len );
+ if ( dn == NULL ) {
+ return NULL;
+ }
+
+ p--;
+
+ for ( ; p != rdns; p-- ) {
+ strcpy( q, *p );
+ q += strlen( *p );
+ strcpy( q, "," );
+ q++;
+ }
+
+ if ( *dce == '/' ) {
+ /* the name was fully qualified, thus the most-significant
+ * RDN was empty. trash the last comma */
+ q--;
+ *q = '\0';
+ } else {
+ /* the name was relative. copy the most significant RDN */
+ strcpy( q, *p );
+ }
+
+ return dn;
}
static char **
state = INQUOTE;
break;
case '+':
- if (!is_dn)
+ if (is_dn == DN_TYPE_LDAP_RDN)
+ goto end_part;
+ break;
+ case '/':
+ if (is_dn == DN_TYPE_DCE_DN)
goto end_part;
break;
case ';':
case ',':
- if (!is_dn)
- break;
- goto end_part;
+ if (is_dn == DN_TYPE_LDAP_DN)
+ goto end_part;
+ break;
case '\0':
end_part:
if ( state == OUTQUOTE ) {
ldap_pvt_tls_init();
#endif
+#ifdef HAVE_CYRUS_SASL
+ ldap_pvt_sasl_init();
+#endif
+
if ( ldap_int_tblsize == 0 )
ldap_int_ip_init();
#include "ldap_pvt.h"
+#ifdef HAVE_CYRUS_SASL
+#include <sasl.h>
+#endif /* HAVE_CYRUS_SASL */
+
LDAP_BEGIN_DECL
#define LDAP_URL_PREFIX "ldap://"
#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1)
#define LDAPS_URL_PREFIX "ldaps://"
#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1)
+#define LDAPI_URL_PREFIX "ldapi://"
+#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1)
+#define LDAPIS_URL_PREFIX "ldapis://"
+#define LDAPIS_URL_PREFIX_LEN (sizeof(LDAPIS_URL_PREFIX)-1)
#define LDAP_URL_URLCOLON "URL:"
#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1)
#define NULLLDAPURLDESC ((LDAPURLDesc *)NULL)
char *lsrv_host;
char *lsrv_dn; /* if NULL, use default */
int lsrv_port;
+/* int lsrv_protocol; */
struct ldap_server *lsrv_next;
} LDAPServer;
int (*ld_rebindproc)( struct ldap *ld, char **dnp,
char **passwdp, int *authmethodp, int freeit );
/* routine to get info needed for re-bind */
+#ifdef HAVE_CYRUS_SASL
+ sasl_conn_t *ld_sasl_context;
+#endif /* HAVE_CYRUS_SASL */
};
#define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION )
LIBLDAP_F (int) ldap_open_defconn( LDAP *ld );
LIBLDAP_F (int) open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srvlist, char **krbinstancep, int async );
-
/*
* in os-ip.c
*/
LIBLDAP_F (void) ldap_close_connection( Sockbuf *sb );
-#ifdef HAVE_KERBEROS
+#if defined(HAVE_KERBEROS) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
LIBLDAP_F (char *) ldap_host_connected_to( Sockbuf *sb );
#endif /* HAVE_KERBEROS */
LIBLDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb );
LIBLDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb );
+#ifdef LDAP_PF_LOCAL
+/*
+ * in os-local.c
+ */
+LIBLDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, const char *path, int async );
+#endif /* LDAP_PF_LOCAL */
/*
* in request.c
LIBLDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
LIBLDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all );
LIBLDAP_F (void) ldap_dump_requests_and_responses( LDAP *ld );
-
LIBLDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp );
LIBLDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s );
if ( srv->lud_host == NULL || *srv->lud_host == 0 )
addr = htonl( INADDR_LOOPBACK );
- rc = ldap_connect_to_host( ld, sb, srv->lud_host, addr, port, async );
+ switch ( srv->lud_protocol ) {
+ case LDAP_PROTO_TCP:
+ case LDAP_PROTO_UDP:
+ rc = ldap_connect_to_host( ld, sb, srv->lud_host, addr, port, async );
+ break;
+ case LDAP_PROTO_LOCAL:
+ rc = ldap_connect_to_path( ld, sb, srv->lud_host, async );
+ break;
+ default:
+ rc = -1;
+ break;
+ }
+
if ( rc == -1 ) {
return( rc );
}
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
#ifdef HAVE_TLS
- tls = srv->lud_ldaps;
- if (tls == -1)
- tls = ld->ld_options.ldo_tls_mode;
+ tls = (srv->lud_properties & LDAP_URL_USE_SSL);
+ if (tls == 0)
+ tls = (srv->lud_properties & LDAP_URL_USE_SSL_UNSPECIFIED);
+
if ( tls != 0 ) {
rc = ldap_pvt_tls_start( sb, ld->ld_options.ldo_tls_ctx );
if (rc != LDAP_SUCCESS)
}
-#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS )
+#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL )
char *
ldap_host_connected_to( Sockbuf *sb )
{
--- /dev/null
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
+ * Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ * Copyright (c) 1999 PADL Software Pty Ltd.
+ * os-ip.c -- platform-specific domain socket code
+ */
+
+
+#include "portable.h"
+
+#ifdef LDAP_PF_LOCAL
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
+
+/* XXX non-portable */
+#include <sys/stat.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif /* HAVE_IO_H */
+
+#include "ldap-int.h"
+
+/* int ldap_int_tblsize = 0; */
+
+#define oslocal_debug(ld,fmt,arg1,arg2,arg3) \
+do { \
+ ldap_log_printf(ld, LDAP_DEBUG_TRACE, fmt, arg1, arg2, arg3); \
+} while(0)
+
+static void
+ldap_pvt_set_errno(int err)
+{
+ errno = err;
+}
+
+static int
+ldap_pvt_ndelay_on(LDAP *ld, int fd)
+{
+ oslocal_debug(ld, "ldap_ndelay_on: %d\n",fd,0,0);
+ return ber_pvt_socket_set_nonblock( fd, 1 );
+}
+
+static int
+ldap_pvt_ndelay_off(LDAP *ld, int fd)
+{
+ oslocal_debug(ld, "ldap_ndelay_off: %d\n",fd,0,0);
+ return ber_pvt_socket_set_nonblock( fd, 0 );
+}
+
+static ber_socket_t
+ldap_pvt_socket(LDAP *ld)
+{
+ ber_socket_t s = socket(AF_UNIX, SOCK_STREAM, 0);
+ oslocal_debug(ld, "ldap_new_socket: %d\n",s,0,0);
+ return ( s );
+}
+
+static int
+ldap_pvt_close_socket(LDAP *ld, int s)
+{
+ oslocal_debug(ld, "ldap_close_socket: %d\n",s,0,0);
+ return tcp_close(s);
+}
+
+#undef TRACE
+#define TRACE do { \
+ oslocal_debug(ld, \
+ "ldap_is_socket_ready: errror on socket %d: errno: %d (%s)\n", \
+ s, \
+ errno, \
+ strerror(errno) ); \
+} while( 0 )
+
+/*
+ * check the socket for errors after select returned.
+ */
+static int
+ldap_pvt_is_socket_ready(LDAP *ld, int s)
+{
+ oslocal_debug(ld, "ldap_is_sock_ready: %d\n",s,0,0);
+
+#if defined( notyet ) /* && defined( SO_ERROR ) */
+{
+ int so_errno;
+ int dummy = sizeof(so_errno);
+ if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &so_errno, &dummy ) == -1 ) {
+ return -1;
+ }
+ if ( so_errno ) {
+ ldap_pvt_set_errno(so_errno);
+ TRACE;
+ return -1;
+ }
+ return 0;
+}
+#else
+{
+ /* error slippery */
+ struct sockaddr_un sun;
+ char ch;
+ int dummy = sizeof(sun);
+ if ( getpeername( s, (struct sockaddr *) &sun, &dummy ) == -1 ) {
+ /* XXX: needs to be replace with ber_stream_read() */
+ read(s, &ch, 1);
+ TRACE;
+ return -1;
+ }
+ return 0;
+}
+#endif
+ return -1;
+}
+#undef TRACE
+
+static int
+ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sun, int async)
+{
+ struct timeval tv, *opt_tv=NULL;
+ fd_set wfds, *z=NULL;
+
+ if ( (opt_tv = ld->ld_options.ldo_tm_net) != NULL ) {
+ tv.tv_usec = opt_tv->tv_usec;
+ tv.tv_sec = opt_tv->tv_sec;
+ }
+
+ oslocal_debug(ld, "ldap_connect_timeout: fd: %d tm: %ld async: %d\n",
+ s, opt_tv ? tv.tv_sec : -1L, async);
+
+ if ( ldap_pvt_ndelay_on(ld, s) == -1 )
+ return ( -1 );
+
+ if ( connect(s, (struct sockaddr *) sun, sizeof(struct sockaddr_un)) == 0 )
+ {
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+ return ( -1 );
+ return ( 0 );
+ }
+
+ if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) {
+ return ( -1 );
+ }
+
+#ifdef notyet
+ if ( async ) return ( -2 );
+#endif
+
+ FD_ZERO(&wfds);
+ FD_SET(s, &wfds );
+
+ if ( select(ldap_int_tblsize, z, &wfds, z, opt_tv ? &tv : NULL) == -1)
+ return ( -1 );
+
+ if ( FD_ISSET(s, &wfds) ) {
+ if ( ldap_pvt_is_socket_ready(ld, s) == -1 )
+ return ( -1 );
+ if ( ldap_pvt_ndelay_off(ld, s) == -1 )
+ return ( -1 );
+ return ( 0 );
+ }
+ oslocal_debug(ld, "ldap_connect_timeout: timed out\n",0,0,0);
+ ldap_pvt_set_errno( ETIMEDOUT );
+ return ( -1 );
+}
+
+int
+ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async)
+{
+ struct sockaddr_un server;
+ ber_socket_t s = AC_SOCKET_INVALID;
+ int rc, i, len;
+ char *ha_buf=NULL, *p, *q;
+
+ oslocal_debug(ld, "ldap_connect_to_path\n",0,0,0);
+
+ if ( (s = ldap_pvt_socket( ld )) == -1 ) {
+ return -1;
+ }
+
+ if ( path == NULL || path[0] == '\0' ) {
+ path = "/tmp/.ldap-sock";
+ } else {
+ if ( strlen(path) > (sizeof( server.sun_path ) - 1) ) {
+ ldap_pvt_set_errno( ENAMETOOLONG );
+ return -1;
+ }
+ }
+
+ oslocal_debug(ld, "ldap_connect_to_path: Trying %s\n", path, 0, 0);
+
+ memset( &server, 0, sizeof(server) );
+ server.sun_family = AF_UNIX;
+ strcpy( server.sun_path, path );
+
+ rc = ldap_pvt_connect(ld, s, &server, async);
+
+ if (rc == 0) {
+ ber_pvt_sb_set_desc( sb, s );
+ } else {
+ ldap_pvt_close_socket(ld, s);
+ }
+ return rc;
+}
+#else
+static int dummy;
+#endif /* LDAP_PF_LOCAL */
( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 );
}
-
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_DNS )
&& ldap_is_dns_dn( dn ) )
return( msgid );
}
-
LDAPConn *
ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
int connect, int bind )
return LDAP_SUCCESS;
}
-/*
- * ldap_sasl_bind_s - bind to the ldap server (and X.500) using simple
- * authentication. The dn and password of the entry to which to bind are
- * supplied. LDAP_SUCCESS is returned upon success, the ldap error code
- * otherwise.
- *
- * Example:
- * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us",
- * "mechanism", "secret", NULL, NULL, &servercred )
- */
int
ldap_sasl_bind_s(
/*
- * Parse BindResponse:
- *
- * BindResponse ::= [APPLICATION 1] SEQUENCE {
- * COMPONENTS OF LDAPResult,
- * serverSaslCreds [7] OCTET STRING OPTIONAL }
- *
- * LDAPResult ::= SEQUENCE {
- * resultCode ENUMERATED,
- * matchedDN LDAPDN,
- * errorMessage LDAPString,
- * referral [3] Referral OPTIONAL }
- */
+* Parse BindResponse:
+*
+* BindResponse ::= [APPLICATION 1] SEQUENCE {
+* COMPONENTS OF LDAPResult,
+* serverSaslCreds [7] OCTET STRING OPTIONAL }
+*
+* LDAPResult ::= SEQUENCE {
+* resultCode ENUMERATED,
+* matchedDN LDAPDN,
+* errorMessage LDAPString,
+* referral [3] Referral OPTIONAL }
+*/
int
ldap_parse_sasl_bind_result(
return( ld->ld_errno );
}
+
+#ifdef HAVE_CYRUS_SASL
+/*
+* Various Cyrus SASL related stuff.
+*/
+
+static int sasl_setup( Sockbuf *sb, void *arg );
+static int sasl_remove( Sockbuf *sb );
+static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t len );
+static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len );
+static int sasl_close( Sockbuf *sb );
+
+static Sockbuf_IO sasl_io=
+{
+sasl_setup,
+sasl_remove,
+sasl_read,
+sasl_write,
+sasl_close
+};
+
+#define HAS_SASL( sb ) ((sb)->sb_io==&sasl_io)
+
+static char *
+array2str( char **a )
+{
+ char *s, **v, *p;
+ int len = 0;
+
+ for ( v = a; *v != NULL; v++ ) {
+ len += strlen( *v ) + 1; /* for a space */
+ }
+
+ if ( len == 0 ) {
+ return NULL;
+ }
+
+ s = LDAP_MALLOC ( len ); /* last space holds \0 */
+
+ if ( s == NULL ) {
+ return NULL;
+ }
+
+ p = s;
+ for ( v = a; *v != NULL; v++ ) {
+ int len;
+
+ if ( v != a ) {
+ strncpy( p, " ", 1 );
+ ++p;
+ }
+ len = strlen( *v );
+ strncpy( p, *v, len );
+ p += len;
+ }
+
+ *p = '\0';
+
+ return s;
+}
+
+int ldap_pvt_sasl_init( void )
+{
+ /* XXX not threadsafe */
+ static int sasl_initialized = 0;
+
+ if ( sasl_initialized ) {
+ return -1;
+ }
+#ifndef CSRIMALLOC
+ sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree );
+#endif /* CSRIMALLOC */
+
+ if ( sasl_client_init( NULL ) == SASL_OK ) {
+ sasl_initialized = 1;
+ return 0;
+ }
+
+ return -1;
+}
+
+int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
+{
+ /* don't install the stuff unless security has been negotiated */
+
+ if ( !HAS_SASL( sb ) ) {
+ ber_pvt_sb_clear_io( sb );
+ ber_pvt_sb_set_io( sb, &sasl_io, ctx_arg );
+ }
+
+ return 0;
+}
+
+static int sasl_setup( Sockbuf *sb, void *arg )
+{
+ sb->sb_iodata = arg;
+ return 0;
+}
+
+static int sasl_remove( Sockbuf *sb )
+{
+ return 0;
+}
+
+static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t buflen )
+{
+ char *recv_tok;
+ unsigned recv_tok_len;
+ sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
+
+ if ((ber_pvt_sb_io_tcp.sbi_read)( sb, buf, buflen ) != buflen ) {
+ return -1;
+ }
+
+ if ( sasl_decode( conn, buf, buflen, &recv_tok, &recv_tok_len ) != SASL_OK ) {
+ return -1;
+ }
+
+ if ( recv_tok_len > buflen ) {
+ LDAP_FREE( recv_tok );
+ return -1;
+ }
+
+ memcpy( buf, recv_tok, recv_tok_len );
+
+ LDAP_FREE( recv_tok );
+
+ return recv_tok_len;
+}
+
+static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len )
+{
+ char *wrapped_tok;
+ unsigned wrapped_tok_len;
+ sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
+
+ if ( sasl_encode( conn, (const char *)buf, len,
+ &wrapped_tok, &wrapped_tok_len ) != SASL_OK ) {
+ return -1;
+ }
+
+ if ((ber_pvt_sb_io_tcp.sbi_write)( sb, wrapped_tok, wrapped_tok_len ) != wrapped_tok_len ) {
+ LDAP_FREE( wrapped_tok );
+ return -1;
+ }
+
+ LDAP_FREE( wrapped_tok );
+
+ return len;
+}
+
+static int sasl_close( Sockbuf *sb )
+{
+ (ber_pvt_sb_io_tcp.sbi_close)( sb );
+}
+
+int
+ldap_pvt_sasl_err2ldap( int saslerr )
+{
+ int rc;
+
+ switch (saslerr) {
+ case SASL_CONTINUE:
+ rc = LDAP_SASL_BIND_IN_PROGRESS;
+ break;
+ case SASL_OK:
+ rc = LDAP_SUCCESS;
+ break;
+ case SASL_FAIL:
+ rc = LDAP_OPERATIONS_ERROR;
+ break;
+ case SASL_NOMEM:
+ rc = LDAP_NO_MEMORY;
+ break;
+ case SASL_NOMECH:
+ rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
+ break;
+ case SASL_BADAUTH:
+ rc = LDAP_INVALID_CREDENTIALS;
+ break;
+ case SASL_NOAUTHZ:
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ break;
+ case SASL_TOOWEAK:
+ case SASL_ENCRYPT:
+ rc = LDAP_INAPPROPRIATE_AUTH;
+ break;
+ default:
+ rc = LDAP_OPERATIONS_ERROR;
+ break;
+ }
+
+ return rc;
+}
+
+int
+ldap_pvt_sasl_getmechs ( LDAP *ld, LDAP_CONST char *desired, char **pmechlist )
+{
+ /* we need to query the server for supported mechs anyway */
+ LDAPMessage *res, *e;
+ char *attrs[] = { "supportedSASLMechanisms", NULL };
+ char **values, *mechlist, **p;
+ int rc;
+
+ rc = ldap_search_s( ld, NULL, LDAP_SCOPE_BASE,
+ "(objectclass=*)", attrs, 0, &res );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return ld->ld_errno;
+ }
+
+ e = ldap_first_entry( ld, res );
+ if ( e == NULL ) {
+ if ( ld->ld_errno == LDAP_SUCCESS ) {
+ ld->ld_errno = LDAP_UNAVAILABLE;
+ }
+ return ld->ld_errno;
+ }
+
+ values = ldap_get_values( ld, e, "supportedSASLMechanisms" );
+ if ( values == NULL ) {
+ ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE;
+ ldap_msgfree( res );
+ return ld->ld_errno;
+ }
+
+ if ( desired != NULL ) {
+ rc = LDAP_INAPPROPRIATE_AUTH;
+
+ for ( p = values; *p != NULL; p++ ) {
+ if ( !strcmp( *p, desired ) == 0 ) {
+ rc = LDAP_SUCCESS;
+ break;
+ }
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ /* just return this */
+ *pmechlist = LDAP_STRDUP( desired );
+ return LDAP_SUCCESS;
+ } else {
+ /* couldn't find it */
+ ld->ld_errno = LDAP_INAPPROPRIATE_AUTH;
+ return ld->ld_errno;
+ }
+ }
+
+ mechlist = array2str( values );
+ if ( mechlist == NULL ) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ ldap_value_free( values );
+ ldap_msgfree( res );
+ return ld->ld_errno;
+ }
+
+ ldap_value_free( values );
+ ldap_msgfree( res );
+
+ *pmechlist = mechlist;
+
+ return LDAP_SUCCESS;
+}
+
+int
+ldap_pvt_sasl_bind(
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ const sasl_callback_t *callbacks,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls )
+{
+ int saslrc, rc, msgid, ssf = 0;
+ struct berval ccred, *scred;
+ char *mechlist = NULL;
+ char *host;
+ sasl_interact_t *client_interact = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
+
+ /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
+ if (ld->ld_version < LDAP_VERSION3) {
+ ld->ld_errno = LDAP_NOT_SUPPORTED;
+ return ld->ld_errno;
+ }
+
+ /*
+ * This connects to the host, side effect being that
+ * ldap_host_connected_to() works.
+ */
+ rc = ldap_pvt_sasl_getmechs( ld, mechanism, &mechlist );
+ if ( rc != LDAP_SUCCESS ) {
+ return ld->ld_errno;
+ }
+
+ /* XXX this doesn't work with PF_LOCAL hosts */
+ host = ldap_host_connected_to( &ld->ld_sb );
+
+ if ( host == NULL ) {
+ LDAP_FREE( mechlist );
+ ld->ld_errno = LDAP_UNAVAILABLE;
+ return ld->ld_errno;
+ }
+
+ if ( ld->ld_sasl_context != NULL ) {
+ LDAP_FREE( mechlist );
+ sasl_dispose( &ld->ld_sasl_context );
+ }
+
+ saslrc = sasl_client_new( "ldap", host, callbacks, 0, &ld->ld_sasl_context );
+
+ LDAP_FREE( host );
+
+ if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
+ LDAP_FREE( mechlist );
+ ld->ld_errno = ldap_pvt_sasl_err2ldap( rc );
+ sasl_dispose( &ld->ld_sasl_context );
+ return ld->ld_errno;
+ }
+
+ ccred.bv_val = NULL;
+ ccred.bv_len = 0;
+
+ saslrc = sasl_client_start( ld->ld_sasl_context,
+ mechlist,
+ NULL,
+ &client_interact,
+ &ccred.bv_val,
+ (unsigned int *)&ccred.bv_len,
+ &mechanism );
+
+ LDAP_FREE( mechlist );
+
+ if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
+ ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc );
+ sasl_dispose( &ld->ld_sasl_context );
+ return ld->ld_errno;
+ }
+
+ scred = NULL;
+
+ do {
+ sasl_interact_t *client_interact = NULL;
+
+ rc = ldap_sasl_bind_s( ld, dn, mechanism, &ccred, sctrls, cctrls, &scred );
+ if ( rc == LDAP_SUCCESS ) {
+ break;
+ } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) {
+ if ( ccred.bv_val != NULL ) {
+ LDAP_FREE( ccred.bv_val );
+ }
+ sasl_dispose( &ld->ld_sasl_context );
+ return ld->ld_errno;
+ }
+
+ if ( ccred.bv_val != NULL ) {
+ LDAP_FREE( ccred.bv_val );
+ ccred.bv_val = NULL;
+ }
+
+ saslrc = sasl_client_step( ld->ld_sasl_context,
+ (scred == NULL) ? NULL : scred->bv_val,
+ (scred == NULL) ? 0 : scred->bv_len,
+ &client_interact,
+ &ccred.bv_val,
+ (unsigned int *)&ccred.bv_len );
+
+ ber_bvfree( scred );
+
+ if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
+ ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc );
+ sasl_dispose( &ld->ld_sasl_context );
+ return ld->ld_errno;
+ }
+ } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
+
+ assert ( rc == LDAP_SUCCESS );
+
+ if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
+ == SASL_OK && ssf ) {
+ ldap_pvt_sasl_install( &ld->ld_sb, ld->ld_sasl_context );
+ }
+
+ return rc;
+}
+
+/* based on sample/sample-client.c */
+static int
+ldap_pvt_sasl_getsecret(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
+{
+ struct berval *passphrase = (struct berval *)context;
+ size_t len;
+
+ if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) {
+ return SASL_BADPARAM;
+ }
+
+ len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0;
+
+ *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len );
+ if ( *psecret == NULL ) {
+ return SASL_NOMEM;
+ }
+
+ (*psecret)->len = passphrase->bv_len;
+
+ if ( passphrase != NULL ) {
+ memcpy((*psecret)->data, passphrase->bv_val, len);
+ }
+
+ return SASL_OK;
+}
+
+static int
+ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len)
+{
+ const char *value = (const char *)context;
+
+ if ( result == NULL ) {
+ return SASL_BADPARAM;
+ }
+
+ switch ( id ) {
+ case SASL_CB_USER:
+ case SASL_CB_AUTHNAME:
+ *result = value;
+ if ( len )
+ *len = value ? strlen( value ) : 0;
+ break;
+ case SASL_CB_LANGUAGE:
+ *result = NULL;
+ if ( len )
+ *len = 0;
+ break;
+ default:
+ return SASL_BADPARAM;
+ }
+
+ return SASL_OK;
+}
+
+/*
+ * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500) using SASL
+ * authentication. The dn and password of the entry to which to bind are
+ * supplied. LDAP_SUCCESS is returned upon success, the ldap error code
+ * otherwise.
+ *
+ * Example:
+ * ldap_negotiated_sasl_bind_s( ld, NULL,
+ * "dn:cn=manager", NULL, "GSSAPI", NULL, NULL, NULL );
+ */
+int
+ldap_negotiated_sasl_bind_s(
+ LDAP *ld,
+ LDAP_CONST char *dn, /* usually NULL */
+ LDAP_CONST char *authorizationId,
+ LDAP_CONST char *authenticationId,
+ LDAP_CONST char *saslMechanism,
+ struct berval *passPhrase,
+ LDAPControl **serverControls,
+ LDAPControl **clientControls)
+{
+ sasl_callback_t callbacks[4];
+ int rc;
+
+ callbacks[0].id = SASL_CB_USER;
+ callbacks[0].proc = ldap_pvt_sasl_getsimple;
+ callbacks[0].context = (void *)authorizationId;
+ callbacks[1].id = SASL_CB_AUTHNAME;
+ callbacks[1].proc = ldap_pvt_sasl_getsimple;
+ callbacks[1].context = (void *)authenticationId;
+ callbacks[2].id = SASL_CB_PASS;
+ callbacks[2].proc = ldap_pvt_sasl_getsecret;
+ callbacks[2].context = (void *)passPhrase;
+ callbacks[3].id = SASL_CB_LIST_END;
+ callbacks[3].proc = NULL;
+ callbacks[3].context = NULL;
+
+ rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks, serverControls, clientControls);
+
+ return rc;
+}
+#endif /* HAVE_CYRUS_SASL */
ld->ld_options.ldo_tm_net = NULL;
}
+#ifdef HAVE_CYRUS_SASL
+ if ( ld->ld_sasl_context != NULL ) {
+ sasl_dispose( &ld->ld_sasl_context );
+ }
+#endif
+
ber_pvt_sb_destroy( &(ld->ld_sb) );
LDAP_FREE( (char *) ld );
static const char* skip_url_prefix LDAP_P((
const char *url,
int *enclosedp,
- int *ldaps ));
+ unsigned long *properties,
+ int *protocol));
int
ldap_is_ldap_url( LDAP_CONST char *url )
{
- int enclosed;
- int ldaps;
+ int enclosed, protocol;
+ unsigned long properties;
if( url == NULL ) {
return 0;
}
- if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) {
+ if( skip_url_prefix( url, &enclosed, &properties, &protocol) == NULL ) {
return 0;
}
- return !ldaps;
+ return !(properties & LDAP_URL_USE_SSL);
}
int
ldap_is_ldaps_url( LDAP_CONST char *url )
{
- int enclosed;
- int ldaps;
+ int enclosed, protocol;
+ unsigned long properties;
if( url == NULL ) {
return 0;
}
- if( skip_url_prefix( url, &enclosed, &ldaps) == NULL ) {
+ if( skip_url_prefix( url, &enclosed, &properties, &protocol) == NULL ) {
return 0;
}
- return ldaps;
+ return (properties & LDAP_URL_USE_SSL);
}
static const char*
skip_url_prefix(
const char *url,
int *enclosedp,
- int *ldaps )
+ unsigned long *properties,
+ int *protocol
+ )
{
/*
* return non-zero if this looks like a LDAP URL; zero if not
p += LDAP_URL_URLCOLON_LEN;
}
+ *properties = 0;
+
/* check for "ldap://" prefix */
if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldap://" prefix and return success */
p += LDAP_URL_PREFIX_LEN;
- *ldaps = 0;
+ *protocol = LDAP_PROTO_TCP;
return( p );
}
if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldaps://" prefix and return success */
p += LDAPS_URL_PREFIX_LEN;
- *ldaps = 1;
+ *protocol = LDAP_PROTO_TCP;
+ *properties |= LDAP_URL_USE_SSL;
+ return( p );
+ }
+
+ /* check for "ldapi://" prefix */
+ if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldapi://" prefix and return success */
+ p += LDAPI_URL_PREFIX_LEN;
+ *protocol = LDAP_PROTO_LOCAL;
+ return( p );
+ }
+
+ /* check for "ldapis://" prefix: should this be legal? */
+ if ( strncasecmp( p, LDAPIS_URL_PREFIX, LDAPIS_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldapis://" prefix and return success */
+ p += LDAPIS_URL_PREFIX_LEN;
+ *protocol = LDAP_PROTO_LOCAL;
+ *properties |= LDAP_URL_USE_SSL;
return( p );
}
LDAPURLDesc *ludp;
char *p, *q;
- int i, enclosed, ldaps;
+ int i, enclosed, protocol;
+ unsigned long properties;
const char *url_tmp;
char *url;
*ludpp = NULL; /* pessimistic */
- url_tmp = skip_url_prefix( url_in, &enclosed, &ldaps );
+ url_tmp = skip_url_prefix( url_in, &enclosed, &properties, &protocol );
if ( url_tmp == NULL ) {
return LDAP_URL_ERR_NOTLDAP;
ludp->lud_next = NULL;
ludp->lud_host = NULL;
ludp->lud_port = 0;
- ludp->lud_dn = NULL;
- ludp->lud_attrs = NULL;
- ludp->lud_filter = NULL;
- ludp->lud_ldaps = ldaps;
+ ludp->lud_dn = NULL;
+ ludp->lud_attrs = NULL;
+ ludp->lud_filter = NULL;
+ ludp->lud_properties = properties;
+ ludp->lud_protocol = protocol;
ludp->lud_scope = LDAP_SCOPE_BASE;
ludp->lud_filter = LDAP_STRDUP("(objectClass=*)");
}
}
- dest->lud_ldaps = ludp->lud_ldaps;
dest->lud_port = ludp->lud_port;
dest->lud_scope = ludp->lud_scope;
ludp->lud_port = atoi(p);
}
ldap_pvt_hex_unescape(ludp->lud_host);
- ludp->lud_ldaps = -1; /* unknown (use TLS default) */
+ ludp->lud_protocol = LDAP_PROTO_TCP;
+ ludp->lud_properties = LDAP_URL_USE_SSL_UNSPECIFIED;
ludp->lud_next = *ludlist;
*ludlist = ludp;
}
p = s;
for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) {
- p += sprintf(p, "ldap%s://%s", (ludp->lud_ldaps == 1) ? "s" : "", ludp->lud_host);
+ p += sprintf(p, "ldap%s://%s", (ludp->lud_properties & LDAP_URL_USE_SSL) ? "s" : "", ludp->lud_host);
if (ludp->lud_port != 0)
p += sprintf(p, ":%d", ludp->lud_port);
*p++ = '/';
ldap_pvt_hex_unescape( char *s )
{
/*
- * Remove URL hex escapes from s... done in place. The basic concept for
- * this routine is borrowed from the WWW library HTUnEscape() routine.
- */
+* Remove URL hex escapes from s... done in place. The basic concept for
+* this routine is borrowed from the WWW library HTUnEscape() routine.
+*/
char *p;
for ( p = s; *s != '\0'; ++s ) {
getdn.c getentry.c getattr.c getvalues.c addentry.c \
request.c getdxbyname.c os-ip.c url.c charset.c \
init.c options.c print.c string.c util-int.c schema.c \
- charray.c digest.c tls.c dn.c
+ charray.c digest.c tls.c dn.c os-local.c
SRCS = thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
thr_pth.c thr_sleep.c thr_stub.c rdwr.c
OBJS = extended.lo \
init.lo options.lo print.lo string.lo util-int.lo schema.lo \
thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
thr_pth.lo thr_sleep.lo thr_stub.lo rdwr.lo \
- charray.lo digest.lo tls.lo dn.lo
+ charray.lo digest.lo tls.lo dn.lo os-local.lo
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
index.c id2children.c nextid.c abandon.c compare.c group.c \
modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
filterindex.c unbind.c close.c alias.c tools.c \
- extended.c passwd.c
+ extended.c passwd.c sasl.c
OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \
index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \
modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \
filterindex.lo unbind.lo close.lo alias.lo tools.lo \
- extended.lo passwd.lo
+ extended.lo passwd.lo sasl.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
}
} else if ( method == LDAP_AUTH_SASL ) {
+#ifdef HAVE_CYRUS_SASL
+ rc = sasl_bind( be, conn, op,
+ dn, ndn, mech, cred, edn );
+#else
if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
/* insert DIGEST calls here */
send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
NULL, NULL, NULL, NULL );
}
-
+#endif /* HAVE_CYRUS_SASL */
} else if ( refs != NULL ) {
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
/*
- * no krbName values present: check against DN
+ * no krbname values present: check against DN
*/
if ( strcasecmp( dn, krbname ) == 0 ) {
rc = 0;
rc = 1;
goto return_results;
- } else { /* look for krbName match */
+ } else { /* look for krbname match */
struct berval krbval;
krbval.bv_val = krbname;
case LDAP_AUTH_SASL:
/* insert SASL code here */
-
+#ifdef HAVE_CYRUS_SASL
+ /* this may discard edn as we always prefer the SASL authzid
+ * because it may be sealed.
+ */
+ rc = sasl_bind( be, conn, op, dn, ndn, mech, cred, edn );
+#endif /* HAVE_CYRUS_SASL */
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
NULL, "auth method not supported", NULL, NULL );
bi->bi_tool_index_change = ldbm_tool_index_change;
bi->bi_tool_sync = ldbm_tool_sync;
+#ifdef HAVE_CYRUS_SASL
+ bi->bi_sasl_authorize = 0; /* ldbm_sasl_authorize; */
+ bi->bi_sasl_getsecret = 0; /* ldbm_sasl_getsecret; */
+ bi->bi_sasl_putsecret = 0; /* ldbm_sasl_putsecret; */
+#endif
+
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
Connection *conn, Operation *op,
char *dn, LDAPModList *mods, Entry *e ));
+#ifdef HAVE_CYRUS_SASL
+/*
+ * sasl.c
+ */
+int ldbm_sasl_authorize LDAP_P((
+ BackendDB *be,
+ const char *auth_identity,
+ const char *requested_user,
+ const char **user,
+ const char **errstring ));
+int ldbm_sasl_getsecret LDAP_P((
+ Backend *be,
+ const char *mechanism,
+ const char *auth_identity,
+ const char *realm,
+ sasl_secret_t **secret ));
+int ldbm_sasl_putsecret LDAP_P((
+ Backend *be,
+ const char *mechanism,
+ const char *auth_identity,
+ const char *realm,
+ const sasl_secret_t *secret ));
+#endif /* HAVE_CYRUS_SASL */
+
/*
* nextid.c
*/
--- /dev/null
+/* bind.c - ldbm backend bind and unbind routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#ifdef HAVE_CYRUS_SASL
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+int
+back_ldbm_sasl_authorize(
+ BackendDB *be,
+ const char *auth_identity,
+ const char *requested_user,
+ const char **user,
+ const char **errstring)
+{
+ return SASL_FAIL;
+}
+
+int
+back_ldbm_sasl_getsecret(
+ Backend *be,
+ const char *mechanism,
+ const char *auth_identity,
+ const char *realm,
+ sasl_secret_t **secret)
+{
+ return SASL_FAIL;
+}
+
+int
+back_ldbm_sasl_putsecret(
+ Backend *be,
+ const char *mechanism,
+ const char *auth_identity,
+ const char *realm,
+ const sasl_secret_t *secret)
+{
+ return SASL_FAIL;
+}
+
+#else
+static int dummy = 1;
+#endif
+
assert( conn->c_authstate == NULL );
#endif
}
-
} else {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
method, mech, &cred, &edn );
if ( ret == 0 ) {
+#ifdef HAVE_CYRUS_SASL
+ int ssf = 0;
+#endif
+
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_cdn = dn;
send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL, NULL, NULL );
+#ifdef HAVE_CYRUS_SASL
+ if ( conn->c_sasl_context != NULL &&
+ sasl_getprop( conn->c_sasl_context, SASL_SSF, (void **)&ssf )
+ == SASL_OK && ssf ) {
+ /* Enable encode/decode */
+ ldap_pvt_sasl_install( conn->c_sb, conn->c_sasl_context );
+ }
+#endif
} else if (edn != NULL) {
free( edn );
}
#ifdef HAVE_CYRUS_SASL
c->c_sasl_context = NULL;
-#endif
+#endif /* HAVE_CYRUS_SASL */
c->c_sb = ber_sockbuf_alloc( );
c->c_currentber = NULL;
c->c_peer_domain = NULL;
}
if(c->c_peer_name != NULL) {
+#ifdef LDAP_PF_LOCAL
+ /*
+ * If peer was a domain socket, unlink. Mind you,
+ * they may be un-named. Should we leave this to
+ * the client?
+ */
+ if (strncmp(c->c_peer_name, "PATH=", 5) == 0) {
+ char *path = c->c_peer_name + 5;
+ if (path != '\0') {
+ (void)unlink(path);
+ }
+ }
+#endif /* LDAP_PF_LOCAL */
free(c->c_peer_name);
c->c_peer_name = NULL;
}
sasl_dispose( &c->c_sasl_context );
c->c_sasl_context = NULL;
}
-#endif
+#endif /* HAVE_CYRUS_SASL */
+
+ c->c_bind_in_progress = 0;
if ( c->c_currentber != NULL ) {
ber_free( c->c_currentber, 1 );
if( conn->c_conn_state == SLAP_C_BINDING) {
conn->c_conn_state = SLAP_C_ACTIVE;
}
- conn->c_bind_in_progress = ( rc == LDAP_SASL_BIND_IN_PROGRESS );
+ /*
+ * Is this ever the case? For now, rely on
+ * the backend to set this.
+ */
+ if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) {
+ conn->c_bind_in_progress = 1;
+ }
}
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
int deny_severity = LOG_NOTICE;
#endif /* TCP Wrappers */
+#ifdef LDAP_PF_LOCAL
+#include <sys/stat.h>
+#endif /* LDAP_PF_LOCAL */
+
/* globals */
time_t starttime;
ber_socket_t dtblsize;
+#ifdef LDAP_PF_LOCAL
+typedef union slap_sockaddr {
+ struct sockaddr sa_addr;
+ struct sockaddr_in sa_in_addr;
+ struct sockaddr_un sa_un_addr;
+} Sockaddr;
+#endif /* LDAP_PF_LOCAL */
+
typedef struct slap_listener {
char* sl_url;
char* sl_name;
int sl_is_tls;
#endif
ber_socket_t sl_sd;
+#ifdef LDAP_PF_LOCAL
+ Sockaddr sl_sa;
+#define sl_addr sl_sa.sa_in_addr
+#else
struct sockaddr_in sl_addr;
+#endif /* LDAP_PF_LOCAL */
} Listener;
Listener **slap_listeners = NULL;
}
#ifndef HAVE_TLS
- if( lud->lud_ldaps ) {
+ if( lud->lud_properties & LDAP_URL_USE_SSL ) {
Debug( LDAP_DEBUG_ANY,
"daemon: TLS not supported (%s)\n",
url, 0, 0 );
}
#else
- l.sl_is_tls = lud->lud_ldaps;
+ l.sl_is_tls = (lud->lud_properties & LDAP_URL_USE_SSL);
if(! lud->lud_port ) {
- lud->lud_port = lud->lud_ldaps ? LDAPS_PORT : LDAP_PORT;
+ lud->lud_port = (lud->lud_properties & LDAP_URL_USE_SSL) ? LDAPS_PORT : LDAP_PORT;
}
#endif
+#ifdef LDAP_PF_LOCAL
+ if (lud->lud_protocol == LDAP_PROTO_LOCAL) {
+ port = 0;
+ (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
+
+ l.sl_sa.sa_un_addr.sun_family = AF_UNIX;
+
+ /* hack: overload the host to be the path */
+ if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
+ strcpy( l.sl_sa.sa_un_addr.sun_path, "/tmp/.ldap-sock" );
+ } else {
+ if ( strlen(lud->lud_host) > (sizeof(l.sl_sa.sa_un_addr.sun_path) - 1) ) {
+ Debug( LDAP_DEBUG_ANY, "domain socket path (%s) too long in URL: %s",
+ lud->lud_host, url, 0);
+ ldap_free_urldesc( lud );
+ return NULL;
+ }
+ strcpy( l.sl_sa.sa_un_addr.sun_path, lud->lud_host );
+ }
+ unlink( l.sl_sa.sa_un_addr.sun_path );
+#if 0
+ /* I don't think we need to set this. */
+ l.sl_sa.sa_un_addr.sun_len = sizeof( l.sl_sa.sa_un_addr.sun_len ) +
+ sizeof( l.sl_sa.sa_un_addr.sun_family ) +
+ strlen( l.sl_sa.sa_un_addr.sun_path ) + 1;
+#endif
+ } else {
+#endif /* LDAP_PF_LOCAL */
+
port = lud->lud_port;
(void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
sizeof( l.sl_addr.sin_addr ) );
}
}
+#ifdef LDAP_PF_LOCAL
+ }
+#endif /* LDAP_PF_LOCAL */
ldap_free_urldesc( lud );
-
+#ifdef LDAP_PF_LOCAL
+ l.sl_sd = socket( l.sl_sa.sa_addr.sa_family, SOCK_STREAM, 0 );
+ if ( l.sl_sd == AC_SOCKET_INVALID ) {
+#else
if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
+#endif /* LDAP_PF_LOCAL */
int err = sock_errno();
Debug( LDAP_DEBUG_ANY,
"daemon: socket() failed errno=%d (%s)\n", err,
}
#endif
+#ifdef LDAP_PF_LOCAL
+ /* for IP sockets only */
+ if ( l.sl_sa.sa_addr.sa_family == AF_INET ) {
+#endif /* LDAP_PF_LOCAL */
+
#ifdef SO_REUSEADDR
/* enable address reuse */
tmp = 1;
}
#endif
+#ifdef LDAP_PF_LOCAL
+ /* close conditional */
+ }
+
+ switch ( l.sl_sa.sa_addr.sa_family ) {
+ case AF_UNIX:
+ rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
+ sizeof(l.sl_sa.sa_un_addr) );
+ break;
+ case AF_INET:
+ rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
+ sizeof(l.sl_sa.sa_in_addr) );
+ break;
+ default:
+ rc = AC_SOCKET_ERROR;
+ errno = EINVAL;
+ break;
+ }
+#else
rc = bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) );
+#endif /* LDAP_PF_LOCAL */
if ( rc == AC_SOCKET_ERROR ) {
int err = sock_errno();
Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
tcp_close( l.sl_sd );
return NULL;
}
-
+#ifdef LDAP_PF_LOCAL
+ if ( l.sl_sa.sa_addr.sa_family == AF_UNIX ) {
+ if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
+ int err = sock_errno();
+ Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
+ (long) l.sl_sd, err, sock_errstr(err) );
+ tcp_close( l.sl_sd );
+ return NULL;
+ }
+ }
+#endif /* LDAP_PF_LOACL */
l.sl_url = ch_strdup( url );
-
+#ifdef LDAP_PF_LOCAL
+ switch ( l.sl_sa.sa_addr.sa_family ) {
+ case AF_UNIX:
+ l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path) + sizeof("PATH=") );
+ sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
+ break;
+ case AF_INET:
+ l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
+ s = inet_ntoa( l.sl_addr.sin_addr );
+ sprintf( l.sl_name, "IP=%s:%d",
+ s != NULL ? s : "unknown" , port );
+ break;
+ default:
+ l.sl_name = ch_strdup( "UNKNOWN" );
+ break;
+ }
+#else
l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
s = inet_ntoa( l.sl_addr.sin_addr );
sprintf( l.sl_name, "IP=%s:%d",
s != NULL ? s : "unknown" , port );
+#endif /* LDAP_PF_LOCAL */
li = ch_malloc( sizeof( Listener ) );
*li = l;
fd_set readfds;
fd_set writefds;
-
+#ifdef LDAP_PF_LOCAL
+ Sockaddr from;
+/* minimize impact, undefine later. */
+#define sin_addr sa_in_addr.sin_addr
+#define sin_port sa_in_addr.sin_port
+#else
struct sockaddr_in from;
+#endif /* LDAP_PF_LOCAL */
#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
struct hostent *hp;
#endif
char *dnsname;
char *peeraddr;
-
+#ifdef LDAP_PF_LOCAL
+ char peername[MAXPATHLEN + sizeof("PATH=")];
+#else
char peername[sizeof("IP=255.255.255.255:65336")];
-
+#endif /* LDAP_PF_LOCAL */
if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
continue;
continue;
}
+#ifdef LDAP_PF_LOCAL
+ switch ( from.sa_addr.sa_family ) {
+ case AF_UNIX:
+ sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
+ break;
+ case AF_INET:
+#endif /* LDAP_PF_LOCAL */
peeraddr = inet_ntoa( from.sin_addr );
sprintf( peername, "IP=%s:%d",
peeraddr != NULL ? peeraddr : "unknown",
continue;
}
#endif /* HAVE_TCPD */
+#ifdef LDAP_PF_LOCAL
+ break;
+ default:
+ slapd_close(s);
+ continue;
+ }
+#undef sin_addr
+#undef sin_port
+#endif /* LDAP_PF_LOCAL */
if( (id = connection_init(s,
slap_listeners[l]->sl_url,
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
+#ifdef LDAP_PF_LOCAL
+ if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_UNIX ) {
+ unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
+ }
+#endif /* LDAP_PF_LOCAL */
slapd_close( slap_listeners[l]->sl_sd );
break;
}
typedef int (*SLAP_EXTOP_GETOID_FN) LDAP_P((
int index, char *oid, int blen ));
+LIBSLAPD_F (int) load_extension LDAP_P((const void *module, const char *file_name));
+LIBSLAPD_F (char *) get_supported_extension LDAP_P((int index));
+
LIBSLAPD_F (int) load_extop LDAP_P((
const char *ext_oid,
SLAP_EXTOP_MAIN_FN ext_main ));
LIBSLAPD_F (int) sasl_init(void);
LIBSLAPD_F (int) sasl_destroy(void);
+#ifdef HAVE_CYRUS_SASL
+LIBSLAPD_F (int) sasl_errldap LDAP_P(( int ));
+LIBSLAPD_F (int) sasl_bind LDAP_P((Backend *,
+ Connection *, Operation *,
+ char *, char *, char *, struct berval *, char **));
+#endif
/*
* schema.c
char **supportedSASLMechanisms = NULL;
#ifdef HAVE_CYRUS_SASL
-static sasl_callback_t callbacks[] = {
- { SASL_CB_LIST_END, NULL, NULL }
-};
+static void *sasl_pvt_mutex_new(void)
+{
+ ldap_pvt_thread_mutex_t *mutex;
+
+ mutex = (ldap_pvt_thread_mutex_t *)ch_malloc( sizeof(ldap_pvt_thread_mutex_t) );
+ if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
+ return mutex;
+ }
+ return NULL;
+}
+
+static int sasl_pvt_mutex_lock(void *mutex)
+{
+ return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex );
+}
+
+static int sasl_pvt_mutex_unlock(void *mutex)
+{
+ return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex );
+}
+
+static void sasl_pvt_mutex_dispose(void *mutex)
+{
+ (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
+ free( mutex );
+}
int sasl_init( void )
{
char *mechs;
sasl_conn_t *server = NULL;
- rc = sasl_server_init( callbacks, "slapd" );
+ sasl_set_alloc( ch_malloc, ch_calloc, ch_realloc, ch_free );
+
+ sasl_set_mutex( sasl_pvt_mutex_new, sasl_pvt_mutex_lock,
+ sasl_pvt_mutex_unlock, sasl_pvt_mutex_dispose );
+
+ rc = sasl_server_init( NULL, "slapd" );
if( rc != SASL_OK ) {
Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n",
return 0;
}
+#ifdef HAVE_CYRUS_SASL
+int sasl_bind(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ char *ndn,
+ char *mech,
+ struct berval *cred,
+ char **edn)
+{
+ struct berval response;
+ const char *errstr;
+ int sc;
+ int rc = 1;
+
+ Debug(LDAP_DEBUG_ARGS, "==> sasl_bind: dn=%s, mech=%s, cred->bv_len=%d\n",
+ dn, mech, cred ? cred->bv_len : 0 );
+
+ if ( conn->c_sasl_context == NULL ) {
+ sasl_callback_t callbacks[4];
+ int cbnum = 0;
+
+ if (be->be_sasl_authorize) {
+ callbacks[cbnum].id = SASL_CB_PROXY_POLICY;
+ callbacks[cbnum].proc = be->be_sasl_authorize;
+ callbacks[cbnum].context = be;
+ ++cbnum;
+ }
+
+ if (be->be_sasl_getsecret) {
+ callbacks[cbnum].id = SASL_CB_SERVER_GETSECRET;
+ callbacks[cbnum].proc = be->be_sasl_getsecret;
+ callbacks[cbnum].context = be;
+ ++cbnum;
+ }
+
+ if (be->be_sasl_putsecret) {
+ callbacks[cbnum].id = SASL_CB_SERVER_PUTSECRET;
+ callbacks[cbnum].proc = be->be_sasl_putsecret;
+ callbacks[cbnum].context = be;
+ ++cbnum;
+ }
+ callbacks[cbnum].id = SASL_CB_LIST_END;
+ callbacks[cbnum].proc = NULL;
+ callbacks[cbnum].context = NULL;
+
+ if ( sasl_server_new( "ldap", NULL, be->be_realm,
+ callbacks, SASL_SECURITY_LAYER, &conn->c_sasl_context ) != SASL_OK ) {
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
+ } else {
+ conn->c_authmech = ch_strdup( mech );
+ sc = sasl_server_start( conn->c_sasl_context, conn->c_authmech,
+ cred->bv_val, cred->bv_len, (char **)&response.bv_val,
+ (unsigned *)&response.bv_len, &errstr );
+ if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
+ send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
+ NULL, errstr, NULL, NULL );
+ }
+ }
+ } else {
+ sc = sasl_server_step( conn->c_sasl_context, cred->bv_val, cred->bv_len,
+ (char **)&response.bv_val, (unsigned *)&response.bv_len, &errstr );
+ if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
+ send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
+ NULL, errstr, NULL, NULL );
+ }
+ }
+ if ( sc == SASL_OK ) {
+ char *authzid;
+
+ if ( ( sc = sasl_getprop( conn->c_sasl_context, SASL_USERNAME,
+ (void **)&authzid ) ) != SASL_OK ) {
+ send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
+ NULL, NULL, NULL, NULL );
+ } else {
+ if ( *edn != NULL ) {
+ free( *edn );
+ }
+ if ( strcasecmp( authzid, "anonymous" ) == 0 ) {
+ *edn = ch_strdup( "" );
+ } else {
+ *edn = ch_malloc( strlen( authzid ) + sizeof( "authzid=" ) );
+ strcpy( *edn, "authzid=" );
+ strcat( *edn, authzid );
+ }
+ /* let FE send result */
+ rc = 0;
+ }
+ } else if ( sc == SASL_CONTINUE ) {
+ /*
+ * We set c_bind_in_progress because it doesn't appear
+ * that connection.c sets this (unless do_bind() itself
+ * returns LDAP_SASL_BIND_IN_PROGRESS).
+ */
+ conn->c_bind_in_progress = 1;
+ send_ldap_sasl( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ /* matched */ NULL, /* text */ NULL, /* refs */ NULL, /* controls */ NULL, &response );
+ }
+
+ Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: rc=%d\n", rc, 0, 0);
+
+ return rc;
+}
+#endif /* HAVE_CYRUS_SASL */
+
#else
/* no SASL support */
int sasl_init( void ) { return 0; }
#define be_index_attr bd_info->bi_tool_index_attr
#define be_index_change bd_info->bi_tool_index_change
#define be_sync bd_info->bi_tool_sync
+#endif
+
+#ifdef HAVE_CYRUS_SASL
+#define be_sasl_authorize bd_info->bi_sasl_authorize
+#define be_sasl_getsecret bd_info->bi_sasl_getsecret
+#define be_sasl_putsecret bd_info->bi_sasl_putsecret
#endif
/* these should be renamed from be_ to bd_ */
struct berval **bv, ID id, int op ));
int (*bi_tool_sync) LDAP_P(( BackendDB *be ));
+#ifdef HAVE_CYRUS_SASL
+ int (*bi_sasl_authorize) LDAP_P(( BackendDB *be,
+ const char *authnid, const char *authzid,
+ const char **canon_authzid, const char **errstr ));
+ int (*bi_sasl_getsecret) LDAP_P(( BackendDB *be,
+ const char *mechanism, const char *authzid,
+ const char *realm, sasl_secret_t **secret ));
+ int (*bi_sasl_putsecret) LDAP_P(( BackendDB *be,
+ const char *mechanism, const char *auth_identity,
+ const char *realm, const sasl_secret_t *secret ));
+#endif /* HAVE_CYRUS_SASL */
+
#define SLAP_INDEX_ADD_OP 0x0001
#define SLAP_INDEX_DELETE_OP 0x0002
int sasl_destroy(void) {
return 0;
}
+
+#ifdef HAVE_CYRUS_SASL
+int sasl_bind(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ char *ndn,
+ char *mech,
+ struct berval *cred,
+ char **edn)
+{
+ return -1;
+}
+#endif