Commit da76c195 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

First-cut proxy authorization support.

parent 9ba95dd0
......@@ -215,7 +215,7 @@ main( int argc, char **argv )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -214,7 +214,7 @@ main( int argc, char **argv )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -278,7 +278,7 @@ main( int argc, char **argv )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -234,7 +234,7 @@ main(int argc, char **argv)
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -234,7 +234,7 @@ main( int argc, char *argv[] )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -471,7 +471,7 @@ main( int argc, char **argv )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -190,7 +190,7 @@ main( int argc, char *argv[] )
}
assert( authzid == NULL );
authzid = control;
authzid = cvalue;
} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
if( manageDSAit ) {
......
......@@ -413,8 +413,9 @@ typedef struct ldapcontrol {
#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
......
......@@ -53,6 +53,7 @@ static struct ldaperror ldap_builtin_errlist[] = {
{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" },
......
......@@ -561,12 +561,10 @@ read_config( const char *fname, int depth )
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;
......
......@@ -44,18 +44,27 @@ typedef int (SLAP_CTRL_PARSE_FN) LDAP_P((
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;
......@@ -63,14 +72,12 @@ static struct slap_control {
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 },
......@@ -79,7 +86,12 @@ static struct slap_control {
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,
......@@ -316,8 +328,19 @@ int get_ctrls(
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;
......@@ -367,9 +390,11 @@ int get_ctrls(
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
......@@ -408,37 +433,101 @@ static int parseManageDSAit (
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,
......@@ -479,7 +568,7 @@ static int parsePagedResults (
}
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;
}
......@@ -555,7 +644,12 @@ int parseValuesReturnFilter (
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;
}
......@@ -599,6 +693,37 @@ int parseValuesReturnFilter (
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,
......@@ -620,7 +745,7 @@ static int parseClientUpdate (
}
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;
}
......
......@@ -150,6 +150,8 @@ do_extended(
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 ) {
......
......@@ -875,6 +875,9 @@ LDAP_SLAPD_F (int) slap_sasl_config(
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
......
......@@ -447,7 +447,7 @@ send_ldap_result(
#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,
......@@ -567,13 +567,12 @@ send_ldap_extended(
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;
......
......@@ -15,31 +15,28 @@
#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 )
......@@ -49,11 +46,13 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
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
......@@ -77,18 +76,42 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
#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
......@@ -98,8 +121,8 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
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",
......@@ -116,12 +139,12 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
} 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
......@@ -131,8 +154,8 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
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",
......@@ -145,42 +168,18 @@ int slap_sasl_config( int cargc, char **cargv, char *line,
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",