/*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
/*
#include "slap.h"
-#ifdef HAVE_CYRUS_SASL
#include <limits.h>
-#ifdef HAVE_SASL_SASL_H
-#include <sasl/sasl.h>
-#else
-#include <sasl.h>
-#endif
-
#include <ldap_pvt.h>
#define SASLREGEX_REPLACE 10
{
int rc = LDAP_SUCCESS;
- if ( strcasecmp( arg, "none" ) == 0 )
+ if ( strcasecmp( arg, "none" ) == 0 ) {
authz_policy = SASL_AUTHZ_NONE;
- else if ( strcasecmp( arg, "from" ) == 0 )
+ } else if ( strcasecmp( arg, "from" ) == 0 ) {
authz_policy = SASL_AUTHZ_FROM;
- else if ( strcasecmp( arg, "to" ) == 0 )
+ } else if ( strcasecmp( arg, "to" ) == 0 ) {
authz_policy = SASL_AUTHZ_TO;
- else if ( strcasecmp( arg, "both" ) == 0 )
+ } else if ( strcasecmp( arg, "both" ) == 0 ) {
authz_policy = SASL_AUTHZ_FROM | SASL_AUTHZ_TO;
- else
+ } else {
rc = LDAP_OTHER;
+ }
return rc;
}
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 ) {
SaslRegexp = (SaslRegexp_t *) ch_realloc( (char *) SaslRegexp,
(nSaslRegexp + 1) * sizeof(SaslRegexp_t) );
+ reg = &SaslRegexp[nSaslRegexp];
+
reg->sr_match = ch_strdup( match );
reg->sr_replace = ch_strdup( replace );
static int slap_sasl_regexp( struct berval *in, struct berval *out )
{
char *saslname = in->bv_val;
- char *scope[] = { "base", "one", "sub" };
SaslRegexp_t *reg;
int i;
saslname, 0, 0 );
#endif
- if (( saslname == NULL ) || ( nSaslRegexp == 0 ))
+ if (( saslname == NULL ) || ( nSaslRegexp == 0 )) {
return( 0 );
+ }
/* Match the normalized SASL name to the saslregexp patterns */
for( reg = SaslRegexp,i=0; i<nSaslRegexp; i++,reg++ ) {
break;
}
- if( i >= nSaslRegexp )
- return( 0 );
+ if( i >= nSaslRegexp ) return( 0 );
/*
* The match pattern may have been of the form "a(b.*)c(d.*)e" and the
out->bv_len ? out->bv_val : "", 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "slap_sasl_regexp: converted SASL name to ldap:///%s??%s?%s\n",
+ "slap_sasl_regexp: converted SASL name to %s\n",
out->bv_len ? out->bv_val : "", 0, 0 );
#endif
}
/* 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)
{
}
+int slap_cb_null_sreference( BackendDB *db, Connection *conn, Operation *o,
+ Entry *e, BerVarray r, LDAPControl **c, BerVarray *v2)
+{
+ return 0;
+}
+
/* This callback actually does some work...*/
static int sasl_sc_sasl2dn( BackendDB *be, Connection *conn, Operation *o,
Entry *e, AttributeName *an, int ao, LDAPControl **c)
ndn->bv_val = NULL;
#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, DETAIL1,
- "slap_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
+ LDAP_LOG( TRANSPORT, DETAIL1,
+ "slap_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"slap_sasl2dn: search DN returned more than 1 entry\n", 0,0,0 );
return 0;
}
-/*
- * Given a SASL name (e.g. "UID=name,cn=REALM,cn=MECH,cn=AUTH")
- * return the LDAP DN to which it matches. The SASL regexp rules in the config
- * file turn the SASL name into an LDAP URI. If the URI is just a DN (or a
- * search with scope=base), just return the URI (or its searchbase). Otherwise
- * an internal search must be done, and if that search returns exactly one
- * entry, return the DN of that one entry.
- */
-
-void slap_sasl2dn( Connection *conn,
- struct berval *saslname, struct berval *sasldn )
-{
- int rc;
- Backend *be;
- 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};
- Operation op = {0};
- struct berval regout = { 0, NULL };
-
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, ENTRY,
- "slap_sasl2dn: converting SASL name %s to DN.\n",
- saslname->bv_val, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE, "==>slap_sasl2dn: "
- "converting SASL name %s to a DN\n",
- saslname->bv_val, 0,0 );
-#endif
-
- sasldn->bv_val = NULL;
- sasldn->bv_len = 0;
- cb.sc_private = sasldn;
-
- /* Convert the SASL name into a minimal URI */
- if( !slap_sasl_regexp( saslname, ®out ) ) {
- goto FINISHED;
- }
-
- rc = slap_parseURI( ®out, &dn, &scope, &filter );
- if( rc != LDAP_SUCCESS ) {
- goto FINISHED;
- }
-
- /* Must do an internal search */
- be = select_backend( &dn, 0, 1 );
-
- /* Massive shortcut: search scope == base */
- if( scope == LDAP_SCOPE_BASE ) {
- *sasldn = dn;
- dn.bv_len = 0;
- dn.bv_val = NULL;
- goto FINISHED;
- }
-
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, DETAIL1,
- "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
- dn.bv_val, scope, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
- dn.bv_val, scope, 0 );
-#endif
-
- if(( be == NULL ) || ( be->be_search == NULL)) {
- goto FINISHED;
- }
- suffix_alias( be, &dn );
-
- op.o_tag = LDAP_REQ_SEARCH;
- op.o_protocol = LDAP_VERSION3;
- op.o_ndn = *saslname;
- op.o_callback = &cb;
- op.o_time = slap_get_time();
- op.o_do_not_cache = 1;
-
- (*be->be_search)( be, conn, &op, NULL, &dn,
- scope, LDAP_DEREF_NEVER, 1, 0,
- filter, NULL, NULL, 1 );
-
-FINISHED:
- if( sasldn->bv_len ) {
- conn->c_authz_backend = be;
- }
- if( dn.bv_len ) ch_free( dn.bv_val );
- if( filter ) filter_free( filter );
-
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, ENTRY,
- "slap_sasl2dn: Converted SASL name to %s\n",
- sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE, "<==slap_sasl2dn: Converted SASL name to %s\n",
- sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
-#endif
-
- return;
-}
typedef struct smatch_info {
struct berval *dn;
if (dn_match(sm->dn, &e->e_nname)) {
sm->match = 1;
return -1; /* short-circuit the search */
- } else {
- return 1;
}
+
+ return 1;
}
/*
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
assertDN->bv_val, rule->bv_val,0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "===>slap_sasl_match: comparing DN %s to rule %s\n", assertDN->bv_val, rule->bv_val, 0 );
+ "===>slap_sasl_match: comparing DN %s to rule %s\n",
+ assertDN->bv_val, rule->bv_val, 0 );
#endif
rc = slap_parseURI( rule, &searchbase, &scope, &filter );
- if( rc != LDAP_SUCCESS )
- goto CONCLUDED;
+ if( rc != LDAP_SUCCESS ) goto CONCLUDED;
/* Massive shortcut: search scope == base */
if( scope == LDAP_SCOPE_BASE ) {
rc = regexec(®, assertDN->bv_val, 0, NULL, 0);
regfree( ® );
}
- if ( rc == 0 )
+ if ( rc == 0 ) {
rc = LDAP_SUCCESS;
- else
+ } else {
rc = LDAP_INAPPROPRIATE_AUTH;
+ }
goto CONCLUDED;
}
rc = LDAP_INAPPROPRIATE_AUTH;
goto CONCLUDED;
}
- suffix_alias( be, &searchbase );
sm.dn = assertDN;
sm.match = 0;
op.o_callback = &cb;
op.o_time = slap_get_time();
op.o_do_not_cache = 1;
+ op.o_is_auth_check = 1;
+ op.o_threadctx = conn->c_sasl_bindop->o_threadctx;
(*be->be_search)( be, conn, &op, /*base=*/NULL, &searchbase,
scope, /*deref=*/1, /*sizelimit=*/0, /*time=*/0, filter, /*fstr=*/NULL,
/*attrs=*/NULL, /*attrsonly=*/0 );
- if (sm.match)
+ if (sm.match) {
rc = LDAP_SUCCESS;
- else
+ } else {
rc = LDAP_INAPPROPRIATE_AUTH;
+ }
CONCLUDED:
if( searchbase.bv_len ) ch_free( searchbase.bv_val );
if( filter ) filter_free( filter );
+
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, ENTRY,
"slap_sasl_match: comparison returned %d\n", rc, 0, 0 );
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, ENTRY,
- "slap_sasl_check_authz: does %s match %s rule in %s?\n",
- assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
+ "slap_sasl_check_authz: does %s match %s rule in %s?\n",
+ assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
#else
Debug( LDAP_DEBUG_TRACE,
"==>slap_sasl_check_authz: does %s match %s rule in %s?\n",
assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
#endif
- rc = backend_attribute( NULL, NULL, NULL, NULL, searchDN, ad, &vals );
- if( rc != LDAP_SUCCESS )
- goto COMPLETE;
+ rc = backend_attribute( NULL, NULL, conn->c_sasl_bindop, NULL,
+ searchDN, ad, &vals );
+ if( rc != LDAP_SUCCESS ) goto COMPLETE;
/* Check if the *assertDN matches any **vals */
for( i=0; vals[i].bv_val != NULL; i++ ) {
rc = slap_sasl_match( conn, &vals[i], assertDN, authc );
- if ( rc == LDAP_SUCCESS )
- goto COMPLETE;
+ if ( rc == LDAP_SUCCESS ) goto COMPLETE;
}
rc = LDAP_INAPPROPRIATE_AUTH;
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, RESULTS,
- "slap_sasl_check_authz: %s check returning %s\n",
- ad->ad_cname.bv_val, rc, 0 );
+ "slap_sasl_check_authz: %s check returning %s\n",
+ ad->ad_cname.bv_val, rc, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "<==slap_sasl_check_authz: %s check returning %d\n", ad->ad_cname.bv_val, rc, 0);
+ "<==slap_sasl_check_authz: %s check returning %d\n",
+ ad->ad_cname.bv_val, rc, 0);
#endif
return( rc );
}
-#endif /* HAVE_CYRUS_SASL */
+
+/*
+ * Given a SASL name (e.g. "UID=name,cn=REALM,cn=MECH,cn=AUTH")
+ * return the LDAP DN to which it matches. The SASL regexp rules in the config
+ * file turn the SASL name into an LDAP URI. If the URI is just a DN (or a
+ * search with scope=base), just return the URI (or its searchbase). Otherwise
+ * an internal search must be done, and if that search returns exactly one
+ * entry, return the DN of that one entry.
+ */
+void slap_sasl2dn( Connection *conn,
+ struct berval *saslname, struct berval *sasldn )
+{
+ int rc;
+ Backend *be = NULL;
+ struct berval dn = { 0, NULL };
+ int scope = LDAP_SCOPE_BASE;
+ Filter *filter = NULL;
+ slap_callback cb = { slap_cb_null_response,
+ slap_cb_null_sresult, sasl_sc_sasl2dn, slap_cb_null_sreference, NULL};
+ Operation op = {0};
+ struct berval regout = { 0, NULL };
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, ENTRY,
+ "slap_sasl2dn: converting SASL name %s to DN.\n",
+ saslname->bv_val, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "==>slap_sasl2dn: "
+ "converting SASL name %s to a DN\n",
+ saslname->bv_val, 0,0 );
+#endif
+
+ sasldn->bv_val = NULL;
+ sasldn->bv_len = 0;
+ cb.sc_private = sasldn;
+
+ /* Convert the SASL name into a minimal URI */
+ if( !slap_sasl_regexp( saslname, ®out ) ) {
+ goto FINISHED;
+ }
+
+ rc = slap_parseURI( ®out, &dn, &scope, &filter );
+ if( regout.bv_val ) ch_free( regout.bv_val );
+ if( rc != LDAP_SUCCESS ) {
+ goto FINISHED;
+ }
+
+ /* Must do an internal search */
+ be = select_backend( &dn, 0, 1 );
+
+ /* Massive shortcut: search scope == base */
+ if( scope == LDAP_SCOPE_BASE ) {
+ *sasldn = dn;
+ dn.bv_len = 0;
+ dn.bv_val = NULL;
+ goto FINISHED;
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, DETAIL1,
+ "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
+ dn.bv_val, scope, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
+ dn.bv_val, scope, 0 );
+#endif
+
+ if(( be == NULL ) || ( be->be_search == NULL)) {
+ goto FINISHED;
+ }
+
+ 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;
+ op.o_is_auth_check = 1;
+ op.o_threadctx = conn->c_sasl_bindop ? conn->c_sasl_bindop->o_threadctx:
+ ldap_pvt_thread_pool_context( &connection_pool );
+
+ (*be->be_search)( be, conn, &op, NULL, &dn,
+ scope, LDAP_DEREF_NEVER, 1, 0,
+ filter, NULL, NULL, 1 );
+
+FINISHED:
+ if( sasldn->bv_len ) {
+ conn->c_authz_backend = be;
+ }
+ if( dn.bv_len ) ch_free( dn.bv_val );
+ if( filter ) filter_free( filter );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, ENTRY,
+ "slap_sasl2dn: Converted SASL name to %s\n",
+ sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "<==slap_sasl2dn: Converted SASL name to %s\n",
+ sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
+#endif
+
+ return;
+}
/* Check if a bind can SASL authorize to another identity.
{
int rc = LDAP_INAPPROPRIATE_AUTH;
-#ifdef HAVE_CYRUS_SASL
/* User binding as anonymous */
if ( authzDN == NULL ) {
rc = LDAP_SUCCESS;
authcDN->bv_val, authzDN->bv_val, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "==>slap_sasl_authorized: can %s become %s?\n", authcDN->bv_val, authzDN->bv_val, 0 );
+ "==>slap_sasl_authorized: can %s become %s?\n",
+ authcDN->bv_val, authzDN->bv_val, 0 );
#endif
/* If person is authorizing to self, succeed */
goto DONE;
}
+ /* Allow the manager to authorize as any DN. */
+ if( conn->c_authz_backend && be_isroot( conn->c_authz_backend, authcDN )) {
+ rc = LDAP_SUCCESS;
+ goto DONE;
+ }
+
/* Check source rules */
if( authz_policy & SASL_AUTHZ_TO ) {
rc = slap_sasl_check_authz( conn, authcDN, authzDN,
rc = LDAP_INAPPROPRIATE_AUTH;
DONE:
-#endif
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, RESULTS, "slap_sasl_authorized: return %d\n", rc,0,0 );