|
|
@@ -16,8 +16,8 @@
|
|
|
#include "back-ldbm.h"
|
|
|
|
|
|
|
|
|
-static struct backentry *find_entry_internal_dn(Slapi_PBlock *pb, backend *be, const Slapi_DN *sdn, int lock, back_txn *txn, int flags);
|
|
|
-static struct backentry * find_entry_internal(Slapi_PBlock *pb, Slapi_Backend *be, const entry_address *addr, int lock, back_txn *txn, int flags);
|
|
|
+static struct backentry *find_entry_internal_dn(Slapi_PBlock *pb, backend *be, const Slapi_DN *sdn, int lock, back_txn *txn, int flags, int *rc);
|
|
|
+static struct backentry * find_entry_internal(Slapi_PBlock *pb, Slapi_Backend *be, const entry_address *addr, int lock, back_txn *txn, int flags, int *rc);
|
|
|
/* The flags take these values */
|
|
|
#define FE_TOMBSTONE_INCLUDED TOMBSTONE_INCLUDED /* :1 defined in back-ldbm.h */
|
|
|
#define FE_REALLY_INTERNAL 0x2
|
|
|
@@ -27,7 +27,7 @@ check_entry_for_referral(Slapi_PBlock *pb, Slapi_Entry *entry, char *matched, co
|
|
|
{
|
|
|
int rc=0, i=0, numValues=0;
|
|
|
Slapi_Attr *attr;
|
|
|
- Slapi_Value *val=NULL;
|
|
|
+ Slapi_Value *val=NULL;
|
|
|
struct berval **refscopy=NULL;
|
|
|
struct berval **url=NULL;
|
|
|
|
|
|
@@ -80,12 +80,13 @@ out:
|
|
|
|
|
|
static struct backentry *
|
|
|
find_entry_internal_dn(
|
|
|
- Slapi_PBlock *pb,
|
|
|
+ Slapi_PBlock *pb,
|
|
|
backend *be,
|
|
|
const Slapi_DN *sdn,
|
|
|
int lock,
|
|
|
- back_txn *txn,
|
|
|
- int flags
|
|
|
+ back_txn *txn,
|
|
|
+ int flags,
|
|
|
+ int *rc /* return code */
|
|
|
)
|
|
|
{
|
|
|
struct backentry *e;
|
|
|
@@ -93,9 +94,14 @@ find_entry_internal_dn(
|
|
|
int err;
|
|
|
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
|
|
|
size_t tries = 0;
|
|
|
+ int isroot = 0;
|
|
|
+ int op_type;
|
|
|
+ char *errbuf = NULL;
|
|
|
|
|
|
/* get the managedsait ldap message control */
|
|
|
- slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
|
|
|
+ slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
|
|
|
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
|
|
|
+ slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
|
|
|
|
|
|
while ( (tries < LDBM_CACHE_RETRY_COUNT) &&
|
|
|
(e = dn2entry_ext( be, sdn, txn, flags & TOMBSTONE_INCLUDED, &err ))
|
|
|
@@ -113,6 +119,9 @@ find_entry_internal_dn(
|
|
|
if(check_entry_for_referral(pb, e->ep_entry, NULL, "find_entry_internal_dn"))
|
|
|
{
|
|
|
CACHE_RETURN( &inst->inst_cache, &e );
|
|
|
+ if (rc) { /* if check_entry_for_referral returns non-zero, result is sent. */
|
|
|
+ *rc = FE_RC_SENT_RESULT;
|
|
|
+ }
|
|
|
return( NULL );
|
|
|
}
|
|
|
}
|
|
|
@@ -151,27 +160,89 @@ find_entry_internal_dn(
|
|
|
struct backentry *me;
|
|
|
Slapi_DN ancestorsdn;
|
|
|
slapi_sdn_init(&ancestorsdn);
|
|
|
- me= dn2ancestor(pb->pb_backend,sdn,&ancestorsdn,txn,&err);
|
|
|
+ me = dn2ancestor(pb->pb_backend, sdn, &ancestorsdn, txn, &err, 1 /* allow_suffix */);
|
|
|
if ( !managedsait && me != NULL ) {
|
|
|
/* if the entry is a referral send the referral */
|
|
|
if(check_entry_for_referral(pb, me->ep_entry, (char*)slapi_sdn_get_dn(&ancestorsdn), "find_entry_internal_dn"))
|
|
|
{
|
|
|
CACHE_RETURN( &inst->inst_cache, &me );
|
|
|
slapi_sdn_done(&ancestorsdn);
|
|
|
+ if (rc) { /* if check_entry_for_referral returns non-zero, result is sent. */
|
|
|
+ *rc = FE_RC_SENT_RESULT;
|
|
|
+ }
|
|
|
return( NULL );
|
|
|
}
|
|
|
/* else fall through to no such object */
|
|
|
}
|
|
|
|
|
|
/* entry not found */
|
|
|
- slapi_send_ldap_result( pb, ( 0 == err || DB_NOTFOUND == err ) ?
|
|
|
- LDAP_NO_SUCH_OBJECT : ( LDAP_INVALID_DN_SYNTAX == err ) ?
|
|
|
- LDAP_INVALID_DN_SYNTAX : LDAP_OPERATIONS_ERROR,
|
|
|
- (char*)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL );
|
|
|
+ if ((0 == err) || (DB_NOTFOUND == err)) {
|
|
|
+ if (me && !isroot) {
|
|
|
+ /* If not root, you may not want to reveal it. */
|
|
|
+ int acl_type = -1;
|
|
|
+ int return_err = LDAP_NO_SUCH_OBJECT;
|
|
|
+ err = LDAP_SUCCESS;
|
|
|
+ switch (op_type) {
|
|
|
+ case SLAPI_OPERATION_ADD:
|
|
|
+ acl_type = SLAPI_ACL_ADD;
|
|
|
+ return_err = LDAP_INSUFFICIENT_ACCESS;
|
|
|
+ break;
|
|
|
+ case SLAPI_OPERATION_DELETE:
|
|
|
+ acl_type = SLAPI_ACL_DELETE;
|
|
|
+ return_err = LDAP_INSUFFICIENT_ACCESS;
|
|
|
+ break;
|
|
|
+ case SLAPI_OPERATION_MODDN:
|
|
|
+ acl_type = SLAPI_ACL_MODDN;
|
|
|
+ return_err = LDAP_INSUFFICIENT_ACCESS;
|
|
|
+ break;
|
|
|
+ case SLAPI_OPERATION_MODIFY:
|
|
|
+ acl_type = SLAPI_ACL_WRITE;
|
|
|
+ return_err = LDAP_INSUFFICIENT_ACCESS;
|
|
|
+ break;
|
|
|
+ case SLAPI_OPERATION_SEARCH:
|
|
|
+ case SLAPI_OPERATION_COMPARE:
|
|
|
+ return_err = LDAP_SUCCESS;
|
|
|
+ acl_type = SLAPI_ACL_READ;
|
|
|
+ break;
|
|
|
+ case SLAPI_OPERATION_BIND:
|
|
|
+ acl_type = -1; /* skip acl check. acl is not set up for bind. */
|
|
|
+ return_err = LDAP_INVALID_CREDENTIALS;
|
|
|
+ slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "No such entry");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (acl_type > 0) {
|
|
|
+ err = plugin_call_acl_plugin(pb, me->ep_entry, NULL, NULL, acl_type,
|
|
|
+ ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
|
|
|
+ }
|
|
|
+ if (((acl_type > 0) && err) || (op_type == SLAPI_OPERATION_BIND)) {
|
|
|
+ /*
|
|
|
+ * Operations to be checked && ACL returns disallow.
|
|
|
+ * Not to disclose the info about the entry's existence,
|
|
|
+ * do not return the "matched" DN.
|
|
|
+ * Plus, the bind case returns LDAP_INAPPROPRIATE_AUTH.
|
|
|
+ */
|
|
|
+ slapi_send_ldap_result(pb, return_err, NULL, NULL, 0, NULL);
|
|
|
+ } else {
|
|
|
+ slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT,
|
|
|
+ (char*)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT,
|
|
|
+ (char*)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ slapi_send_ldap_result( pb, ( LDAP_INVALID_DN_SYNTAX == err ) ?
|
|
|
+ LDAP_INVALID_DN_SYNTAX : LDAP_OPERATIONS_ERROR,
|
|
|
+ (char*)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL );
|
|
|
+ }
|
|
|
+ if (rc) {
|
|
|
+ *rc = FE_RC_SENT_RESULT;
|
|
|
+ }
|
|
|
slapi_sdn_done(&ancestorsdn);
|
|
|
CACHE_RETURN( &inst->inst_cache, &me );
|
|
|
}
|
|
|
|
|
|
+ slapi_ch_free_string(&errbuf);
|
|
|
LDAPDebug( LDAP_DEBUG_TRACE, "<= find_entry_internal_dn not found (%s)\n",
|
|
|
slapi_sdn_get_dn(sdn), 0, 0 );
|
|
|
return( NULL );
|
|
|
@@ -183,11 +254,11 @@ find_entry_internal_dn(
|
|
|
*/
|
|
|
static struct backentry *
|
|
|
find_entry_internal_uniqueid(
|
|
|
- Slapi_PBlock *pb,
|
|
|
+ Slapi_PBlock *pb,
|
|
|
backend *be,
|
|
|
- const char *uniqueid,
|
|
|
+ const char *uniqueid,
|
|
|
int lock,
|
|
|
- back_txn *txn
|
|
|
+ back_txn *txn
|
|
|
)
|
|
|
{
|
|
|
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
|
|
|
@@ -243,8 +314,9 @@ find_entry_internal(
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
int lock,
|
|
|
- back_txn *txn,
|
|
|
- int flags
|
|
|
+ back_txn *txn,
|
|
|
+ int flags,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
/* check if we should search based on uniqueid or dn */
|
|
|
@@ -261,11 +333,9 @@ find_entry_internal(
|
|
|
LDAPDebug( LDAP_DEBUG_TRACE, "=> find_entry_internal (dn=%s) lock %d\n",
|
|
|
slapi_sdn_get_dn(addr->sdn), lock, 0 );
|
|
|
if (addr->sdn) {
|
|
|
- entry = find_entry_internal_dn (pb, be, addr->sdn,
|
|
|
- lock, txn, flags);
|
|
|
+ entry = find_entry_internal_dn (pb, be, addr->sdn, lock, txn, flags, rc);
|
|
|
} else {
|
|
|
- LDAPDebug0Args( LDAP_DEBUG_ANY,
|
|
|
- "find_entry_internal: Null target dn\n" );
|
|
|
+ LDAPDebug0Args( LDAP_DEBUG_ANY, "find_entry_internal: Null target dn\n" );
|
|
|
}
|
|
|
|
|
|
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= find_entry_internal\n" );
|
|
|
@@ -278,10 +348,11 @@ find_entry(
|
|
|
Slapi_PBlock *pb,
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
- back_txn *txn
|
|
|
+ back_txn *txn,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
- return( find_entry_internal( pb, be, addr, 0/*!lock*/, txn, 0/*flags*/ ) );
|
|
|
+ return(find_entry_internal(pb, be, addr, 0/*!lock*/, txn, 0/*flags*/, rc));
|
|
|
}
|
|
|
|
|
|
struct backentry *
|
|
|
@@ -289,10 +360,11 @@ find_entry2modify(
|
|
|
Slapi_PBlock *pb,
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
- back_txn *txn
|
|
|
+ back_txn *txn,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
- return( find_entry_internal( pb, be, addr, 1/*lock*/, txn, 0/*flags*/ ) );
|
|
|
+ return(find_entry_internal(pb, be, addr, 1/*lock*/, txn, 0/*flags*/, rc));
|
|
|
}
|
|
|
|
|
|
/* New routines which do not do any referral stuff.
|
|
|
@@ -304,10 +376,11 @@ find_entry_only(
|
|
|
Slapi_PBlock *pb,
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
- back_txn *txn
|
|
|
+ back_txn *txn,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
- return( find_entry_internal( pb, be, addr, 0/*!lock*/, txn, FE_REALLY_INTERNAL ) );
|
|
|
+ return(find_entry_internal(pb, be, addr, 0/*!lock*/, txn, FE_REALLY_INTERNAL, rc));
|
|
|
}
|
|
|
|
|
|
struct backentry *
|
|
|
@@ -315,10 +388,11 @@ find_entry2modify_only(
|
|
|
Slapi_PBlock *pb,
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
- back_txn *txn
|
|
|
+ back_txn *txn,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
- return( find_entry_internal( pb, be, addr, 1/*lock*/, txn, FE_REALLY_INTERNAL ) );
|
|
|
+ return(find_entry_internal(pb, be, addr, 1/*lock*/, txn, 0 /* to check aci, disable INTERNAL */, rc));
|
|
|
}
|
|
|
|
|
|
struct backentry *
|
|
|
@@ -327,10 +401,9 @@ find_entry2modify_only_ext(
|
|
|
Slapi_Backend *be,
|
|
|
const entry_address *addr,
|
|
|
int flags,
|
|
|
- back_txn *txn
|
|
|
-
|
|
|
+ back_txn *txn,
|
|
|
+ int *rc
|
|
|
)
|
|
|
{
|
|
|
- return( find_entry_internal( pb, be, addr, 1/*lock*/, txn,
|
|
|
- FE_REALLY_INTERNAL | flags ));
|
|
|
+ return(find_entry_internal(pb, be, addr, 1/*lock*/, txn, FE_REALLY_INTERNAL | flags, rc));
|
|
|
}
|