}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
}
assert( authzid == NULL );
- authzid = control;
+ authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
#define LDAP_IS_LEAF 0x23 /* not LDAPv3 */
#define LDAP_ALIAS_DEREF_PROBLEM 0x24
-#define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x30,0x32) /* 48-50 */
+#define LDAP_SECURITY_ERROR(n) LDAP_RANGE((n),0x2F,0x32) /* 47-50 */
+#define LDAP_PROXY_AUTHZ_FAILURE 0x2F /* LDAPv3 proxy authorization */
#define LDAP_INAPPROPRIATE_AUTH 0x30
#define LDAP_INVALID_CREDENTIALS 0x31
#define LDAP_INSUFFICIENT_ACCESS 0x32
{LDAP_IS_LEAF, "Entry is a leaf" },
{LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" },
+ {LDAP_PROXY_AUTHZ_FAILURE, "Proxy Authorization Failure" },
{LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" },
{LDAP_INVALID_CREDENTIALS, "Invalid credentials" },
{LDAP_INSUFFICIENT_ACCESS, "Insufficient access" },
lutil_salt_format( cargv[1] );
-#ifdef HAVE_CYRUS_SASL
/* SASL config options */
} else if ( strncasecmp( cargv[0], "sasl", 4 ) == 0 ) {
if ( slap_sasl_config( cargc, cargv, line, fname, lineno ) )
return 1;
-#endif /* HAVE_CYRUS_SASL */
} else if ( strcasecmp( cargv[0], "schemadn" ) == 0 ) {
struct berval dn;
LDAPControl *ctrl,
const char **text ));
+static SLAP_CTRL_PARSE_FN parseProxyAuthz;
static SLAP_CTRL_PARSE_FN parseManageDSAit;
-static SLAP_CTRL_PARSE_FN parseSubentries;
static SLAP_CTRL_PARSE_FN parseNoOp;
static SLAP_CTRL_PARSE_FN parsePagedResults;
static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
+#ifdef LDAP_CONTROL_SUBENTRIES
+static SLAP_CTRL_PARSE_FN parseSubentries;
+#endif
#ifdef LDAP_CLIENT_UPDATE
static SLAP_CTRL_PARSE_FN parseClientUpdate;
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
#undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
+static char *proxy_authz_extops[] = {
+ LDAP_EXOP_MODIFY_PASSWD,
+ LDAP_EXOP_X_WHO_AM_I,
+ NULL
+};
+
static struct slap_control {
char *sc_oid;
slap_mask_t sc_mask;
SLAP_CTRL_PARSE_FN *sc_parse;
} supportedControls[] = {
+ { LDAP_CONTROL_PROXY_AUTHZ,
+ SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops,
+ parseProxyAuthz },
{ LDAP_CONTROL_MANAGEDSAIT,
SLAP_CTRL_ACCESS, NULL,
parseManageDSAit },
-#ifdef LDAP_CONTROL_SUBENTRIES
- { LDAP_CONTROL_SUBENTRIES,
- SLAP_CTRL_SEARCH, NULL,
- parseSubentries },
-#endif
{ LDAP_CONTROL_NOOP,
SLAP_CTRL_ACCESS, NULL,
parseNoOp },
parsePagedResults },
{ LDAP_CONTROL_VALUESRETURNFILTER,
SLAP_CTRL_SEARCH, NULL,
- parseValuesReturnFilter },
+ parseValuesReturnFilter },
+#ifdef LDAP_CONTROL_SUBENTRIES
+ { LDAP_CONTROL_SUBENTRIES,
+ SLAP_CTRL_SEARCH, NULL,
+ parseSubentries },
+#endif
#ifdef LDAP_CLIENT_UPDATE
{ LDAP_CONTROL_CLIENT_UPDATE,
SLAP_CTRL_SEARCH, NULL,
tagmask = SLAP_CTRL_ABANDON;
break;
case LDAP_REQ_EXTENDED:
- /* FIXME: check list of extended operations */
- tagmask = ~0U;
+ tagmask=~0L;
+ assert( op->o_extendedop != NULL );
+ if( sc->sc_extendedops != NULL ) {
+ int i;
+ for( i=0; sc->sc_extendedops[i] != NULL; i++ ) {
+ if( strcmp( op->o_extendedop, sc->sc_extendedops[i] )
+ == 0 )
+ {
+ tagmask=0L;
+ break;
+ }
+ }
+ }
break;
default:
rc = LDAP_OTHER;
return_results:
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, RESULTS,
- "get_ctrls: n=%d rc=%d err=%s\n", nctrls, rc, errmsg ? errmsg : "" );
+ "get_ctrls: n=%d rc=%d err=\"%s\"\n",
+ nctrls, rc, errmsg ? errmsg : "" );
#else
- Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: n=%d rc=%d err=%s\n",
+ Debug( LDAP_DEBUG_TRACE,
+ "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
nctrls, rc, errmsg ? errmsg : "");
#endif
return LDAP_SUCCESS;
}
-#ifdef LDAP_CONTROL_SUBENTRIES
-static int parseSubentries (
+static int parseProxyAuthz (
Connection *conn,
Operation *op,
LDAPControl *ctrl,
const char **text )
{
- if ( op->o_subentries != SLAP_NO_CONTROL ) {
- *text = "subentries control specified multiple times";
- return LDAP_PROTOCOL_ERROR;
- }
+ int rc;
+ struct berval dn;
- /* FIXME: should use BER library */
- if( ( ctrl->ldctl_value.bv_len != 3 )
- && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
- && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
- {
- *text = "subentries control value encoding is bogus";
+ if ( op->o_proxy_authz != SLAP_NO_CONTROL ) {
+ *text = "proxy authorization control specified multiple times";
return LDAP_PROTOCOL_ERROR;
}
- op->o_subentries = ctrl->ldctl_iscritical
+ op->o_proxy_authz = ctrl->ldctl_iscritical
? SLAP_CRITICAL_CONTROL
: SLAP_NONCRITICAL_CONTROL;
- op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, ARGS,
+ "parseProxyAuthz: conn %d authzid=\"%s\"\n",
+ conn->c_connid,
+ ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
+ 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS,
+ "parseProxyAuthz: conn %d authzid=\"%s\"\n",
+ conn->c_connid,
+ ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
+ 0 );
+#endif
- return LDAP_SUCCESS;
-}
+ if( ctrl->ldctl_value.bv_len == 0 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, TRACE,
+ "parseProxyAuthz: conn=%d anonymous\n",
+ conn->c_connid, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "parseProxyAuthz: conn=%d anonymous\n",
+ conn->c_connid, 0, 0 );
+#endif
+
+ /* anonymous */
+ free( op->o_dn.bv_val );
+ op->o_dn.bv_len = 0;
+ op->o_dn.bv_val = ch_strdup( "" );
+
+ free( op->o_ndn.bv_val );
+ op->o_ndn.bv_len = 0;
+ op->o_ndn.bv_val = ch_strdup( "" );
+
+ return LDAP_SUCCESS;
+ }
+
+ rc = slap_sasl_getdn( conn,
+ ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len,
+ NULL, &dn, SLAP_GETDN_AUTHZID );
+
+ if( rc != LDAP_SUCCESS || !dn.bv_len ) {
+ *text = "authzId mapping failed";
+ return LDAP_PROXY_AUTHZ_FAILURE;
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, TRACE,
+ "parseProxyAuthz: conn=%d \"%s\"\n",
+ conn->c_connid,
+ dn.bv_len ? dn.bv_val : "(NULL)", 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "parseProxyAuthz: conn=%d \"%s\"\n",
+ conn->c_connid,
+ dn.bv_len ? dn.bv_val : "(NULL)", 0 );
+#endif
+
+ rc = slap_sasl_authorized( conn, &op->o_dn, &dn );
+
+ if( rc ) {
+ ch_free( dn.bv_val );
+ *text = "not authorized to assume identity";
+ return LDAP_PROXY_AUTHZ_FAILURE;
+ }
+
+#if 0
+ ch_free( op->o_dn );
+ ch_free( op->o_ndn );
+
+ op->o_dn = dn;
#endif
+ *text = "not (yet) implemented";
+ return LDAP_OTHER;
+}
+
static int parseNoOp (
Connection *conn,
Operation *op,
}
if ( ctrl->ldctl_value.bv_len == 0 ) {
- *text = "paged results control value is empty";
+ *text = "paged results control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
}
const char *err_msg = "";
if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) {
- *text = "valuesreturnfilter control specified multiple times";
+ *text = "valuesReturnFilter control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ *text = "valuesReturnFilter control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
}
return LDAP_SUCCESS;
}
+#ifdef LDAP_CONTROL_SUBENTRIES
+static int parseSubentries (
+ Connection *conn,
+ Operation *op,
+ LDAPControl *ctrl,
+ const char **text )
+{
+ if ( op->o_subentries != SLAP_NO_CONTROL ) {
+ *text = "subentries control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ /* FIXME: should use BER library */
+ if( ( ctrl->ldctl_value.bv_len != 3 )
+ && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
+ && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
+ {
+ *text = "subentries control value encoding is bogus";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_subentries = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);
+
+ return LDAP_SUCCESS;
+}
+#endif
+
#ifdef LDAP_CLIENT_UPDATE
static int parseClientUpdate (
Connection *conn,
}
if ( ctrl->ldctl_value.bv_len == 0 ) {
- *text = "LCUP client update control value is empty";
+ *text = "LCUP client update control value is empty (or absent)";
return LDAP_PROTOCOL_ERROR;
}
goto done;
}
+ op->o_extendedop = reqoid.bv_val;
+
tag = ber_peek_tag( op->o_ber, &len );
if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
const char *fname,
int lineno );
+LDAP_SLAPD_F (int) slap_sasl_getdn( Connection *conn,
+ char *id, int len,
+ char *user_realm, struct berval *dn, int flags );
/*
* saslauthz.c
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ENTRY,
- "send_ldap_result : conn %lu op=%lu p=%d\n",
+ "send_ldap_result: conn %lu op=%lu p=%d\n",
op->o_connid, op->o_opid, op->o_protocol );
#else
Debug( LDAP_DEBUG_TRACE,
rspdata != NULL ? rspdata->bv_len : 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "send_ldap_extended err=%d oid=%s len=%ld\n",
+ "send_ldap_extended: err=%d oid=%s len=%ld\n",
err,
rspoid ? rspoid : "",
rspdata != NULL ? rspdata->bv_len : 0 );
#endif
-
tag = req2res( op->o_tag );
msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
#include "slap.h"
-#ifdef HAVE_CYRUS_SASL
#include <limits.h>
-#ifdef HAVE_SASL_SASL_H
-#include <sasl/sasl.h>
-#else
-#include <sasl.h>
-#endif
+#ifdef HAVE_CYRUS_SASL
+# ifdef HAVE_SASL_SASL_H
+# include <sasl/sasl.h>
+# else
+# include <sasl.h>
+# endif
+
+# if SASL_VERSION_MAJOR >= 2
+# include <sasl/saslplug.h>
+# define SASL_CONST const
+# else
+# define SASL_CONST
+# endif
-#include <lutil.h>
-#if SASL_VERSION_MAJOR >= 2
-#include <sasl/saslplug.h>
-#define SASL_CONST const
-#else
-#define SASL_CONST
-#endif
+static sasl_security_properties_t sasl_secprops;
+#endif /* HAVE_CYRUS_SASL */
#include "ldap_pvt.h"
#include "lber_pvt.h"
-
-/* Flags for telling slap_sasl_getdn() what type of identity is being passed */
-#define FLAG_GETDN_AUTHCID 2
-#define FLAG_GETDN_AUTHZID 4
-
-static sasl_security_properties_t sasl_secprops;
+#include <lutil.h>
int slap_sasl_config( int cargc, char **cargv, char *line,
const char *fname, int lineno )
if ( cargc != 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s: line %d: missing policy in \"sasl-authz-policy <policy>\" line\n",
- fname, lineno, 0 );
+ "%s: line %d: missing policy in"
+ " \"sasl-authz-policy <policy>\" line\n",
+ fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing policy in \"sasl-authz-policy <policy>\" line\n",
+ "%s: line %d: missing policy in"
+ " \"sasl-authz-policy <policy>\" line\n",
fname, lineno, 0 );
#endif
#endif
return( 1 );
}
-
+ } else if ( !strcasecmp( cargv[0], "sasl-regexp" )
+ || !strcasecmp( cargv[0], "saslregexp" ) )
+ {
+ int rc;
+ if ( cargc != 3 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONFIG, CRIT,
+ "%s: line %d: need 2 args in "
+ "\"saslregexp <match> <replace>\"\n",
+ fname, lineno, 0 );
+#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;
+ }
+
+#ifdef HAVE_CYRUS_SASL
/* set SASL host */
} else if ( strcasecmp( cargv[0], "sasl-host" ) == 0 ) {
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s: line %d: missing host in \"sasl-host <host>\" line\n",
- fname, lineno, 0 );
+ "%s: line %d: missing host in \"sasl-host <host>\" line\n",
+ fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing host in \"sasl-host <host>\" line\n",
+ "%s: line %d: missing host in \"sasl-host <host>\" line\n",
fname, lineno, 0 );
#endif
if ( global_host != NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s: line %d: already set sasl-host!\n",
- fname, lineno, 0 );
+ "%s: line %d: already set sasl-host!\n",
+ fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: already set sasl-host!\n",
} else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) {
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( CONFIG, CRIT,
- "%s: line %d: missing realm in \"sasl-realm <realm>\" line.\n",
- fname, lineno, 0 );
+ LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
+ "missing realm in \"sasl-realm <realm>\" line.\n",
+ fname, lineno, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing realm in \"sasl-realm <realm>\" line\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing realm in \"sasl-realm <realm>\" line.\n",
fname, lineno, 0 );
#endif
if ( global_realm != NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s: line %d: already set sasl-realm!\n",
- fname, lineno, 0 );
+ "%s: line %d: already set sasl-realm!\n",
+ fname, lineno, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: already set sasl-realm!\n",
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, CRIT,
- "%s: line %d: need 2 args in "
- "\"saslregexp <match> <replace>\"\n",
- fname, lineno, 0 );
-#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, CRIT,
- "%s: line %d: missing flags in "
- "\"sasl-secprops <properties>\" line\n",
- fname, lineno, 0 );
+ LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
+ "missing flags in \"sasl-secprops <properties>\" line\n",
+ fname, lineno, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing flags in \"sasl-secprops <properties>\" line\n",
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing flags in \"sasl-secprops <properties>\" line\n",
fname, lineno, 0 );
#endif
if ( txt != NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s: line %d sasl-secprops: %s\n",
- fname, lineno, txt );
+ "%s: line %d sasl-secprops: %s\n",
+ fname, lineno, txt );
#else
Debug( LDAP_DEBUG_ANY,
- "%s: line %d: sasl-secprops: %s\n",
+ "%s: line %d: sasl-secprops: %s\n",
fname, lineno, txt );
#endif
return 1;
}
+#endif /* HAVE_CYRUS_SASL */
}
return LDAP_SUCCESS;
}
-static int
+#ifdef HAVE_CYRUS_SASL
+
+int
slap_sasl_log(
void *context,
int priority,
}
-/* Take any sort of identity string and return a DN with the "dn:" prefix. The
- string returned in *dn is in its own allocated memory, and must be free'd
- by the calling process.
- -Mark Adamson, Carnegie Mellon
-
- The "dn:" prefix is no longer used anywhere inside slapd. It is only used
- on strings passed in directly from SASL.
- -Howard Chu, Symas Corp.
-*/
-
-#define SET_DN 1
-#define SET_U 2
-
-static struct berval ext_bv = BER_BVC( "EXTERNAL" );
-
-int slap_sasl_getdn( Connection *conn, char *id, int len,
- char *user_realm, struct berval *dn, int flags )
-{
- char *c1;
- int rc, is_dn = 0, do_norm = 1;
- sasl_conn_t *ctx;
- struct berval dn2;
-
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, ENTRY,
- "slap_sasl_getdn: conn %d id=%s\n",
- conn ? conn->c_connid : -1, id ? (*id ? id : "<empty>") : "NULL", 0 );
-#else
- Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: id=%s\n",
- id?(*id?id:"<empty>"):"NULL",0,0 );
-#endif
-
- dn->bv_val = NULL;
- dn->bv_len = 0;
-
- if ( id ) {
- if ( len == 0 ) len = strlen( id );
-
- /* Blatantly anonymous ID */
- if ( len == sizeof("anonymous") - 1 &&
- !strcasecmp( id, "anonymous" ) ) {
- return( LDAP_SUCCESS );
- }
- } else {
- len = 0;
- }
-
- ctx = conn->c_sasl_context;
-
- /* 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 & FLAG_GETDN_AUTHCID ) {
-#ifdef HAVE_TLS
- if( conn->c_is_tls &&
- conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len &&
- strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 )
- {
- /* X.509 DN is already normalized */
- do_norm = 0;
- is_dn = SET_DN;
- ber_str2bv( id, len, 1, dn );
-
- } else
-#endif
- {
- /* convert to u:<username> form */
- is_dn = SET_U;
- dn->bv_val = id;
- dn->bv_len = len;
- }
- }
- if( !is_dn ) {
- if( !strncasecmp( id, "u:", sizeof("u:")-1 )) {
- is_dn = SET_U;
- dn->bv_val = id+2;
- dn->bv_len = len-2;
- } else if ( !strncasecmp( id, "dn:", sizeof("dn:")-1) ) {
- is_dn = SET_DN;
- dn->bv_val = id+3;
- dn->bv_len = len-3;
- }
- }
-
- /* No other possibilities from here */
- if( !is_dn ) {
- dn->bv_val = NULL;
- dn->bv_len = 0;
- return( LDAP_INAPPROPRIATE_AUTH );
- }
-
- /* Username strings */
- if( is_dn == SET_U ) {
- char *p, *realm;
- len = dn->bv_len + sizeof("uid=")-1 + sizeof(",cn=auth")-1;
-
- /* 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;
- }
-
- if( conn->c_sasl_bind_mech.bv_len ) {
- len += conn->c_sasl_bind_mech.bv_len + sizeof(",cn=")-1;
- }
-
- /* Build the new dn */
- c1 = dn->bv_val;
- dn->bv_val = SLAP_MALLOC( len+1 );
- if( dn->bv_val == NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, ERR,
- "slap_sasl_getdn: SLAP_MALLOC failed", 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY,
- "slap_sasl_getdn: SLAP_MALLOC failed", 0, 0, 0 );
-#endif
- return LDAP_OTHER;
- }
- p = lutil_strcopy( dn->bv_val, "uid=" );
- p = lutil_strncopy( p, c1, dn->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 ) {
- p = lutil_strcopy( p, ",cn=" );
- p = lutil_strcopy( p, user_realm );
- }
-
- if( conn->c_sasl_bind_mech.bv_len ) {
- p = lutil_strcopy( p, ",cn=" );
- p = lutil_strcopy( p, conn->c_sasl_bind_mech.bv_val );
- }
- p = lutil_strcopy( p, ",cn=auth" );
- dn->bv_len = p - dn->bv_val;
-
-#ifdef NEW_LOGGING
- 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 );
-#endif
- }
-
- /* All strings are in DN form now. Normalize if needed. */
- if ( do_norm ) {
- rc = dnNormalize2( NULL, dn, &dn2 );
-
- /* User DNs were constructed above and must be freed now */
- if ( is_dn == SET_U )
- ch_free( dn->bv_val );
-
- if ( rc != LDAP_SUCCESS ) {
- dn->bv_val = NULL;
- dn->bv_len = 0;
- return rc;
- }
- *dn = dn2;
- }
-
- /* Run thru regexp */
- slap_sasl2dn( conn, dn, &dn2 );
- if( dn2.bv_val ) {
- ch_free( dn->bv_val );
- *dn = dn2;
-#ifdef NEW_LOGGING
- LDAP_LOG( TRANSPORT, ENTRY,
- "slap_sasl_getdn: dn:id converted to %s.\n", dn->bv_val, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE, "getdn: dn:id converted to %s\n",
- dn->bv_val, 0, 0 );
-#endif
- }
-
- return( LDAP_SUCCESS );
-}
-
#if SASL_VERSION_MAJOR >= 2
static const char *slap_propnames[] = {
"*slapConn", "*authcDN", "*authzDN", NULL };
*/
rc = slap_sasl_getdn( conn, (char *)username, 0, NULL, &dn,
- FLAG_GETDN_AUTHCID );
+ SLAP_GETDN_AUTHCID );
if ( rc != LDAP_SUCCESS ) {
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
return SASL_NOUSER;
}
rc = slap_sasl_getdn( conn, (char *)in, inlen, (char *)user_realm, &dn,
- (flags & SASL_CU_AUTHID) ? FLAG_GETDN_AUTHCID : FLAG_GETDN_AUTHZID );
+ (flags & SASL_CU_AUTHID) ? SLAP_GETDN_AUTHCID : SLAP_GETDN_AUTHZID );
if ( rc != LDAP_SUCCESS ) {
sasl_seterror( sconn, 0, ldap_err2string( rc ) );
return SASL_NOAUTHZ;
/* Convert the identities to DN's. If no authzid was given, client will
be bound as the DN matching their username */
- rc = slap_sasl_getdn( conn, (char *)authcid, 0, realm, &authcDN, FLAG_GETDN_AUTHCID );
+ rc = slap_sasl_getdn( conn, (char *)authcid, 0, realm,
+ &authcDN, SLAP_GETDN_AUTHCID );
if( rc != LDAP_SUCCESS ) {
*errstr = ldap_err2string( rc );
return SASL_NOAUTHZ;
*errstr = NULL;
return SASL_OK;
}
- rc = slap_sasl_getdn( conn, (char *)authzid, 0, realm, &authzDN, FLAG_GETDN_AUTHZID );
+ rc = slap_sasl_getdn( conn, (char *)authzid, 0, realm,
+ &authzDN, SLAP_GETDN_AUTHZID );
if( rc != LDAP_SUCCESS ) {
ch_free( authcDN.bv_val );
*errstr = ldap_err2string( rc );
}
#endif
-
int slap_sasl_init( void )
{
#ifdef HAVE_CYRUS_SASL
done:
return rc;
}
+#endif /* HAVE_CYRUS_SASL */
+
+/* Take any sort of identity string and return a DN with the "dn:" prefix. The
+ string returned in *dn is in its own allocated memory, and must be free'd
+ by the calling process.
+ -Mark Adamson, Carnegie Mellon
+
+ The "dn:" prefix is no longer used anywhere inside slapd. It is only used
+ on strings passed in directly from SASL.
+ -Howard Chu, Symas Corp.
+*/
+
+#define SET_DN 1
+#define SET_U 2
+
+static struct berval ext_bv = BER_BVC( "EXTERNAL" );
+
+int slap_sasl_getdn( Connection *conn, char *id, int len,
+ char *user_realm, struct berval *dn, int flags )
+{
+ char *c1;
+ int rc, is_dn = 0, do_norm = 1;
+ struct berval dn2;
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, ENTRY,
+ "slap_sasl_getdn: conn %d id=%s\n",
+ conn ? conn->c_connid : -1, id ? (*id ? id : "<empty>") : "NULL", 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: id=%s\n",
+ id?(*id?id:"<empty>"):"NULL",0,0 );
+#endif
+
+ dn->bv_val = NULL;
+ dn->bv_len = 0;
+
+ if ( id ) {
+ if ( len == 0 ) len = strlen( id );
+
+ /* Blatantly anonymous ID */
+ if ( len == sizeof("anonymous") - 1 &&
+ !strcasecmp( id, "anonymous" ) ) {
+ return( LDAP_SUCCESS );
+ }
+ } else {
+ len = 0;
+ }
+
+ /* 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 ) {
+#ifdef HAVE_TLS
+ if( conn->c_is_tls &&
+ conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len &&
+ strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 )
+ {
+ /* X.509 DN is already normalized */
+ do_norm = 0;
+ is_dn = SET_DN;
+ ber_str2bv( id, len, 1, dn );
+
+ } else
#endif
+ {
+ /* convert to u:<username> form */
+ is_dn = SET_U;
+ dn->bv_val = id;
+ dn->bv_len = len;
+ }
+ }
+ if( !is_dn ) {
+ if( !strncasecmp( id, "u:", sizeof("u:")-1 )) {
+ is_dn = SET_U;
+ dn->bv_val = id+2;
+ dn->bv_len = len-2;
+ } else if ( !strncasecmp( id, "dn:", sizeof("dn:")-1) ) {
+ is_dn = SET_DN;
+ dn->bv_val = id+3;
+ dn->bv_len = len-3;
+ }
+ }
+
+ /* No other possibilities from here */
+ if( !is_dn ) {
+ dn->bv_val = NULL;
+ dn->bv_len = 0;
+ return( LDAP_INAPPROPRIATE_AUTH );
+ }
+
+ /* Username strings */
+ if( is_dn == SET_U ) {
+ char *p, *realm;
+ len = dn->bv_len + sizeof("uid=")-1 + sizeof(",cn=auth")-1;
+
+ /* 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;
+ }
+
+ if( conn->c_sasl_bind_mech.bv_len ) {
+ len += conn->c_sasl_bind_mech.bv_len + sizeof(",cn=")-1;
+ }
+
+ /* Build the new dn */
+ c1 = dn->bv_val;
+ dn->bv_val = SLAP_MALLOC( len+1 );
+ if( dn->bv_val == NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, ERR,
+ "slap_sasl_getdn: SLAP_MALLOC failed", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "slap_sasl_getdn: SLAP_MALLOC failed", 0, 0, 0 );
+#endif
+ return LDAP_OTHER;
+ }
+ p = lutil_strcopy( dn->bv_val, "uid=" );
+ p = lutil_strncopy( p, c1, dn->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 ) {
+ p = lutil_strcopy( p, ",cn=" );
+ p = lutil_strcopy( p, user_realm );
+ }
+
+ if( conn->c_sasl_bind_mech.bv_len ) {
+ p = lutil_strcopy( p, ",cn=" );
+ p = lutil_strcopy( p, conn->c_sasl_bind_mech.bv_val );
+ }
+ p = lutil_strcopy( p, ",cn=auth" );
+ dn->bv_len = p - dn->bv_val;
+
+#ifdef NEW_LOGGING
+ 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 );
+#endif
+ }
+
+ /* All strings are in DN form now. Normalize if needed. */
+ if ( do_norm ) {
+ rc = dnNormalize2( NULL, dn, &dn2 );
+
+ /* User DNs were constructed above and must be freed now */
+ if ( is_dn == SET_U )
+ ch_free( dn->bv_val );
+
+ if ( rc != LDAP_SUCCESS ) {
+ dn->bv_val = NULL;
+ dn->bv_len = 0;
+ return rc;
+ }
+ *dn = dn2;
+ }
+
+ /* Run thru regexp */
+ slap_sasl2dn( conn, dn, &dn2 );
+ if( dn2.bv_val ) {
+ ch_free( dn->bv_val );
+ *dn = dn2;
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, ENTRY,
+ "slap_sasl_getdn: dn:id converted to %s.\n", dn->bv_val, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "getdn: dn:id converted to %s\n",
+ dn->bv_val, 0, 0 );
+#endif
+ }
+
+ return( LDAP_SUCCESS );
+}
#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
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 = 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, 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;
- op.o_threadctx = conn->c_sasl_bindop->o_threadctx;
-
- (*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;
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, 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;
+ op.o_threadctx = conn->c_sasl_bindop->o_threadctx;
+
+ (*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 */
rc = LDAP_INAPPROPRIATE_AUTH;
DONE:
-#endif
#ifdef NEW_LOGGING
LDAP_LOG( TRANSPORT, RESULTS, "slap_sasl_authorized: return %d\n", rc,0,0 );
slap_ssf_t sss_simple_bind;
} slap_ssf_set_t;
+
+/* Flags for telling slap_sasl_getdn() what type of identity is being passed */
+#define SLAP_GETDN_AUTHCID 2
+#define SLAP_GETDN_AUTHZID 4
+
/*
* Index types
*/
ber_tag_t o_tag; /* tag of the request */
time_t o_time; /* time op was initiated */
+ char * o_extendedop; /* extended operation OID */
+
ldap_pvt_thread_t o_tid; /* thread handling this op */
volatile sig_atomic_t o_abandon; /* abandon flag */
#define SLAP_CRITICAL_CONTROL 2
char o_managedsait;
char o_noop;
+ char o_proxy_authz;
char o_subentries;
char o_subentries_visibility;
char o_valuesreturnfilter;
return 0;
}
+int slap_sasl_getdn( Connection *conn, char *id, int len,
+ char *user_realm, struct berval *dn, int flags )
+{
+ return -1;
+}
+
+int slap_sasl_authorized( Connection *conn,
+ struct berval *authcDN, struct berval *authzDN )
+{
+ return -1;
+}
+
exit $RC
fi
+echo "Testing ldapwhoami as ${MANAGERDN} for anonymous..."
+$LDAPWHOAMI -h $LOCALHOST -p $PORT -D "$MANAGERDN" -w $PASSWD \
+ -e \!authzid=""
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapwhoami failed ($RC)!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Testing ldapwhoami as ${MANAGERDN} for dn:$BABSDN..."
+$LDAPWHOAMI -h $LOCALHOST -p $PORT -D "$MANAGERDN" -w $PASSWD \
+ -e \!authzid="dn:$BABSDN"
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapwhoami failed ($RC)!"
+# kill -HUP $PID
+# exit $RC
+fi
+
+echo "Testing ldapwhoami as ${MANAGERDN} for u:ursula..."
+$LDAPWHOAMI -h $LOCALHOST -p $PORT -D "$MANAGERDN" -w $PASSWD \
+ -e \!authzid="u:ursula"
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapwhoami failed ($RC)!"
+# kill -HUP $PID
+# exit $RC
+fi
+
kill -HUP $PID
echo ">>>>> Test succeeded"