You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@directory.apache.org by Alex Karasulu <ao...@bellsouth.net> on 2005/10/16 10:24:03 UTC

[ApacheDS] Problems with using nextInterceptor.xxxx()

Trustin,


After adding ACI guards for search() I started getting some 
IndexOutOfBoundsExceptions.  These were resulting from peek() calls by 
interceptors on an empty InvocationStack.  To sum up what's happening: 
the exceptions are resulting from calls to nextInterceptor.xxxx() within 
ACI tuple filters. 


Below is an in depth explanation of what's happening and why using 
nextInterceptor.xxxx() operations are *evil* ...


The search() method guards are implemented using a SearchResultFilter.  
This filter is used in conjunction with a 
SearchResultFilteringEnumeration which wraps the nexus returned 
enumeration.   It applies this filter to each candidate entry before it 
is returned to remove attributes or their values.  It also determines if 
the entry should be returned by the search at all.  I use the ACDFEngine 
obviously to perform access checks within the filter's accept() method. 


The search() method (and list() also) is very special in terms of 
interceptor handling.  Special, because both these operations produce 
NamingEnumerations.  The enumerations once returned by the proxy, are 
used to retrieve entries.  Calls to next() on enumerations invoke code 
that executes behind the nexus proxy even though the "interception" 
process is over.  Let me show the steps that lead to this 
IndexOutOfBoundsException:


1). A search() is invoked on a ServerDirContext
2). ServerDirContext transforms some arguments and forwards call to a 
search() method on the DirectoryPartitionNexusProxy
  (a) Proxy pushes a search operation Invocation onto InvocationStack: 
this Invocation object contains a handle to the JNDI context used to 
initiate the search() operation
  (b) Proxy then forwards the search() call to InterceptorChain
3). InterceptorChain after invoking search() on all interceptors finally 
calls search() on the DirectoryPartitionNexus which returns a 
NamingEnumeration
4). While returning through all the interceptors in the chain, the 
NamingEnumeration returned by the nexus is wrapped by one or more 
interceptors using a SearchResultFilteringEnumeration.
5). The wrapped NamingEnumeration returns from the call to the 
InterceptorChain
6). The proxy then pops the Invocation stack (so the stack is empty)
7). Calls are made to the enumeration's next() method
  (a) accept() methods of SearchResultFilters are invoked.  These 
SearchResultFilters are usually defined as inner classes within an 
Interceptor and they have access to the Interceptor's members and methods.
  (b) accept() methods invoke the ACDFEngine to determine whether or not 
to return an entry, remove attributes, or just values from attributes
  (c) ACDFEngine calls nextInterceptor.xxxx() to do its job
  (d) Downstream interceptors peek() on the empty InvocationStack to 
produce IndexOutOfBoundsExceptions

What does all this mean in the end?  We cannot invoke 
nextInterceptor.xxxx() methods from within SearchResultFilter.accept() 
methods since they *can* execute when the stack is empty.  There are two 
choices for us:

1).  Call the nexus directly
2).  Call the nexus proxy

The first option is risky.  It does not take into account things managed 
by other interceptors like entries that are marked deleted but have yet 
to be deleted.  Or for example when operational attributes like 
modifyTimestamp are updated.  These would all have to be managed 
manually and there would be much code duplication defeating the purpose 
for these interceptors.

The second option is a PITA because we have to figure out the identity 
that we must execute the code as.  Sometimes it should be as the user 
that is performing the search and sometimes it should be as the admin to 
access sensitive internal server information.  If it is the admin then 
we have to authenticate as the admin or do we?  Perhaps admin access can 
be rigged in somehow without requiring authentication? See how this 
becomes a problem.

So do you have any ideas here?  I know this is a lot of stuff.  I'm just 
not doing too well with ideas at the moment. Hopefully you have a quick 
nice solution in mind already :-).

Thanks,
Alex



Re: [ApacheDS] Problems with using nextInterceptor.xxxx()

Posted by Trustin Lee <tr...@gmail.com>.
Hi Alex,

2005/10/16, Alex Karasulu <ao...@bellsouth.net>:
>
> The search() method (and list() also) is very special in terms of
> interceptor handling. Special, because both these operations produce
> NamingEnumerations. The enumerations once returned by the proxy, are
> used to retrieve entries. Calls to next() on enumerations invoke code
> that executes behind the nexus proxy even though the "interception"
> process is over. Let me show the steps that lead to this
> IndexOutOfBoundsException:
>
> 1). A search() is invoked on a ServerDirContext
> 2). ServerDirContext transforms some arguments and forwards call to a
> search() method on the DirectoryPartitionNexusProxy
> (a) Proxy pushes a search operation Invocation onto InvocationStack:
> this Invocation object contains a handle to the JNDI context used to
> initiate the search() operation
> (b) Proxy then forwards the search() call to InterceptorChain
> 3). InterceptorChain after invoking search() on all interceptors finally
> calls search() on the DirectoryPartitionNexus which returns a
> NamingEnumeration
> 4). While returning through all the interceptors in the chain, the
> NamingEnumeration returned by the nexus is wrapped by one or more
> interceptors using a SearchResultFilteringEnumeration.
> 5). The wrapped NamingEnumeration returns from the call to the
> InterceptorChain
> 6). The proxy then pops the Invocation stack (so the stack is empty)
> 7). Calls are made to the enumeration's next() method
> (a) accept() methods of SearchResultFilters are invoked. These
> SearchResultFilters are usually defined as inner classes within an
> Interceptor and they have access to the Interceptor's members and methods.
> (b) accept() methods invoke the ACDFEngine to determine whether or not
> to return an entry, remove attributes, or just values from attributes
> (c) ACDFEngine calls nextInterceptor.xxxx() to do its job
> (d) Downstream interceptors peek() on the empty InvocationStack to
> produce IndexOutOfBoundsExceptions


I understood it fully thanks to your great explanation.

What does all this mean in the end? We cannot invoke
> nextInterceptor.xxxx() methods from within SearchResultFilter.accept()
> methods since they *can* execute when the stack is empty. There are two
> choices for us:
>
> 1). Call the nexus directly
> 2). Call the nexus proxy
>
> The first option is risky. It does not take into account things managed
> by other interceptors like entries that are marked deleted but have yet
> to be deleted. Or for example when operational attributes like
> modifyTimestamp are updated. These would all have to be managed
> manually and there would be much code duplication defeating the purpose
> for these interceptors.


Yes, it is risky and should be performed only when it is required without
questions.

The second option is a PITA because we have to figure out the identity
> that we must execute the code as. Sometimes it should be as the user
> that is performing the search and sometimes it should be as the admin to
> access sensitive internal server information. If it is the admin then
> we have to authenticate as the admin or do we? Perhaps admin access can
> be rigged in somehow without requiring authentication? See how this
> becomes a problem.


Yes, we can modify the users identity temporarilly. In case of search, I
think it is a right way to go.

So do you have any ideas here? I know this is a lot of stuff. I'm just
> not doing too well with ideas at the moment. Hopefully you have a quick
> nice solution in mind already :-).


I'll modify DirectoryService (or DirectoryServiceConfiguration) to provide
more getter methods such as getProxiedPartitionNexus() besides
getJndiContext(). WDYT?

Trustin
--
what we call human nature is actually human habit
--
http://gleamynode.net/