Commit 50299d90 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Update saslauthz code

parent 68b72f35
......@@ -860,6 +860,8 @@ LDAP_SLAPD_F (int) slap_sasl_authorized LDAP_P((
LDAP_SLAPD_F (int) slap_sasl_regexp_config LDAP_P((
const char *match, const char *replace ));
LDAP_SLAPD_F (int) slap_sasl_setpolicy LDAP_P(( const char * ));
LDAP_SLAPD_F (slap_response) slap_cb_null_response;
LDAP_SLAPD_F (slap_sresult) slap_cb_null_sresult;
/*
......
......@@ -458,7 +458,77 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
}
#if SASL_VERSION_MAJOR >= 2
static const char *slap_propnames[] = { "*authcDN", "*authzDN", NULL };
static const char *slap_propnames[] = {
"*slapConn", "*authcDN", "*authzDN", NULL };
static Filter *generic_filter;
#define PROP_CONN 0
#define PROP_AUTHC 1
#define PROP_AUTHZ 2
typedef struct lookup_info {
int last;
int flags;
const struct propval *list;
sasl_server_params_t *sparams;
} lookup_info;
static int
sasl_ap_lookup(
BackendDB *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeName *an,
int attrsonly,
LDAPControl **ctrls )
{
BerVarray bv;
AttributeDescription *ad;
Attribute *a;
const char *text;
int rc, i;
slap_callback *tmp = op->o_callback;
lookup_info *sl = tmp->sc_private;
for( i = 0; i < sl->last; i++ ) {
const char *name = sl->list[i].name;
if ( name[0] == '*' ) {
if ( sl->flags & SASL_AUXPROP_AUTHZID ) continue;
name++;
} else if ( !(sl->flags & SASL_AUXPROP_AUTHZID ) )
continue;
if ( sl->list[i].values ) {
if ( !(sl->flags & SASL_AUXPROP_OVERRIDE) ) continue;
}
ad = NULL;
rc = slap_str2ad( name, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, DETAIL1,
"slap_auxprop: str2ad(%s): %s\n", name, text, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"slap_auxprop: str2ad(%s): %s\n", name, text, 0 );
#endif
continue;
}
a = attr_find( e->e_attrs, ad );
if ( !a ) continue;
if ( ! access_allowed( be, conn, op, e, ad, NULL, ACL_AUTH, NULL ) )
continue;
if ( sl->list[i].values && ( sl->flags & SASL_AUXPROP_OVERRIDE ) )
sl->sparams->utils->prop_erase( sl->sparams->propctx, sl->list[i].name );
for ( bv = a->a_vals; bv->bv_val; bv++ ) {
sl->sparams->utils->prop_set( sl->sparams->propctx, sl->list[i].name,
bv->bv_val, bv->bv_len );
}
}
return LDAP_SUCCESS;
}
static void
slap_auxprop_lookup(
......@@ -468,29 +538,35 @@ slap_auxprop_lookup(
const char *user,
unsigned ulen)
{
int rc, i, last;
int rc, i, doit=0;
struct berval dn;
const struct propval *list;
BerVarray vals, bv;
AttributeDescription *ad;
const char *text;
list = sparams->utils->prop_get( sparams->propctx );
/* Find our DN first */
for( i = 0, last = 0; list[i].name; i++ ) {
if ( list[i].name[0] == '*' ) {
Connection *conn = NULL;
lookup_info sl;
sl.list = sparams->utils->prop_get( sparams->propctx );
sl.sparams = sparams;
sl.flags = flags;
/* Find our DN and conn first */
for( i = 0, sl.last = 0; sl.list[i].name; i++ ) {
if ( sl.list[i].name[0] == '*' ) {
if ( !strcmp( sl.list[i].name, slap_propnames[PROP_CONN] ) ) {
if ( sl.list[i].values && sl.list[i].values[0] )
AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) );
if ( !sl.last ) sl.last = i;
}
if ( (flags & SASL_AUXPROP_AUTHZID) &&
!strcmp( list[i].name, slap_propnames[1] ) ) {
if ( list[i].values && list[i].values[0] )
AC_MEMCPY( &dn, list[i].values[0], sizeof( dn ) );
if ( !last ) last = i;
!strcmp( sl.list[i].name, slap_propnames[PROP_AUTHZ] ) ) {
if ( sl.list[i].values && sl.list[i].values[0] )
AC_MEMCPY( &dn, sl.list[i].values[0], sizeof( dn ) );
if ( !sl.last ) sl.last = i;
break;
}
if ( !strcmp( list[i].name, slap_propnames[0] ) ) {
if ( !last ) last = i;
if ( list[i].values && list[i].values[0] ) {
AC_MEMCPY( &dn, list[i].values[0], sizeof( dn ) );
if ( !strcmp( sl.list[i].name, slap_propnames[PROP_AUTHC] ) ) {
if ( !sl.last ) sl.last = i;
if ( sl.list[i].values && sl.list[i].values[0] ) {
AC_MEMCPY( &dn, sl.list[i].values[0], sizeof( dn ) );
if ( !(flags & SASL_AUXPROP_AUTHZID) )
break;
}
......@@ -498,9 +574,9 @@ slap_auxprop_lookup(
}
}
/* Now fetch the rest */
for( i = 0; i < last; i++ ) {
const char *name = list[i].name;
/* Now see what else needs to be fetched */
for( i = 0; i < sl.last; i++ ) {
const char *name = sl.list[i].name;
if ( name[0] == '*' ) {
if ( flags & SASL_AUXPROP_AUTHZID ) continue;
......@@ -508,30 +584,34 @@ slap_auxprop_lookup(
} else if ( !(flags & SASL_AUXPROP_AUTHZID ) )
continue;
if ( list[i].values ) {
if ( sl.list[i].values ) {
if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue;
sparams->utils->prop_erase( sparams->propctx, list[i].name );
}
ad = NULL;
rc = slap_str2ad( name, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, DETAIL1,
"slap_auxprop: str2ad(%s): %s\n", name, text, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"slap_auxprop: str2ad(%s): %s\n", name, text, 0 );
#endif
rc = slap_str2undef_ad( name, &ad, &text );
if ( rc != LDAP_SUCCESS ) continue;
}
rc = backend_attribute( NULL,NULL,NULL,NULL, &dn, ad, &vals );
if ( rc != LDAP_SUCCESS ) continue;
for ( bv = vals; bv->bv_val; bv++ ) {
sparams->utils->prop_set( sparams->propctx, list[i].name,
bv->bv_val, bv->bv_len );
doit = 1;
}
if (doit) {
Backend *be;
Operation op = {0};
slap_callback cb = { slap_cb_null_response,
slap_cb_null_sresult, sasl_ap_lookup, NULL };
cb.sc_private = &sl;
be = select_backend( &dn, 0, 1 );
if ( be && be->be_search ) {
op.o_tag = LDAP_REQ_SEARCH;
op.o_protocol = LDAP_VERSION3;
op.o_ndn = conn->c_ndn;
op.o_callback = &cb;
op.o_time = slap_get_time();
op.o_do_not_cache = 1;
(*be->be_search)( be, conn, &op, NULL, &dn,
LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
generic_filter, NULL, NULL, 0 );
}
ber_bvarray_free( vals );
}
}
......@@ -562,6 +642,42 @@ slap_auxprop_init(
return SASL_OK;
}
typedef struct checkpass_info {
int rc;
struct berval cred;
} checkpass_info;
static int
sasl_cb_checkpass(
BackendDB *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeName *an,
int attrsonly,
LDAPControl **ctrls )
{
slap_callback *tmp = op->o_callback;
checkpass_info *ci = tmp->sc_private;
Attribute *a;
struct berval *bv;
ci->rc = SASL_NOVERIFY;
a = attr_find( e->e_attrs, slap_schema.si_ad_userPassword );
if ( !a ) return 0;
if ( ! access_allowed( be, conn, op, e, slap_schema.si_ad_userPassword,
NULL, ACL_AUTH, NULL ) ) return 0;
for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
if ( !lutil_passwd( bv, &ci->cred, NULL ) ) {
ci->rc = SASL_OK;
break;
}
}
return 0;
}
static int
slap_sasl_checkpass(
sasl_conn_t *sconn,
......@@ -572,12 +688,12 @@ slap_sasl_checkpass(
struct propctx *propctx)
{
Connection *conn = (Connection *)context;
struct berval dn, cred;
struct berval dn;
int rc;
BerVarray vals, bv;
Backend *be;
checkpass_info ci;
cred.bv_val = (char *)pass;
cred.bv_len = passlen;
ci.rc = SASL_NOUSER;
/* SASL will fallback to its own mechanisms if we don't
* find an answer here.
......@@ -599,34 +715,35 @@ slap_sasl_checkpass(
return SASL_NOUSER;
}
rc = backend_attribute( NULL, NULL, NULL, NULL, &dn,
slap_schema.si_ad_userPassword, &vals);
if ( rc != LDAP_SUCCESS ) {
ch_free( dn.bv_val );
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
return SASL_NOVERIFY;
}
rc = SASL_NOVERIFY;
if ( vals != NULL ) {
for ( bv = vals; bv->bv_val != NULL; bv++ ) {
if ( !lutil_passwd( bv, &cred, NULL ) ) {
rc = SASL_OK;
break;
}
}
ber_bvarray_free( vals );
be = select_backend( &dn, 0, 1 );
if ( be && be->be_search ) {
Operation op = {0};
slap_callback cb = { slap_cb_null_response,
slap_cb_null_sresult, sasl_cb_checkpass, NULL };
ci.cred.bv_val = (char *)pass;
ci.cred.bv_len = passlen;
cb.sc_private = &ci;
op.o_tag = LDAP_REQ_SEARCH;
op.o_protocol = LDAP_VERSION3;
op.o_ndn = conn->c_ndn;
op.o_callback = &cb;
op.o_time = slap_get_time();
op.o_do_not_cache = 1;
(*be->be_search)( be, conn, &op, NULL, &dn,
LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
generic_filter, NULL, NULL, 0 );
}
if ( rc != SASL_OK ) {
if ( ci.rc != SASL_OK ) {
sasl_seterror( sconn, 0,
ldap_err2string( LDAP_INVALID_CREDENTIALS ) );
}
ch_free( dn.bv_val );
return rc;
return ci.rc;
}
/* Convert a SASL authcid or authzid into a DN. Store the DN in an
......@@ -681,10 +798,17 @@ slap_sasl_canonicalize(
prop_request( props, slap_propnames );
if ( flags & SASL_CU_AUTHID )
which = 0;
which = PROP_AUTHC;
else
which = 1;
which = PROP_AUTHZ;
/* Need to store the Connection for auxprop_lookup */
if ( !auxvals[PROP_CONN].values ) {
names[0] = slap_propnames[PROP_CONN];
names[1] = NULL;
prop_set( props, names[0], (char *)&conn, sizeof( conn ) );
}
/* Already been here? */
if ( auxvals[which].values )
goto done;
......@@ -764,7 +888,8 @@ slap_sasl_authorize(
conn->c_sasl_dn.bv_len = 0;
}
prop_getnames( props, slap_propnames, auxvals );
/* Skip PROP_CONN */
prop_getnames( props, slap_propnames+1, auxvals );
AC_MEMCPY( &authcDN, auxvals[0].values[0], sizeof(authcDN) );
......@@ -965,10 +1090,10 @@ int slap_sasl_init( void )
};
sasl_set_alloc(
ch_malloc,
ch_calloc,
ch_realloc,
ch_free );
ber_memalloc,
ber_memcalloc,
ber_memrealloc,
ber_memfree );
sasl_set_mutex(
ldap_pvt_sasl_mutex_new,
......@@ -1016,6 +1141,9 @@ int slap_sasl_destroy( void )
{
#ifdef HAVE_CYRUS_SASL
sasl_done();
#endif
#if SASL_VERSION_MAJOR >= 2
filter_free( generic_filter );
#endif
free( global_host );
global_host = NULL;
......@@ -1076,6 +1204,9 @@ int slap_sasl_open( Connection *conn )
/* create new SASL context */
#if SASL_VERSION_MAJOR >= 2
if ( generic_filter == NULL ) {
generic_filter = str2filter( "(objectclass=*)" );
}
if ( conn->c_sock_name.bv_len != 0 &&
strncmp( conn->c_sock_name.bv_val, "IP=", 3 ) == 0) {
char *p;
......
......@@ -98,7 +98,7 @@ static int slap_parseURI( struct berval *uri,
bv.bv_val = uri->bv_val + sizeof("dn:")-1;
bv.bv_val += strspn( bv.bv_val, " " );
is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
rc = dnNormalize2( NULL, &bv, searchbase );
if( rc == LDAP_SUCCESS ) {
......@@ -334,14 +334,14 @@ static int slap_sasl_regexp( struct berval *in, struct berval *out )
}
/* Two empty callback functions to avoid sending results */
static void sasl_sc_r( Connection *conn, Operation *o, ber_tag_t tag,
void slap_cb_null_response( Connection *conn, Operation *o, ber_tag_t tag,
ber_int_t msgid, ber_int_t err, const char *matched,
const char *text, BerVarray ref, const char *resoid,
struct berval *resdata, struct berval *sasldata, LDAPControl **c)
{
}
static void sasl_sc_s( Connection *conn, Operation *o, ber_int_t err,
void slap_cb_null_sresult( Connection *conn, Operation *o, ber_int_t err,
const char *matched, const char *text, BerVarray refs, LDAPControl **c,
int nentries)
{
......@@ -389,7 +389,7 @@ void slap_sasl2dn( Connection *conn,
struct berval dn = { 0, NULL };
int scope = LDAP_SCOPE_BASE;
Filter *filter = NULL;
slap_callback cb = {sasl_sc_r, sasl_sc_s, sasl_sc_sasl2dn, NULL};
slap_callback cb = {slap_cb_null_response, slap_cb_null_sresult, sasl_sc_sasl2dn, NULL};
Operation op = {0};
struct berval regout = { 0, NULL };
......@@ -509,7 +509,7 @@ int slap_sasl_match(Connection *conn, struct berval *rule, struct berval *assert
Filter *filter=NULL;
regex_t reg;
smatch_info sm;
slap_callback cb = { sasl_sc_r, sasl_sc_s, sasl_sc_smatch, NULL };
slap_callback cb = { slap_cb_null_response, slap_cb_null_sresult, sasl_sc_smatch, NULL };
Operation op = {0};
#ifdef NEW_LOGGING
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment