Added sasl-authz-policy config keyword to control proxy authorization.
Moved sasl-related config processing to sasl.c:slap_sasl_config().
Moved other global defs used only in saslauthz.c into saslauthz.c.
char *strtok_quote_ptr;
-int nSaslRegexp = 0;
-SaslRegexp_t *SaslRegexp = NULL;
-
#ifdef SLAPD_RLOOKUPS
int use_reverse_lookup = 1;
#else /* !SLAPD_RLOOKUPS */
lutil_salt_format( cargv[1] );
- /* set SASL host */
- } else if ( strcasecmp( cargv[0], "sasl-host" ) == 0 ) {
- if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: missing host in \"sasl-host <host>\" line\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing host in \"sasl-host <host>\" line\n",
- fname, lineno, 0 );
-#endif
-
- return( 1 );
- }
-
- if ( global_host != NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: already set sasl-host!\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: already set sasl-host!\n",
- fname, lineno, 0 );
-#endif
-
+ /* SASL config options */
+ } else if ( strncasecmp( cargv[0], "sasl", 4 ) == 0 ) {
+ if ( slap_sasl_config( cargc, cargv, line, fname, lineno ) )
return 1;
- } else {
- global_host = ch_strdup( cargv[1] );
- }
-
- /* set SASL realm */
- } else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) {
- if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: missing realm in \"sasl-realm <realm>\" line.\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing realm in \"sasl-realm <realm>\" line\n",
- fname, lineno, 0 );
-#endif
-
- return( 1 );
- }
-
- if ( global_realm != NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: already set sasl-realm!\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: already set sasl-realm!\n",
- fname, lineno, 0 );
-#endif
-
- return 1;
-
- } else {
- global_realm = ch_strdup( cargv[1] );
- }
-
- } else if ( !strcasecmp( cargv[0], "sasl-regexp" )
- || !strcasecmp( cargv[0], "saslregexp" ) )
- {
- int rc;
- if ( cargc != 3 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: need 2 args in "
- "\"saslregexp <match> <replace>\"\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: need 2 args in \"saslregexp <match> <replace>\"\n",
- fname, lineno, 0 );
-#endif
-
- return( 1 );
- }
- rc = slap_sasl_regexp_config( cargv[1], cargv[2] );
- if ( rc ) {
- return rc;
- }
-
- /* SASL security properties */
- } else if ( strcasecmp( cargv[0], "sasl-secprops" ) == 0 ) {
- char *txt;
-
- if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d: missing flags in "
- "\"sasl-secprops <properties>\" line\n",
- fname, lineno ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing flags in \"sasl-secprops <properties>\" line\n",
- fname, lineno, 0 );
-#endif
-
- return 1;
- }
-
- txt = slap_sasl_secprops( cargv[1] );
- if ( txt != NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
- "%s: line %d sas-secprops: %s\n",
- fname, lineno, txt ));
-#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: sasl-secprops: %s\n",
- fname, lineno, txt );
-#endif
-
- return 1;
- }
-
/* set UCDATA path */
} else if ( strcasecmp( cargv[0], "ucdata-path" ) == 0 ) {
int err;
LDAPControl *** rspctrls,
const char **text );
+LDAP_SLAPD_F (int) slap_sasl_config(
+ int cargc,
+ char **cargv,
+ char *line,
+ const char *fname,
+ int lineno );
+
+
/*
* saslauthz.c
*/
struct berval *authzid ));
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 * ));
+
/*
* schema.c
LDAP_SLAPD_V (struct berval) default_search_base;
LDAP_SLAPD_V (struct berval) default_search_nbase;
-LDAP_SLAPD_V (int) nSaslRegexp;
-LDAP_SLAPD_V (SaslRegexp_t*) SaslRegexp;
-
LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) num_sent_mutex;
LDAP_SLAPD_V (unsigned long) num_bytes_sent;
LDAP_SLAPD_V (unsigned long) num_pdu_sent;
static sasl_security_properties_t sasl_secprops;
+int slap_sasl_config( int cargc, char **cargv, char *line,
+ const char *fname, int lineno )
+{
+ /* set SASL proxy authorization policy */
+ if ( strcasecmp( cargv[0], "sasl-authz-policy" ) == 0 ) {
+ if ( cargc != 2 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: missing policy in \"sasl-authz-policy <policy>\" line\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing policy in \"sasl-authz-policy <policy>\" line\n",
+ fname, lineno, 0 );
+#endif
+
+ return( 1 );
+ }
+ if ( slap_sasl_setpolicy( cargv[1] ) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: unable "
+ "to parse value \"%s\" "
+ "in \"sasl-authz-policy "
+ "<policy>\" line.\n",
+ fname, lineno, cargv[1] ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: unable "
+ "to parse value \"%s\" "
+ "in \"sasl-authz-policy "
+ "<policy>\" line\n",
+ fname, lineno, cargv[1] );
+#endif
+ return( 1 );
+ }
+
+
+ /* set SASL host */
+ } else if ( strcasecmp( cargv[0], "sasl-host" ) == 0 ) {
+ if ( cargc < 2 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: missing host in \"sasl-host <host>\" line\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing host in \"sasl-host <host>\" line\n",
+ fname, lineno, 0 );
+#endif
+
+ return( 1 );
+ }
+
+ if ( global_host != NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: already set sasl-host!\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: already set sasl-host!\n",
+ fname, lineno, 0 );
+#endif
+
+ return 1;
+
+ } else {
+ global_host = ch_strdup( cargv[1] );
+ }
+
+ /* set SASL realm */
+ } else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) {
+ if ( cargc < 2 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: missing realm in \"sasl-realm <realm>\" line.\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing realm in \"sasl-realm <realm>\" line\n",
+ fname, lineno, 0 );
+#endif
+
+ return( 1 );
+ }
+
+ if ( global_realm != NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: already set sasl-realm!\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: already set sasl-realm!\n",
+ fname, lineno, 0 );
+#endif
+
+ return 1;
+
+ } else {
+ global_realm = ch_strdup( cargv[1] );
+ }
+
+ } else if ( !strcasecmp( cargv[0], "sasl-regexp" )
+ || !strcasecmp( cargv[0], "saslregexp" ) )
+ {
+ int rc;
+ if ( cargc != 3 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: need 2 args in "
+ "\"saslregexp <match> <replace>\"\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: need 2 args in \"saslregexp <match> <replace>\"\n",
+ fname, lineno, 0 );
+#endif
+
+ return( 1 );
+ }
+ rc = slap_sasl_regexp_config( cargv[1], cargv[2] );
+ if ( rc ) {
+ return rc;
+ }
+
+ /* SASL security properties */
+ } else if ( strcasecmp( cargv[0], "sasl-secprops" ) == 0 ) {
+ char *txt;
+
+ if ( cargc < 2 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d: missing flags in "
+ "\"sasl-secprops <properties>\" line\n",
+ fname, lineno ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing flags in \"sasl-secprops <properties>\" line\n",
+ fname, lineno, 0 );
+#endif
+
+ return 1;
+ }
+
+ txt = slap_sasl_secprops( cargv[1] );
+ if ( txt != NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+ "%s: line %d sasl-secprops: %s\n",
+ fname, lineno, txt ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: sasl-secprops: %s\n",
+ fname, lineno, txt );
+#endif
+
+ return 1;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
static int
slap_sasl_log(
void *context,
#include <ldap_pvt.h>
+#define SASLREGEX_REPLACE 10
+
+typedef struct sasl_uri {
+ struct berval dn;
+ struct berval filter;
+ int scope;
+} SaslUri_t;
+
+typedef struct sasl_regexp {
+ char *sr_match; /* regexp match pattern */
+ SaslUri_t sr_replace; /* regexp replace pattern */
+ regex_t sr_workspace; /* workspace for regexp engine */
+ regmatch_t sr_strings[SASLREGEX_REPLACE]; /* strings matching $1,$2 ... */
+ int sr_dn_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */
+ int sr_fi_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */
+} SaslRegexp_t;
+
+static int nSaslRegexp = 0;
+static SaslRegexp_t *SaslRegexp = NULL;
+
+/* What SASL proxy authorization policies are allowed? */
+#define SASL_AUTHZ_NONE 0
+#define SASL_AUTHZ_FROM 1
+#define SASL_AUTHZ_TO 2
+
+static int authz_policy = SASL_AUTHZ_NONE;
+
+int slap_sasl_setpolicy( const char *arg )
+{
+ int rc = LDAP_SUCCESS;
+
+ if ( strcasecmp( arg, "none" ) == 0 )
+ authz_policy = SASL_AUTHZ_NONE;
+ else if ( strcasecmp( arg, "from" ) == 0 )
+ authz_policy = SASL_AUTHZ_FROM;
+ else if ( strcasecmp( arg, "to" ) == 0 )
+ authz_policy = SASL_AUTHZ_TO;
+ else if ( strcasecmp( arg, "both" ) == 0 )
+ authz_policy = SASL_AUTHZ_FROM | SASL_AUTHZ_TO;
+ else
+ rc = LDAP_OTHER;
+ return rc;
+}
+
/* URI format: ldap://<host>/<base>[?[<attrs>][?[<scope>][?[<filter>]]]] */
static int slap_parseURI( struct berval *uri,
* The DNs should not have the dn: prefix
*/
static int
-slap_sasl_check_authz(struct berval *searchDN, struct berval *assertDN, struct berval *attr, struct berval *authc)
+slap_sasl_check_authz(struct berval *searchDN, struct berval *assertDN, AttributeDescription *ad, struct berval *authc)
{
- const char *errmsg;
int i, rc;
BerVarray vals=NULL;
- AttributeDescription *ad=NULL;
#ifdef NEW_LOGGING
LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
"slap_sasl_check_authz: does %s match %s rule in %s?\n",
- assertDN->bv_val, attr->bv_val, searchDN->bv_val ));
+ 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, attr->bv_val, searchDN->bv_val);
+ assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
#endif
- rc = slap_bv2ad( attr, &ad, &errmsg );
- if( rc != LDAP_SUCCESS )
- goto COMPLETE;
-
rc = backend_attribute( NULL, NULL, NULL, NULL, searchDN, ad, &vals );
if( rc != LDAP_SUCCESS )
goto COMPLETE;
#ifdef NEW_LOGGING
LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
- "slap_sasl_check_authz: %s check returning %s\n", attr->bv_val, rc ));
+ "slap_sasl_check_authz: %s check returning %s\n", ad->ad_cname.bv_val, rc ));
#else
Debug( LDAP_DEBUG_TRACE,
- "<==slap_sasl_check_authz: %s check returning %d\n", attr->bv_val, rc, 0);
+ "<==slap_sasl_check_authz: %s check returning %d\n", ad->ad_cname.bv_val, rc, 0);
#endif
return( rc );
* The DNs should not have the dn: prefix
*/
-static struct berval sasl_authz_src = {
- sizeof(SASL_AUTHZ_SOURCE_ATTR)-1, SASL_AUTHZ_SOURCE_ATTR };
-
-static struct berval sasl_authz_dst = {
- sizeof(SASL_AUTHZ_DEST_ATTR)-1, SASL_AUTHZ_DEST_ATTR };
-
int slap_sasl_authorized( struct berval *authcDN, struct berval *authzDN )
{
int rc = LDAP_INAPPROPRIATE_AUTH;
}
/* Check source rules */
- rc = slap_sasl_check_authz( authcDN, authzDN, &sasl_authz_src,
- authcDN );
- if( rc == LDAP_SUCCESS ) {
- goto DONE;
+ if( authz_policy & SASL_AUTHZ_TO ) {
+ rc = slap_sasl_check_authz( authcDN, authzDN,
+ slap_schema.si_ad_saslAuthzTo, authcDN );
+ if( rc == LDAP_SUCCESS ) {
+ goto DONE;
+ }
}
/* Check destination rules */
- rc = slap_sasl_check_authz( authzDN, authcDN, &sasl_authz_dst,
- authcDN );
- if( rc == LDAP_SUCCESS ) {
- goto DONE;
+ if( authz_policy & SASL_AUTHZ_FROM ) {
+ rc = slap_sasl_check_authz( authzDN, authcDN,
+ slap_schema.si_ad_saslAuthzFrom, authcDN );
+ if( rc == LDAP_SUCCESS ) {
+ goto DONE;
+ }
}
rc = LDAP_INAPPROPRIATE_AUTH;
"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
offsetof(struct slap_internal_schema, si_ad_children) },
+ { "saslAuthzTo", "( 1.3.6.1.4.1.4203.1.3.3 "
+ "NAME 'saslAuthzTo' "
+ "DESC 'SASL proxy authorization targets' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "USAGE dSAOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_saslAuthzTo) },
+ { "saslAuthzFrom", "( 1.3.6.1.4.1.4203.1.3.4 "
+ "NAME 'saslAuthzFrom' "
+ "DESC 'SASL proxy authorization sources' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "USAGE dSAOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_saslAuthzFrom) },
#ifdef SLAPD_ACI_ENABLED
{ "OpenLDAPaci", "( 1.3.6.1.4.1.4203.666.1.5 "
"NAME 'OpenLDAPaci' "
/* Access Control Internals */
AttributeDescription *si_ad_entry;
AttributeDescription *si_ad_children;
+ AttributeDescription *si_ad_saslAuthzTo;
+ AttributeDescription *si_ad_saslAuthzFrom;
#ifdef SLAPD_ACI_ENABLED
AttributeDescription *si_ad_aci;
#endif
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 )
#endif
-
-#define SASLREGEX_REPLACE 10
-#define SASL_AUTHZ_SOURCE_ATTR "saslAuthzTo"
-#define SASL_AUTHZ_DEST_ATTR "saslAuthzFrom"
-
-typedef struct sasl_uri {
- struct berval dn;
- struct berval filter;
- int scope;
-} SaslUri_t;
-
-typedef struct sasl_regexp {
- char *sr_match; /* regexp match pattern */
- SaslUri_t sr_replace; /* regexp replace pattern */
- regex_t sr_workspace; /* workspace for regexp engine */
- regmatch_t sr_strings[SASLREGEX_REPLACE]; /* strings matching $1,$2 ... */
- int sr_dn_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */
- int sr_fi_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */
-} SaslRegexp_t;
-
/*
* listener; need to access it from monitor backend
*/
return LDAP_SUCCESS;
}
-char * slap_sasl_secprops( const char *in )
+int slap_sasl_config(
+ int cargc,
+ char **cargv,
+ char *line,
+ const char *fname,
+ int lineno )
{
- return NULL;
-}
-
-int slap_sasl_regexp_config( const char *match, const char *replace )
-{
- return(0);
+ return LDAP_SUCCESS;
}