PQ71279: Client cannot retrieve detailed error messages from WSAS5.0 CustomRegistry

 Fixes are available

5.0.1: WebSphere Application Server Version 5.0 Fix Pack 1 (Version 5.0.1)
Cumulative Security Interim fix for V5.0
5.0.1: WebSphere Application Server Enterprise Edition Version 5.0 Fix Pack 1



APAR status
Closed as program error.

Error description
Environment: Win2K, WSAS 5.0 Base

WebSphere Security Custom Registry issue.

The customer has a customRegistry program on server side and
they want to pass the detailed error messages from
customRegistry to the client code with the loginhelper class.

Method checkPassword from customRegistry class throws
passwordCheckFailed exception with a message "password check
exception userid = null".

On the client, the request_login method of the loginHelper
class throws a LoginFailed exception is WITHOUT including the
above message.

Customer considers this critical to their business and cannot
wait till the ptf. So, they would like an efix on 5.0.

Solution suggested by customer:
******************************

Reviewed the client trace MyTraceFile.log and found the
following errors:


org.omg.CORBA.NO_PERMISSION: Caught WSSecurityContextException
in WSSecurityContext.acceptSecContext(), reason: Major Code■0
Minor
Code■0 Message■ Cannot get credential because of the following
error: password check exception userid = null  minor code:
49424300  completed: No
at
com.ibm.ISecurityLocalObjectBaseL13Impl.PrincipalAuthFailReason.
map_auth_fail_to_minor_code(PrincipalAuthFailReason.java:83)
at
com.ibm.ISecurityLocalObjectBaseL13Impl.CSIServerRI.receive_requ
est(CSIServerRI.java:1706)
at
com.ibm.rmi.pi.InterceptorManager.iterateReceiveRequest(Intercep
torManager.java:729)
at
com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDe
legate.java:571)


The stack trace, while simplified here, goes along this path
MyApplication -> LoginHelperImpl -> CommonSecurityServer ->
SecurityContextImpl

1) LoginHelperImpl
- the one thing I notice here in several places is that the code
throws exceptions like throw new LoginFailed(); Perhaps some of
those are ok, but if there is more information, like the
message text of a previous exception, that could be added in.
- in this method
public synchronized Credentials request_login_controlled(String
security_name, String realm_name, String password, byte
credential_token[], CredentialsHolder creds_holder, OpaqueHolder
auth_specific_data, boolean store_in_default_creds_list, int
authentication_target, boolean set_invocation_creds)
            throws LoginFailed

eventually, this calls CommonSecurityServer.authenticate() like
this
...
                CommonSecurityServer cSecServer =
_vault.getCommonSecurityServer(4);
                AuthenticationResult authResult = null;
                authResult = cSecServer.authenticate(r_name,
basicAuthData, false);
                if(authResult.get_auth_fail_reason() != 100)
                {
                    logMsg = "Credential is null, BasicAuth
creds did not authenticate.";
                    SecurityLogger.debugMessage(logMethod,
logMsg);
  //mike
  String blah = authResult.get_auth_fail_message();
  System.out.println ("blah4=" + blah);
  throw new LoginFailed(null, blah);
  //throw new LoginFailed();
  //mike
                }
The code within the //mike comments are there to fix this
problem.  The message text from the custom registry is caught
by the SecurityServer class and placed INTO the
AuthenticationResult.

Points of interest?
- the call for cSecServer.authenticate, in the current code,
causes 4 authentications to occur

2) CommonSecurityServer
The method for authentication that is eventually called is
    private AuthenticationResult authenticate(String realm,
BasicAuthData authenticationData, String name, byte token[],
String methodName)
In this method, there is a call to initSecurityServer

b) initSecurityServer()
This method does some code like
        if(securityServer == null)
            try
            {
                Class wrapperclass =
Class.forName("com.ibm.WebSphereSecurityImpl.SecurityServerImpl"
);
                java.lang.Object wrapperObj =
wrapperclass.newInstance();
                securityServer = (SecurityServer)wrapperObj;
                if(securityServer != null &&
SecurityLogger.debugTraceEnabled)
                {
                    logMsg = "Security Server is initialized.";
                    SecurityLogger.debugMessage(logMethod,
logMsg);
                }
            }
            catch(Exception e)
            {
                FFDCFilter.processException(e,
"com.ibm.ISecurityUtilityImpl.CommonSecurityServer.initSecurityS
erver",
"102", this);
                logMsg = "security.JSAS0199E";
                SecurityLogger.logError(logMsg, new
java.lang.Object[] {
                    logMethod
                });
//mike
                mike =
((NoPermissionException)e).getRootCause().getMessage();
            }
