Hi Marc,

I saw this problem in 3.2.1 as well  - I made a fix for it in the tomcat that ships with the Borland AppServer but
couldn't get anyone to comment on the fix in the main code-line (essentially I'm not a commiter so couldn't submit the fix)

Here's what I found:

The following code is in org.apache.tomcat.core.RequestImpl.java:

    public Principal getUserPrincipal() {
         if( getRemoteUser() == null ) return null;
         if( principal == null ) {
             principal=new SimplePrincipal( getRemoteUser() );
         }
         return principal;
    }

Notice the call to SimplePrincipal - this creates a new SimplePrincpal object (i.e. a java.security.principal) using the
name associated with the remote User call.

I found two problems with this approach -

1. The username used was not that of the current user - it was of the previously authorized user - subsequent users after the first one to be authorized
    didn't get changed  the reason for this is that the only time we refresh the principal with a new user, is if the principal was null, but, in this case, it wasn't
    the principal still held the previous user's principal..

2. If you were using a custom Realm for authorization (e.g. LDAPRealm), then this 'new' principal wouldn't be valid for that authorization object.
   If the servlet tried to use that 'special' principal for use with some other software, it would no longer be the 'special' principal -it would be a SimplePrincipal.
 

 It blew my J2EE CTS testing out of the water in several places.

I fixed it by doing the following:
1.  in org.apache.tomcat.core.RequestImpl.java: I made the following change to getUserPrincipal:

    public Principal getUserPrincipal() {
         if( getRemoteUser() == null ) return null;
         // else return principal
         return principal;
    }

And in SimplRealm (and JDBCRealm and any other special Realm Manager) I added the following to the authenticate method:
(in bold).  My rationale for making this change was that, given it was the Realm manager's job to authenticate the user - and, only after authentication
should the userPrincipal be set, I moved the responsibility for setting the UserPrincipal to the Realm manager.

This also meant that, at any time following successful authorization, the current user principal would be correct for the user.

    public int authenticate( Request req, Response response )
    {
     // Extract the credentials
     Hashtable cred=new Hashtable();
     SecurityTools.credentials( req, cred );

     // This realm will use only username and password callbacks
     String user=(String)cred.get("username");
     String password=(String)cred.get("password");

     if( debug > 0 ) log( "Verify user=" + user + " pass=" + password );
     if( memoryRealm.checkPassword( user, password ) ) {
         if( debug > 0 ) log( "Auth ok, user=" + user );
             req.setRemoteUser( user );
            // set principal as well
            req.setUserPrincipal(new SimplePrincipal(user));
            Context ctx = req.getContext();
            if (ctx != null)
                req.setAuthType(ctx.getAuthMethod());
        }
         return 0;
    }

Anyway, that's the story behind this particular problem.

There's also a bug in support for security-role-links but that's another story ;-)

-Thom
 

Marc Palmer wrote:

Hi,

I'm a relative tomcat newbie but have discovered what looks to me like a
bug in the simple tomcat-user.xml authentication interceptor.

In a nutshell:

In tomcat-users.xml I have 2 users, in 2 different roles, let's say:

"john" has role "manager"
"jane" has role "clerk"

They auth fine, my servlet is protected using this scheme, everything is
beautiful.

However, when a (real life) user exits their browser (to clear auth
credentials) and opens a browser again on the same PC and goes to my site
and logs in as a different tomcat user, the user Principal remains the
same as the previous request, but the role changes!

Step by step:

1) User logs in as "jane". Servlet prints "user = jane, role=clerk"

2) User closes and re-opens browser window.

3) User logs in again, this time as "john". Servlet prints "user = jane,
role = manager".

So, basically getUserPrincipal is not changing, for some WEIRD reason.
Role changes ok, so auth is happening, but it's like the auth interceptor
is caching principals by IP or something.

AFAIK this is not a problem with the browser (IE5) because I have
rebooted in between logins and the problem still occurs. In addition,
keeping a second auth attempt (that shows incorrect user principal) open
in the browser and restarting tomcat and then pressing REFRESH on the
browser sends the CORRECT principal to my servlet � so it looks like the
browser is sending the right credentials.

Am I being silly, or is this a boo-boo?

Cheers

--
http://www.borland.com/newsgroups
http://www.borland.com/devsupport/disclaim.html
 

Reply via email to