# define SASL_CONST
# endif
-static sasl_security_properties_t sasl_secprops;
-
#define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\
(SASL_VERSION_MINOR << 8) | SASL_VERSION_STEP)
-#endif /* HAVE_CYRUS_SASL */
+static sasl_security_properties_t sasl_secprops;
+#elif defined( SLAP_BUILTIN_SASL )
+/*
+ * built-in SASL implementation
+ * only supports EXTERNAL
+ */
+typedef struct sasl_ctx {
+ slap_ssf_t sc_external_ssf;
+ struct berval sc_external_id;
+} SASL_CTX;
+
+#endif
#include "ldap_pvt.h"
#include "lber_pvt.h"
#include <lutil.h>
+static struct berval ext_bv = BER_BVC( "EXTERNAL" );
+
int slap_sasl_config( int cargc, char **cargv, char *line,
const char *fname, int lineno )
{
sasl_server_params_t *sparams;
} lookup_info;
-static slap_response sasl_ap_lookup, sasl_ap_store, sasl_cb_checkpass;
+static slap_response sasl_ap_lookup, sasl_cb_checkpass;
static int
sasl_ap_lookup( Operation *op, SlapReply *rs )
unsigned ulen)
{
Operation op = {0};
- int rc, i, doit=0;
+ int i, doit = 0;
Connection *conn = NULL;
lookup_info sl;
}
if (doit) {
- slap_callback cb = { sasl_ap_lookup, NULL };
+ slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL };
cb.sc_private = &sl;
}
#if SASL_VERSION_FULL >= 0x020110
-static int
-sasl_ap_store( Operation *op, SlapReply *rs )
-{
- return 0;
-}
-
static int
slap_auxprop_store(
void *glob_context,
Connection *conn = NULL;
const struct propval *pr;
Modifications *modlist = NULL, **modtail = &modlist, *mod;
- slap_callback cb = { sasl_ap_store, NULL };
+ slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
char textbuf[SLAP_TEXT_BUFLEN];
const char *text;
size_t textlen = sizeof(textbuf);
op.o_bd = select_backend( &op.o_req_ndn, 0, 1 );
if ( op.o_bd && op.o_bd->be_search ) {
- slap_callback cb = { sasl_cb_checkpass, NULL };
+ slap_callback cb = { NULL, sasl_cb_checkpass, NULL, NULL };
SlapReply rs = {REP_RESULT};
ci.cred.bv_val = (char *)pass;
* auxiliary property, so that we can refer to it in sasl_authorize
* without interfering with anything else. Also, the SASL username
* buffer is constrained to 256 characters, and our DNs could be
- * much longer (totally arbitrary length)...
+ * much longer (SLAP_LDAPDN_MAXLEN, currently set to 8192)
*/
static int
slap_sasl_canonicalize(
sasl_version( NULL, &rc );
if ( ((rc >> 16) != ((SASL_VERSION_MAJOR << 8)|SASL_VERSION_MINOR)) ||
- (rc & 0xffff) < SASL_VERSION_STEP) {
+ (rc & 0xffff) < SASL_VERSION_STEP)
+ {
char version[sizeof("xxx.xxx.xxxxx")];
sprintf( version, "%u.%d.%d", (unsigned)rc >> 24, (rc >> 16) & 0xff,
rc & 0xffff );
0, 0, 0 );
#endif
-
/* default security properties */
memset( &sasl_secprops, '\0', sizeof(sasl_secprops) );
sasl_secprops.max_ssf = INT_MAX;
int slap_sasl_open( Connection *conn, int reopen )
{
- int cb, sc = LDAP_SUCCESS;
-#if SASL_VERSION_MAJOR >= 2
- char *ipremoteport = NULL, *iplocalport = NULL;
-#endif
-
+ int sc = LDAP_SUCCESS;
#ifdef HAVE_CYRUS_SASL
+ int cb;
+
sasl_conn_t *ctx = NULL;
sasl_callback_t *session_callbacks;
+#if SASL_VERSION_MAJOR >= 2
+ char *ipremoteport = NULL, *iplocalport = NULL;
+#endif
+
assert( conn->c_sasl_authctx == NULL );
if ( !reopen ) {
}
sc = slap_sasl_err2ldap( sc );
+
+#elif defined(SLAP_BUILTIN_SASL)
+ /* built-in SASL implementation */
+ SASL_CTX *ctx = (SASL_CTX *) SLAP_MALLOC(sizeof(SASL_CTX));
+ if( ctx == NULL ) return -1;
+
+ ctx->sc_external_ssf = 0;
+ ctx->sc_external_id.bv_len = 0;
+ ctx->sc_external_id.bv_val = NULL;
+
+ conn->c_sasl_authctx = ctx;
#endif
+
return sc;
}
int slap_sasl_external(
Connection *conn,
slap_ssf_t ssf,
- const char *auth_id )
+ struct berval *auth_id )
{
#if SASL_VERSION_MAJOR >= 2
int sc;
return LDAP_OTHER;
}
- sc = sasl_setprop( ctx, SASL_AUTH_EXTERNAL, auth_id );
+ sc = sasl_setprop( ctx, SASL_AUTH_EXTERNAL,
+ auth_id ? auth_id->bv_val : NULL );
if ( sc != SASL_OK ) {
return LDAP_OTHER;
memset( &extprops, '\0', sizeof(extprops) );
extprops.ssf = ssf;
- extprops.auth_id = (char *) auth_id;
+ extprops.auth_id = auth_id ? auth_id->bv_val : NULL;
sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL,
(void *) &extprops );
if ( sc != SASL_OK ) {
return LDAP_OTHER;
}
+#elif defined(SLAP_BUILTIN_SASL)
+ /* built-in SASL implementation */
+ SASL_CTX *ctx = conn->c_sasl_authctx;
+ if ( ctx == NULL ) return LDAP_UNAVAILABLE;
+
+ ctx->sc_external_ssf = ssf;
+ if( auth_id ) {
+ ctx->sc_external_id = *auth_id;
+ auth_id->bv_len = 0;
+ auth_id->bv_val = NULL;
+ } else {
+ ctx->sc_external_id.bv_len = 0;
+ ctx->sc_external_id.bv_val = NULL;
+ }
#endif
return LDAP_SUCCESS;
ch_free( mechstr );
#endif
}
+#elif defined(SLAP_BUILTIN_SASL)
+ /* builtin SASL implementation */
+ SASL_CTX *ctx = conn->c_sasl_authctx;
+ if ( ctx != NULL && ctx->sc_external_id.bv_val ) {
+ /* should check ssf */
+ mechs = ldap_str2charray( "EXTERNAL", "," );
+ }
#endif
return mechs;
if( ctx != NULL ) {
sasl_dispose( &ctx );
}
- if ( conn->c_sasl_sockctx && conn->c_sasl_authctx != conn->c_sasl_sockctx ) {
+ if ( conn->c_sasl_sockctx &&
+ conn->c_sasl_authctx != conn->c_sasl_sockctx )
+ {
ctx = conn->c_sasl_sockctx;
sasl_dispose( &ctx );
}
free( conn->c_sasl_extra );
conn->c_sasl_extra = NULL;
+
+#elif defined(SLAP_BUILTIN_SASL)
+ SASL_CTX *ctx = conn->c_sasl_authctx;
+ if( ctx ) {
+ if( ctx->sc_external_id.bv_val ) {
+ free( ctx->sc_external_id.bv_val );
+ ctx->sc_external_id.bv_val = NULL;
+ }
+ free( ctx );
+ conn->c_sasl_authctx = NULL;
+ }
#endif
return LDAP_SUCCESS;
op->orb_cred.bv_len );
#endif
-
if( ctx == NULL ) {
send_ldap_error( op, rs, LDAP_UNAVAILABLE,
"SASL unavailable on this session" );
Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: rc=%d\n", rs->sr_err, 0, 0);
#endif
+#elif defined(SLAP_BUILTIN_SASL)
+ /* built-in SASL implementation */
+ SASL_CTX *ctx = op->o_conn->c_sasl_authctx;
+ if ( ctx == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "Internal SASL Error" );
+
+ } else if ( bvmatch( &ext_bv, &op->o_conn->c_sasl_bind_mech ) ) {
+ /* EXTERNAL */
+
+ if( op->orb_cred.bv_len ) {
+ rs->sr_text = "proxy authorization not support";
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ send_ldap_result( op, rs );
+
+ } else {
+ op->orb_edn = ctx->sc_external_id;
+ rs->sr_err = LDAP_SUCCESS;
+ rs->sr_sasldata = NULL;
+ send_ldap_sasl( op, rs );
+ }
+
+ } else {
+ send_ldap_error( op, rs, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ "requested SASL mechanism not supported" );
+ }
#else
- send_ldap_error( op, rs, LDAP_UNAVAILABLE,
+ send_ldap_error( op, rs, LDAP_AUTH_METHOD_NOT_SUPPORTED,
"SASL not supported" );
#endif
#define SET_DN 1
#define SET_U 2
-static struct berval ext_bv = BER_BVC( "EXTERNAL" );
-
int slap_sasl_getdn( Connection *conn, Operation *op, char *id, int len,
char *user_realm, struct berval *dn, int flags )
{
- char *c1;
int rc, is_dn = SET_NONE, do_norm = 1;
- struct berval dn2;
+ struct berval dn2, *mech;
+
+ assert( conn );
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, ENTRY,
"slap_sasl_getdn: conn %d id=%s [len=%d]\n",
- conn ? conn->c_connid : -1, id ? (*id ? id : "<empty>") : "NULL", len );
+ conn->c_connid, id ? (*id ? id : "<empty>") : "NULL", len );
#else
Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: id=%s [len=%d]\n",
id ? ( *id ? id : "<empty>" ) : "NULL", len, 0 );
len = 0;
}
+ if ( conn->c_sasl_bind_mech.bv_len ) {
+ mech = &conn->c_sasl_bind_mech;
+ } else {
+ mech = &conn->c_authmech;
+ }
+
/* An authcID needs to be converted to authzID form. Set the
* values directly into *dn; they will be normalized later. (and
* normalizing always makes a new copy.) An ID from a TLS certificate
* is already normalized, so copy it and skip normalization.
*/
if( flags & SLAP_GETDN_AUTHCID ) {
- if( conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len &&
- strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 )
- {
+ if( bvmatch( mech, &ext_bv )) {
/* EXTERNAL DNs are already normalized */
do_norm = 0;
is_dn = SET_DN;
/* Username strings */
if( is_dn == SET_U ) {
- char *p, *realm;
+ char *p;
+ struct berval realm = { 0, NULL }, c1 = *dn;
+
len = dn->bv_len + sizeof("uid=")-1 + sizeof(",cn=auth")-1;
+#if 0
/* username may have embedded realm name */
- if( ( realm = strchr( dn->bv_val, '@') ) ) {
- *realm++ = '\0';
- len += sizeof(",cn=")-2;
- } else if( user_realm && *user_realm ) {
- len += strlen( user_realm ) + sizeof(",cn=")-1;
+ /* FIXME:
+ * userids can legally have embedded '@' chars;
+ * the realm should be set by those mechanisms
+ * that support it by means of the user_realm
+ * variable
+ */
+ if( ( realm.bv_val = strrchr( dn->bv_val, '@') ) ) {
+ char *r = realm.bv_val;
+
+ realm.bv_val++;
+ realm.bv_len = dn->bv_len - ( realm.bv_val - dn->bv_val );
+ len += sizeof( ",cn=" ) - 2;
+ c1.bv_len -= realm.bv_len + 1;
+
+ if ( strchr( dn->bv_val, '@') == r ) {
+ /* FIXME: ambiguity, is it the realm
+ * or something else? */
+ }
+
+ } else
+#endif
+ if( user_realm && *user_realm ) {
+ realm.bv_val = user_realm;
+ realm.bv_len = strlen( user_realm );
+ len += realm.bv_len + sizeof(",cn=") - 1;
}
- if( conn->c_sasl_bind_mech.bv_len ) {
- len += conn->c_sasl_bind_mech.bv_len + sizeof(",cn=")-1;
+ if( mech->bv_len ) {
+ len += mech->bv_len + sizeof(",cn=")-1;
}
/* Build the new dn */
- c1 = dn->bv_val;
dn->bv_val = sl_malloc( len+1, op->o_tmpmemctx );
if( dn->bv_val == NULL ) {
#ifdef NEW_LOGGING
return LDAP_OTHER;
}
p = lutil_strcopy( dn->bv_val, "uid=" );
- p = lutil_strncopy( p, c1, dn->bv_len );
+ p = lutil_strncopy( p, c1.bv_val, c1.bv_len );
- if( realm ) {
- int rlen = dn->bv_len - ( realm - c1 );
- p = lutil_strcopy( p, ",cn=" );
- p = lutil_strncopy( p, realm, rlen );
- realm[-1] = '@';
- } else if( user_realm && *user_realm ) {
+ if( realm.bv_len ) {
p = lutil_strcopy( p, ",cn=" );
- p = lutil_strcopy( p, user_realm );
+ p = lutil_strncopy( p, realm.bv_val, realm.bv_len );
}
- if( conn->c_sasl_bind_mech.bv_len ) {
+ if( mech->bv_len ) {
p = lutil_strcopy( p, ",cn=" );
- p = lutil_strcopy( p, conn->c_sasl_bind_mech.bv_val );
+ p = lutil_strcopy( p, mech->bv_val );
}
p = lutil_strcopy( p, ",cn=auth" );
dn->bv_len = p - dn->bv_val;
LDAP_LOG( TRANSPORT, ENTRY,
"slap_sasl_getdn: u:id converted to %s.\n", dn->bv_val, 0, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "getdn: u:id converted to %s\n", dn->bv_val,0,0 );
+ Debug( LDAP_DEBUG_TRACE, "slap_sasl_getdn: u:id converted to %s\n", dn->bv_val,0,0 );
#endif
} else {
}
/* Run thru regexp */
- slap_sasl2dn( op, dn, &dn2 );
+ slap_sasl2dn( op, dn, &dn2, flags );
if( dn2.bv_val ) {
sl_free( dn->bv_val, op->o_tmpmemctx );
*dn = dn2;