Read point 3 about SecurityServerImpl.

What happens is that constructor completes successfully, even
though 2 authentications have failed.  So, the wrapperObj is an
actual instance, and not NULL.  No exception is thrown from the
constructor in SecurityServerImpl.  So, in this code, the
securityServer object is created, and the method returns as if
it was successful (when it hasn t been).  This method should
either throw or return something other than null.

3. SecurityServerImpl
The base constructor for this is
    public SecurityServerImpl()
        throws Exception
    {
        securityServer = null;
        getSecurityServer();
    }
which would be invoked with the newInstance() call above.

b) getSecurityServer()
This code has an initial try/catch block trying to get an
initial context.  This catch dumps some stuff out to the trace
logs, but then carries on.  It then does a lookup on
SecurityServer, which will also authenticate and fail.  The
first catch should do a throw, rather than continuing on to the
second attempt.

In the current code, if the SecuritySeverImpl constructor calls
getSecurityServer, which does 2 authentications.  This method
just returns normally, even though it has not successfully
connected to the mid-tier.  The class that attempts to make
this one gets back an object, rather than a null or an
exception.

c) simple_authenticate
    public boolean simple_authenticate(BasicAuthData
basicauthdata)
        throws AuthenticationFailedException,
AuthenticationNotSupportedException
This method will check if the securityserver is set up (checking
for null).  Since it didn t work in the constructor, the code
calls getSecurityServer() again.  This will cause two more
authentication failures.

In the code I'd sent, in each of those classes I added some code
commented with //mike.  In there, I throw an exception from
getSecurityServer().  This contains the message text of the
exception thrown from the customregistry on the server side.
This will cause the SecurityServerImpl to not be constructed.
In the CommonSecurityServer class, it will now catch this
exception, and I placed the message text into a member variable
(too lazy to change that method (initSecurityServer) to throw).
In this case now, the securityServer variable is now NULL,
Local fix
where with ut the fix, it was NOT NULL.

Then, basically, for the code that calls initSecurityServer, it
checks for securityServer being null.  If it is, it can take the
message we stored above, and include it in the
AuthenticationResult.

Then, way back in LoginHelperImpl, when it gets the
AuthenticationResult, it can get this message and throw a new
LoginFailed with that message text in it.
LOCAL FIX:ン
None
Problem summary
****************************************************************
* USERS AFFECTED: All WebSphere Application Server users       *
*                 throwing exceptions from Custom User         *
*                 Registries.                                  *
****************************************************************
* PROBLEM DESCRIPTION: Exception text is not available to the  *
*                      client.                                 *
****************************************************************
* RECOMMENDATION:                                              *
****************************************************************
The text used to instantiate an exception thrown by a Custom
User Registry is not available to the client.
Problem conclusion
The exception text is now available in the
org.omg.SecurityLevel2.LoginFailed exception caught by the
client.  This was resolved in internal defect 155026.
Temporary fix
WAS_Security_02-24-2003_5.0.0_cumulative_fix.jar
Comments
APAR information
APAR number PQ71279
Reported component name WAS BASE 5.0
Reported component ID 5630A3600
Reported release 00W
Status CLOSED PER
PE NoPE
HIPER NoHIPER
Special Attention NoSpecatt
Submitted date 2003-02-23
Closed date 2003-03-13
Last modified date 2003-03-13

APAR is sysrouted FROM one or more of the following:

APAR is sysrouted TO one or more of the following:

Modules/Macros
Security          

Publications Referenced

Fix information

Applicable component levels
R003 PSY    UP
R00A PSY    UP
R00H PSY    UP
R00I PSY    UP
R00S PSY    UP
R00W PSY    UP


Document Information


Product categories: Software > Application Servers > Distributed Application & Web Servers > WebSphere Application Server > General
Operating system(s):
Software version: 00W
Software edition:
Reference #: PQ71279
IBM Group: Software Group
Modified date: Mar 13, 2003