I did that part programmatically:
   public AppConfigurationEntry[] getAppConfigurationEntry( String 
applicationName )
    {
        if( m_appConfig == null ) {
            if( applicationName == null ) {
                throw new NullPointerException( "Could not retrieve security 
configuration.  "
                                                + "Application name was not 
specified." );
            }

            if( m_dbkey == null ) {
                throw new NullPointerException( "The application, \"" + 
applicationName + "\", "
                                                + "does not have a security 
configuration entry "
                                                + "defined in " + 
this.getClass().getName() + "." );
            }

            String[] parms = { applicationName };
            String sql = MessageFormat.format( SECURITY_CONFIGURATION_SQL, 
parms );

            Connection dbConn = null;
            Statement stmt = null;
            ResultSet rs = null;

            ArrayList modules = new ArrayList();
            try {
                dbConn = ConnectionFactory.getConnection( m_dbkey );
                stmt = dbConn.createStatement();
                rs = stmt.executeQuery( sql );

                while( rs.next() ) {
                    String loginClass = rs.getString( "LoginModuleClass" );
                    String cFlag = rs.getString( "ControlFlag" );
                    DEBUG_MODE = rs.getBoolean( "DebugFlag" );
                    HashMap options = new HashMap();
                    options.put( "debug", String.valueOf( DEBUG_MODE ) );

                    AppConfigurationEntry.LoginModuleControlFlag controlFlag =
                                                                        
resolveControlFlag( cFlag );

                    AppConfigurationEntry appEntry = new AppConfigurationEntry( 
loginClass,
                                                                                
controlFlag,
                                                                                
options );
                    modules.add( appEntry );

                    m_appConfig = (AppConfigurationEntry[])modules.toArray(
                                                        new 
AppConfigurationEntry[modules.size()] );

                }

            } catch( SQLException e ) {
                Logger.log( Logger.ERROR, getClass() + 
".getAppConfigurationEntry", e );
                return null;
            } catch( KException e ) {
                Logger.log( Logger.ERROR, getClass() + 
".getAppConfigurationEntry", e );
                return null;
            } finally {
                SQLUtil.close( dbConn, stmt, rs );
                rs = null;
                stmt = null;
                dbConn = null;
            }
        }

        return m_appConfig;
    }

The hook into the login module is created when the context listener for the 
web-app is initialized.  The initialization parameters come from the database, 
which is what I was referring to, as opposed to a policy file.

What I find strange is that the authentication piece works perfectly.  Tomcat 
calls my login module, does it's work and build a Subject that is consistent 
with what I expect.  The question is, why am I able to call 
request.isUserInRole("landscape") when Tomcat's internal call to the roles in 
my Subject uses something else?

The Tomcat code that is failing for my auth check is 
(http://kickjava.com/src/org/apache/catalina/realm/RealmBase.java.htm):

           } else if(!denyfromall) {
787
788                 for (int j = 0; j < roles.length; j++) {
789                     if (hasRole(principal, roles[j]))
790                         status = true;
791                     if( log.isDebugEnabled() )
792                         log.debug( "No role found: " + roles[j]);
793                 }
794             }

public boolean hasRole(Principal JavaDoc principal, String JavaDoc role) {
851
852         // Should be overriten in JAASRealm - to avoid pretty inefficient 
conversions
853 if ((principal == null) || (role == null) ||
854             !(principal instanceof GenericPrincipal))
855             return (false);
856
857         GenericPrincipal gp = (GenericPrincipal) principal;
858         if (!(gp.getRealm() == this)) {
859             if(log.isDebugEnabled())
860                 log.debug("Different realm " + this + " " + 
gp.getRealm());// return (false);
861 }
862         boolean result = gp.hasRole(role);
863         if (log.isDebugEnabled()) {
864             String JavaDoc name = principal.getName();
865             if (result)
866                 log.debug(sm.getString("realmBase.hasRoleSuccess", name, 
role));
867             else
868                 log.debug(sm.getString("realmBase.hasRoleFailure", name, 
role));
869         }
870         return (result);
871
872     }

So, what works in the one case, i.e., request.isUserInRole("landscape"), fails 
when using Tomcat's role checking, i.e., hasRole(principal, roles[j]).  So, 
Tomcat isn't treating my Principal as a role, which its own messages says that 
it is:

org.apache.catalina.realm.JAASRealm  - Checking Principal "landscape" 
[com.kaleidescape.logdb.webapp.security.auth.UserGroupPrincipal]
2008-05-05 14:02:53,665 10885193 [http-9808-Processor24] DEBUG 
org.apache.catalina.realm.JAASRealm  - Adding role Principal "landscape" to 
this user Principal's roles

If my JAAS realm wasn't properly configured, I can't see how I'd get all the 
way to the JAASRealm hasRole() method.  Also, my own implementation was a check 
against Tomcat.  I called all the same code that Tomcat calls, the only 
difference is, I can access my Subject when I call my own code, whereas Tomcat 
sticks the Subject that it creates into an InternalSession, which isn't 
accessible outside of the Catalina code base.

Since my UserGroupPrincipal implements Principal, it is castable to 
GenericPrincipal.  I am not in a different realm, since the debug message about 
that isn't fired.  So it comes down to how the Catalina code base is 
interpreting gp.hasRole(role).  Haven't tracked down that code yet but I will.

At least, that's how it appears to me, but I am open to any fixes. :)
Robin.

-----Original Message-----
From: Caldarale, Charles R [mailto:[EMAIL PROTECTED]
Sent: Monday, May 05, 2008 2:12 PM
To: Tomcat Users List
Subject: RE: JAAS authenticated user fails authorization check

> From: Robin Coe [mailto:[EMAIL PROTECTED]
> Subject: RE: JAAS authenticated user fails authorization check

It appears that the problem is you haven't fully configured the JAAS
environment.  See below for details.

> I tested the implementation of isUserInRole() by wild-carding
> the role, to force Tomcat to authenticate but not authorize:

It doesn't work that way.  A <role-name> of * means that authorization
is allowed for any of the listed <security-role>s, not that
authorization is ignored.

> As a side note, I wrote my own implementation of the login
> process, using a servlet to hook into my login module, thus
> avoiding the declarative security.

Why did you choose to reinvent the wheel here?  Use the declarative
security - it's much easier.

> <Context>
>         <Realm className="org.apache.catalina.realm.JAASRealm"
>            appName="landscape"

The appName is not some arbitrary value; it needs to point to the entry
in the file pointed to by the java.security.auth.login.config system
property (see below).

> The JAAS module is not based on a security policy file, I
> wrote it to work from a database.

Not relevant to the discussion.  You still have to tell Tomcat's
JAASRealm what your LoginModule class name is via the file pointed to by
the java.security.auth.login.config system property.  For example,
here's ours:

-Djava.security.auth.login.config=conf/security/tomcatLogin.config

The conf/security/tomcatLogin.config file contains:

TomcatLogin {
  com.unisys.os2200.security.TomcatLoginModule required;
};

Have you done that?

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to