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 );
}
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]);
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;
}
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 */
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;
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 */
{
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 ) ) {
} 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 ) );
}
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 };
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 ) );
}
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 */
}
}
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 ) ) {
}
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 );
}
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 );
}
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 };
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 );
}
&& 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 ) );
}
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 ) {
if ( rc ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "Rewrite error";
+ dontfreetext = 1;
rc = -1;
goto finish;
}
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);
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 );
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 ) {
} 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 &&
*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 );
*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)