Oleg
I looked into this a little more this
morning. I would not suggest committing that "work around", as I
don't think it really properly solves the problem.
Here's what I'm thinking. I think the following should
be handled in the SecurityInterceptor, in the sequence specified for each invoke
and invokeHome call:
(1) authenticate caller principal, as set by
client
(2) realm mapping - run as what principal
(3) checking permissions - for the mapped
principal
(4) associate the mapped principal / credential with
thread
(5) invoke next level
interceptor
(6) associate original client
principal / credential with thread
Right now, it appears
that the realm mapping is done in EnterpriseContext.java [bypassing the
permission checks], and the association of a principal with a thread is
partially handled in SecurityInterceptor, but not completely [in
SecurityAssociation, if a principal is already associated with a thread,
authentication and permission checks are not evaluated --- but the association
could have been set in a completely different client invocation!]. The
work-around was to hack EnterpriseContext.java for that
problem.
Last, it is necessary to "revert" the principal
association because realm mapping could have happened in a nested bean call,
which would change the principal associated with the thread. [ By the way, Realm
mapping must map credentials as well as principal, correct? Otherwise,
nested invocations may fail authentication. ]
The caller principal (unmapped)
should be determined prior to calling the SecurityInterceptor. For RMI
calls, it's handled from the RMI handler (what class?). For in-VM calls,
it should be determined from the thread association (in GenericProxy). So
I think this part is already handled correctly.
However...
I think the six steps listed above are logically
correct, but, as stated, it forces nested calls to be authenticated.
However, since most nested calls will not change the principal, the
authentication can be cached -- that is, if the principal has been authenticated
already, no need to do it again.
But if the principal is changed by mapping, should the mapped
principal / credential be authenticated? (Clearly necessary on out-of-VM
calls, but may not be necessary for in-VM calls.)
Transactions...
If a method
invocation fails because of security (insufficient permissions), should the
transaction be set for rollback only? I'm looking at section 17.3 of the
EJB 2.0 draft spec; it appears that this may be required in some
cases.
- Keith
-----Original Message-----
From: Oleg Nitz <[EMAIL PROTECTED]>
To: jBoss <[EMAIL PROTECTED]>
Date: Thursday, November 23, 2000 7:10 AM
Subject: Re: [jBoss-User] CallerPrincipal propagation
>Hi Keith,From: Oleg Nitz <[EMAIL PROTECTED]>
To: jBoss <[EMAIL PROTECTED]>
Date: Thursday, November 23, 2000 7:10 AM
Subject: Re: [jBoss-User] CallerPrincipal propagation
>
>Thank you, your analysis is thorough and your workaround is acceptable
>for now, I propose to commit to CVS it unless Rickard or Dan or
>somebody else will help us to find better solution quickly -
>unfortunately, I never really investigated RMI calls internals,
>GenericProxy and so on, I have to dig into this stuff.
>
>Best regards,
> Oleg
>
>Keith L. Musser wrote:
>KLM> Oleg,
>
>KLM> I'm still finding problems with principal propagation. Since you responded to this earlier, I'm sending this email to you directly. See bottom for a description of the problem, and here for a
>KLM> workaround.
>
>KLM> (By the way, after writing the attached problem description, I discovered that the same problem occurs if I use JNDI to get the home interface. To see the problem, the client or clients must be
>KLM> accessing the same beans from different principals, as in a web application.)
>
>KLM> I found a workaround for this problem, but this is not a "good" solution. I was unable to follow the intended logic for principal propagation -- it appears it may be a bit different for in-VM
>KLM> compared with RMI calls. Anyway, I don't have a suggestion on what a good solution is. But the workaround should at least illustrate what's happening.
>
>KLM> My workaround is to modify EnterpriseContext.java as follows:
>
>KLM> ORIGINAL:
>
>KLM> public void setPrincipal( Principal principal ){
>KLM> this.principal = principal;
>KLM> this.beanPrincipal = null;
>KLM> }
>
>KLM> WORKAROUND:
>
>KLM> public void setPrincipal( Principal principal ){
>KLM> this.principal = principal;
>KLM> this.beanPrincipal = null;
>KLM> SecurityAssociation.setPrincipal(principal);
>KLM> }
>
>KLM> It seems (but I'm not sure) that the thread-local SecurityAssociation is set for some RMI calls but not for all of them. However, the principal seems to always be set correctly for non-nested
>KLM> calls. However, when a bean calls another bean, the RMI-based propagation is not used (since RMI is not used). Instead, GenericProxy uses the SecurityAssociation to get the principal. But
>KLM> sometimes it has not been set.
>
>KLM> The workaround makes sure that the SecurityAssociation gets set, so if needed later by a nested (non-RMI) invocation, the principal is valid.
>
>KLM> Also, please note that I don't know if my workaround works in all cases. I only know that it solved the specific instance of the problem that I am having.
>
>KLM> As you can see, this isn't elegant. (I presume all this stuff should be set in the SecurityInterceptor?) But hopefully it illustrates what the problem is so you can find a good solution.
>
>KLM> - Keith
>KLM> -----Original Message-----
>KLM> From: Keith L. Musser <[EMAIL PROTECTED]>
>KLM> To: jBOSS-User <[EMAIL PROTECTED]>
>KLM> Date: Wednesday, November 22, 2000 5:57 PM
>KLM> Subject: [jBoss-User] CallerPrincipal propagation
>
>
>KLM> I'm using ctx.getCallerPrincipal() extensively for fine-grained security which I control. I depend only on JBoss to ensure that the caller principal is set correctly on every invocation.
>
>KLM> This works most of the time (with a fix I've discussed on this group earlier). However, I'm having one problem, and I don't know if it's a bug or if I'm violating the EJB spec.
>
>KLM> In my "User" entity bean I want to get a reference to a different instance of "User". I do this:
>
>KLM> public void myMethod( ) throws RemoteException {
>KLM> ....
>KLM> UserHome h = ctx.getEJBHome();
>KLM> User otherUser = h.findByPrimaryKey( key );
>KLM> ...
>KLM> }
>
>KLM> The problem is that the caller principal when I invoke methods on otherUser is NOT the caller principal from the calling thread. Rather, it is the caller principal which was used when my
>KLM> client retrieved the UserHome at an earlier point.
>
>KLM> If it is legal to call "getEJBHome" inside of a bean, then there appears to be a bug in the way caller principal is propagated to the home.
>
>KLM> (I recognize that an alternative is to lookup the home as an EJB reference using JNDI, and I assume the caller is propagated that way. However, it seems to me "getEJBHome" should work also.)
>
>KLM> Keith L. Musser
>KLM> Integrated Dynamics, Inc.
>KLM> 812-371-7777
>KLM> email: [EMAIL PROTECTED]
>
>
>
>
>--
>--------------------------------------------------------------
>To subscribe: [EMAIL PROTECTED]
>To unsubscribe: [EMAIL PROTECTED]
>Problems?: [EMAIL PROTECTED]
>
>
