Skip to content
Snippets Groups Projects
Commit cdb11fc5 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

add administrative bind and proxyAuthz control to enable bound operations in...

add administrative bind and proxyAuthz control to enable bound operations in distributed directories (need to manually #define LDAP_BACK_PROXY_AUTHZ and patches from ITS#2851 and ITS#2852)
parent 2c68cb41
No related branches found
No related tags found
No related merge requests found
......@@ -73,6 +73,10 @@ ldap_back_add(
struct berval mdn = { 0, NULL };
ber_int_t msgid;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
int rc = LDAP_SUCCESS;
#endif /* LDAP_BACK_PROXY_AUTHZ */
#ifdef NEW_LOGGING
LDAP_LOG( BACK_LDAP, ENTRY, "ldap_back_add: %s\n", op->o_req_dn.bv_val, 0, 0 );
......@@ -149,8 +153,29 @@ ldap_back_add(
}
attrs[i] = NULL;
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_add_ext(lc->ld, mdn.bv_val, attrs,
op->o_ctrls, NULL, &msgid);
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL, &msgid);
#ifdef LDAP_BACK_PROXY_AUTHZ
cleanup:
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
for (--i; i>= 0; --i) {
ch_free(attrs[i]->mod_vals.modv_bvals);
ch_free(attrs[i]);
......@@ -159,7 +184,12 @@ ldap_back_add(
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
return -1;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
return ldap_back_op_result( lc, op, rs, msgid, 1 ) != LDAP_SUCCESS;
}
......@@ -210,6 +210,15 @@ extern int ldap_dnattr_result_rewrite( dncookie *dc, BerVarray a_vals );
extern int ldap_chain_setup();
#ifdef LDAP_BACK_PROXY_AUTHZ
extern int
ldap_back_proxy_authz_ctrl(
struct ldapconn *lc,
Operation *op,
SlapReply *rs,
LDAPControl ***pctrls );
#endif /* LDAP_BACK_PROXY_AUTHZ */
LDAP_END_DECL
#endif /* SLAPD_LDAP_H */
......@@ -404,13 +404,52 @@ ldap_back_getconn(Operation *op, SlapReply *rs)
int
ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
{
struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
int rc;
ber_int_t msgid;
ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
if ( !lc->bound ) {
rs->sr_err = ldap_sasl_bind(lc->ld, lc->bound_dn.bv_val,
LDAP_SASL_SIMPLE, &lc->cred, NULL, NULL, &msgid);
#ifdef LDAP_BACK_PROXY_AUTHZ
int gotit = 0;
#if 0
int i;
/*
* FIXME: we need to let clients use proxyAuthz
* otherwise we cannot do symmetric pools of servers;
* we have to live with the fact that a user can
* authorize itself as any ID that is allowed
* by the saslAuthzTo directive of the "binddn".
*/
for ( i = 0; op->o_ctrls && op->o_ctrls[ i ]; i++ ) {
if ( strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PROXY_AUTHZ ) == 0 ) {
gotit = 1;
break;
}
}
#endif
/*
* if no bind took place yet, but the connection is bound
* and the binddn is set, then bind with binddn and
* explicitly add proxyAuthz control to every operation
* with the dn bound to the connection as control value.
*/
if ( ( lc->bound_dn.bv_val == NULL || lc->bound_dn.bv_len == 0 )
&& ( op->o_conn && op->o_conn->c_dn.bv_val != NULL && op->o_conn->c_dn.bv_len != 0 )
&& ( li->binddn.bv_val != NULL && li->binddn.bv_len != 0 )
&& ! gotit ) {
rs->sr_err = ldap_sasl_bind(lc->ld, li->binddn.bv_val,
LDAP_SASL_SIMPLE, &li->bindpw, NULL, NULL, &msgid);
} else
#endif /* LDAP_BACK_PROXY_AUTHZ */
{
rs->sr_err = ldap_sasl_bind(lc->ld, lc->bound_dn.bv_val,
LDAP_SASL_SIMPLE, &lc->cred, NULL, NULL, &msgid);
}
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
if (rc == LDAP_SUCCESS) {
lc->bound = 1;
......@@ -550,3 +589,98 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
return( (rs->sr_err == LDAP_SUCCESS) ? 0 : -1 );
}
#ifdef LDAP_BACK_PROXY_AUTHZ
/*
* ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control
* to existing server-side controls if required; if not,
* the existing server-side controls are placed in *pctrls.
* The caller, after using the controls in client API
* operations, if ( *pctrls != op->o_ctrls ), should
* free( (*pctrls)[ 0 ] ) and free( *pctrls ).
* The function returns success if the control could
* be added if required, or if it did nothing; in the future,
* it might return some error if it failed.
*
* if no bind took place yet, but the connection is bound
* and the binddn is set, then bind with binddn and
* explicitly add proxyAuthz control to every operation
* with the dn bound to the connection as control value.
*
* If no server-side controls are defined for the operation,
* simply add the proxyAuthz control; otherwise, if the
* proxyAuthz control is not already set, add it as
* the first one (FIXME: is controls order significant
* for security?).
*/
int
ldap_back_proxy_authz_ctrl(
struct ldapconn *lc,
Operation *op,
SlapReply *rs,
LDAPControl ***pctrls )
{
struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
LDAPControl **ctrls = NULL;
*pctrls = NULL;
if ( ( lc->bound_dn.bv_val == NULL || lc->bound_dn.bv_len == 0 )
&& ( op->o_conn && op->o_conn->c_dn.bv_val != NULL && op->o_conn->c_dn.bv_len != 0 )
&& ( li->binddn.bv_val != NULL && li->binddn.bv_len != 0 ) ) {
int i = 0, gotit = 0;
if ( op->o_ctrls ) {
for ( i = 0; op->o_ctrls[i]; i++ ) {
if ( strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PROXY_AUTHZ ) == 0 ) {
gotit = 1;
break;
}
}
}
if ( ! gotit ) {
ctrls = ch_malloc( sizeof( LDAPControl * ) * (i + 2) );
ctrls[ 0 ] = ch_malloc( sizeof( LDAPControl ) );
ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
ctrls[ 0 ]->ldctl_iscritical = 1;
ctrls[ 0 ]->ldctl_value.bv_len = op->o_conn->c_dn.bv_len + 3;
ctrls[ 0 ]->ldctl_value.bv_val = ch_malloc( ctrls[ 0 ]->ldctl_value.bv_len + 1 );
AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", sizeof( "dn:" ) - 1 );
AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val + sizeof( "dn:") - 1,
op->o_conn->c_dn.bv_val, op->o_conn->c_dn.bv_len + 1 );
if ( op->o_ctrls ) {
for ( i = 0; op->o_ctrls[ i ]; i++ ) {
ctrls[ i + 1 ] = op->o_ctrls[ i ];
}
}
ctrls[ i + 1 ] = NULL;
} else {
/*
* FIXME: we do not want to perform proxyAuthz
* on behalf of the client, because this would
* be performed with "binddn" privileges.
*
* This might actually be too strict, since
* the "binddn" saslAuthzTo, and each entry's
* saslAuthzFrom attributes may be crafted
* to avoid unwanted proxyAuthz to take place.
*/
#if 0
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "proxyAuthz not allowed within namingContext";
#endif
}
}
if ( ctrls == NULL ) {
ctrls = op->o_ctrls;
}
*pctrls = ctrls;
return rs->sr_err;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
......@@ -66,11 +66,15 @@ ldap_back_compare(
{
struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
struct ldapconn *lc;
struct berval mapped_at, mapped_val;
struct berval mapped_at = { 0, NULL }, mapped_val = { 0, NULL };
struct berval mdn = { 0, NULL };
ber_int_t msgid;
int freeval = 0;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
int rc = LDAP_SUCCESS;
#endif /* LDAP_BACK_PROXY_AUTHZ */
lc = ldap_back_getconn(op, rs);
if (!lc || !ldap_back_dobind( lc, op, rs ) ) {
......@@ -119,18 +123,47 @@ ldap_back_compare(
} else if (mapped_val.bv_val != op->orc_ava->aa_value.bv_val) {
freeval = 1;
}
} else {
mapped_val = op->orc_ava->aa_value;
}
}
rs->sr_err = ldap_compare_ext( lc->ld, mdn.bv_val, mapped_at.bv_val,
&mapped_val, op->o_ctrls, NULL, &msgid );
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_compare_ext( lc->ld, mdn.bv_val,
mapped_at.bv_val, &mapped_val,
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL, &msgid );
#ifdef LDAP_BACK_PROXY_AUTHZ
cleanup:
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
if ( freeval ) {
free( mapped_val.bv_val );
}
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
return -1;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
}
......@@ -68,6 +68,10 @@ ldap_back_delete(
struct ldapconn *lc;
ber_int_t msgid;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
int rc = LDAP_SUCCESS;
#endif /* LDAP_BACK_PROXY_AUTHZ */
struct berval mdn = { 0, NULL };
......@@ -93,13 +97,40 @@ ldap_back_delete(
send_ldap_result( op, rs );
return -1;
}
rs->sr_err = ldap_delete_ext( lc->ld, mdn.bv_val, op->o_ctrls,
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_delete_ext( lc->ld, mdn.bv_val,
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL, &msgid );
#ifdef LDAP_BACK_PROXY_AUTHZ
cleanup:
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
return -1;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
}
......@@ -48,7 +48,40 @@ ldap_back_extended(
for( i=0; exop_table[i].extended != NULL; i++ ) {
if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
#ifdef LDAP_BACK_PROXY_AUTHZ
struct ldapconn *lc;
LDAPControl **oldctrls = NULL;
int rc;
/* FIXME: this needs to be called here, so it is
* called twice; maybe we could avoid the
* ldap_back_dobind() call inside each extended()
* call ... */
lc = ldap_back_getconn(op, rs);
if (!lc || !ldap_back_dobind(lc, op, rs) ) {
return -1;
}
oldctrls = op->o_ctrls;
if ( ldap_back_proxy_authz_ctrl( lc, op, rs, &op->o_ctrls ) ) {
op->o_ctrls = oldctrls;
send_ldap_result( op, rs );
rs->sr_text = NULL;
return rs->sr_err;
}
rc = (exop_table[i].extended)( op, rs );
if ( op->o_ctrls && op->o_ctrls != oldctrls ) {
free( op->o_ctrls[ 0 ] );
free( op->o_ctrls );
}
op->o_ctrls = oldctrls;
return rc;
#else /* ! LDAP_BACK_PROXY_AUTHZ */
return (exop_table[i].extended)( op, rs );
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
}
}
......
......@@ -74,6 +74,9 @@ ldap_back_modify(
struct berval mdn = { 0, NULL };
ber_int_t msgid;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
#endif /* LDAP_BACK_PROXY_AUTHZ */
lc = ldap_back_getconn(op, rs);
if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
......@@ -181,10 +184,29 @@ ldap_back_modify(
}
modv[i] = 0;
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_modify_ext( lc->ld, mdn.bv_val, modv,
op->o_ctrls, NULL, &msgid );
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL, &msgid );
cleanup:;
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
......@@ -194,6 +216,13 @@ cleanup:;
ch_free( mods );
ch_free( modv );
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
return -1;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
return ldap_back_op_result( lc, op, rs, msgid, 1 );
}
......@@ -68,6 +68,10 @@ ldap_back_modrdn(
struct ldapconn *lc;
ber_int_t msgid;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
int rc = LDAP_SUCCESS;
#endif /* LDAP_BACK_PROXY_AUTHZ */
struct berval mdn = { 0, NULL }, mnewSuperior = { 0, NULL };
......@@ -112,11 +116,31 @@ ldap_back_modrdn(
return -1;
}
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
goto cleanup;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_rename( lc->ld, mdn.bv_val,
op->orr_newrdn.bv_val, mnewSuperior.bv_val,
op->orr_deleteoldrdn, op->o_ctrls,
op->orr_deleteoldrdn,
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL, &msgid );
#ifdef LDAP_BACK_PROXY_AUTHZ
cleanup:
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
......@@ -124,7 +148,14 @@ ldap_back_modrdn(
&& mnewSuperior.bv_val != op->oq_modrdn.rs_newSup->bv_val ) {
free( mnewSuperior.bv_val );
}
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
return -1;
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
return( ldap_back_op_result( lc, op, rs, msgid, 1 ) );
}
......@@ -88,7 +88,11 @@ ldap_back_search(
struct berval mfilter = { 0, NULL };
struct slap_limits_set *limit = NULL;
int isroot = 0;
int dontfreetext = 0;
dncookie dc;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
#endif /* LDAP_BACK_PROXY_AUTHZ */
lc = ldap_back_getconn(op, rs);
if ( !lc ) {
......@@ -181,6 +185,7 @@ ldap_back_search(
if ( rc ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "Rewrite error";
dontfreetext = 1;
rc = -1;
goto finish;
}
......@@ -193,27 +198,26 @@ ldap_back_search(
goto finish;
}
#if 0
if ( mapped_attrs == NULL && op->oq_search.rs_attrs) {
int count;
/* this can happen only if ch_calloc() fails
* in ldap_back_map_attrs() */
for (count=0; op->oq_search.rs_attrs[count].an_name.bv_val; count++);
mapped_attrs = ch_malloc( (count+1) * sizeof(char *));
for (count=0; op->oq_search.rs_attrs[count].an_name.bv_val; count++) {
mapped_attrs[count] = op->oq_search.rs_attrs[count].an_name.bv_val;
}
mapped_attrs[count] = NULL;
#ifdef LDAP_BACK_PROXY_AUTHZ
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
dontfreetext = 1;
goto finish;
}
#endif
#endif /* LDAP_BACK_PROXY_AUTHZ */
rs->sr_err = ldap_search_ext(lc->ld, mbase.bv_val,
op->oq_search.rs_scope, mfilter.bv_val,
mapped_attrs, op->oq_search.rs_attrsonly,
op->o_ctrls, NULL,
#ifdef LDAP_BACK_PROXY_AUTHZ
ctrls,
#else /* ! LDAP_BACK_PROXY_AUTHZ */
op->o_ctrls,
#endif /* ! LDAP_BACK_PROXY_AUTHZ */
NULL,
tv.tv_sec ? &tv : NULL, op->oq_search.rs_slimit,
&msgid);
&msgid );
if ( rs->sr_err != LDAP_SUCCESS ) {
fail:;
rc = ldap_back_op_result(lc, op, rs, msgid, 0);
......@@ -347,6 +351,13 @@ fail:;
finish:;
send_ldap_result( op, rs );
#ifdef LDAP_BACK_PROXY_AUTHZ
if ( ctrls && ctrls != op->o_ctrls ) {
free( ctrls[ 0 ] );
free( ctrls );
}
#endif /* LDAP_BACK_PROXY_AUTHZ */
if ( match.bv_val ) {
if ( rs->sr_matched != match.bv_val ) {
free( (char *)rs->sr_matched );
......@@ -355,7 +366,9 @@ finish:;
LDAP_FREE( match.bv_val );
}
if ( rs->sr_text ) {
LDAP_FREE( (char *)rs->sr_text );
if ( !dontfreetext ) {
LDAP_FREE( (char *)rs->sr_text );
}
rs->sr_text = NULL;
}
if ( mapped_attrs ) {
......@@ -536,7 +549,6 @@ ldap_build_entry(
} else if ( attr->a_desc->ad_type->sat_syntax ==
slap_schema.si_syn_distinguishedName ) {
ldap_dnattr_result_rewrite( &dc, attr->a_vals );
}
if ( normalize && last && attr->a_desc->ad_type->sat_equality &&
......@@ -560,6 +572,7 @@ ldap_build_entry(
*attrp = attr;
attrp = &attr->a_next;
}
/* make sure it's free'able */
if (!private && ent->e_name.bv_val == bdn->bv_val)
ber_dupbv( &ent->e_name, bdn );
......@@ -646,7 +659,7 @@ ldap_back_entry_get(
*ptr++ = ')';
*ptr++ = '\0';
}
if (ldap_search_ext_s(lc->ld, mdn.bv_val, LDAP_SCOPE_BASE, filter,
gattr, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result) != LDAP_SUCCESS)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment