JMS - Java Message Service



Authenticating of J2EE client
against IBM Websphere MQ version 5.2.1 / 5.3 / 6.0 (formerly MQseries)

With everything running on the same physical machine - MQ and the client - the problem of authentication will mostly not need addressing. But when interfacing to MQ between different machines, you will need to deal with authentification - regardless if you run non-transactional - or transactional..

Dealing with security really brings in issues: Authenticating the user... is a problem because the MQ client always tells the server about which user credential is running at the client. The classes in com.ibm.mqjms.jar are reading the JVM environment property "user.name". Fx. the class com.ibm.mq.server.MQSESSION retrieves the credientials (user name) for the user currently running the MQ services (client) and in a similar way the server will retrieve the credientials running the server process. It comes clear if you unpack the MQ J2EE drivers from the jar-files and search for "user.name". Even without and disassembly you'll find quite a number of times, where the drivers deals with the environment variable.

If the credentials on the client and server are the same - or if the client credientials has been defined with suddfient rights on the server, there will be no problems. Otherwise you have to address the issue in following ways: Oddly enough, the client and server only exchanges and evaluate user name - not password - furthermore the MQ client does not require opening SSL ports, which leads me to suspect the credentials are exchanged in clear text format... so much for security... Thus the value of the security check cannot really be of any significant protection value. If the server is running as a standard Windows service, it will usually be running under user name "system" - which will be more than sufficient to use at the client to get access.

On the server, you can set and display access rights with:

setmqaut syntax

>>-setmqaut--- -m QMgrName--- -n ObjectName--- -t ObjectType---->
 
                                 .--------------------------.
                                 V                          |
>-----+----------------------+-------+- -p PrincipalName-+--+--->
      '- -s ServiceComponent-'       '- -g GroupName-----'
 
      .------------------------------------------.
      V                                          |
>---------+-| MQI authorizations |------------+--+-------------><
          +-| Context authorizations |--------+
          +-| Administration authorizations |-+
          '-| Generic authorizations |--------'
 
MQI authorizations
 
    .-----------------------.
    V                       |
|---------+- +get -----+----+-----------------------------------|
          +- -get -----+
          +- +browse --+
          +- -browse --+
          +- +put -----+
          +- -put -----+
          +- +inq -----+
          +- -inq -----+
          +- +set -----+
          +- -set -----+
          +- +connect -+
          +- -connect -+
          +- +altusr --+
          '- -altusr --'
 
Context authorizations
 
    .-----------------------.
    V                       |
|---------+- +passid --+----+-----------------------------------|
          +- -passid --+
          +- +passall -+
          +- -passall -+
          +- +setid ---+
          +- -setid ---+
          +- +setall --+
          '- -setall --'
 
 
Administration authorizations
 
   .-------------------.
   V                   |
|--------+- +crt -+----+----------------------------------------|
         +- -crt -+
         +- +dlt -+
         +- -dlt -+
         +- +chg -+
         +- -chg -+
         +- +dsp -+
         +- -dsp -+
         +- +clr -+
         '- -clr -'
 
Generic authorizations
 
    .----------------------.
    V                      |
|---------+- +allmqi -+----+------------------------------------|
          +- -allmqi -+
          +- +alladm -+
          +- -alladm -+
          +- +all ----+
          '- -all ----'
 
setmqaut example
setmqaut -m "topsecurity.queue.manager.name" -t queue -n topsecurity.queue.name -g topsecuritygroup +all
should give all rights to the queue "topsecurity.queue.name" defined with queuemanager "topsecurity.queue.manager.name" where topsecuritygroup is the ID of the group to be given the authorizations.

Returning to out example from the past... remembering(?) the shaded area in the client code from the MQ/WLS integration document.. This would normally take care of the authentication part.


From J2EE stand-alone client to MQ
TopsecurityMQClient.java

package dk.topsecurity;

import javax.jms.*;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.*;

public class TopsecurityMQClient implements ExceptionListener {

/** 
 * Setting up authorisation username. Used by classes in com.ibm.mqjms.jar
 * Setting up queue connection factory (QCF)
 * Setting up name of queue, as defined in the MQ setup
 * Setting up url for file-based, external JNDI provider 
 * Setting up context factory to use with external JNDI
 */

  public String mq_username = "Administrator";
  public String mq_qcf = "TOPSECURITY_QCF";
  public String mq_qname = "TOPSECURITY.QUEUE";
  public String mq_url = "file:/C:/jms-jndi-directory";
  public String mq_jndi =  "com.sun.jndi.fscontext.RefFSContextFactory";

...

  private void setupQueueConnection() throws Exception {

    /* authentication related part - completely remove when running MQ and
     * J2EE client on same machine under same user - or different machines
     * and identical user names. Otherwise enter the username used for the
     * MQ installation. Failure to do so, will cause the program to exit with
     * authentication exception.
     */
    System.out.println("Initial user.name="+System.getProperty("user.name"));
    System.setProperty("user.name",mq_username);
    System.out.println("Authrorisation required user.name="+System.getProperty("user.name"));
    /*end of authentication related part*/

    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, mq_jndi);
    env.put(Context.PROVIDER_URL, mq_url);

    InitialDirContext ctx = new InitialDirContext(env);
    com.ibm.mq.jms.MQQueueConnectionFactory factory =
            (com.ibm.mq.jms.MQQueueConnectionFactory)ctx.lookup(mq_qcf);

    System.out.println("Factory = " +factory);

    /* Create a QueueConnection, QueueSession
     * When a connection is made, use the createQueueSession method on the
     * QueueConnection to obtain a session. Parameters: 
     * boolean= determines whether the session is transacted or non-transacted.
     * int =  that determines the acknowledge mode.
     * Simplest case is that of the non-transacted session with AUTO_ACKNOWLEDGE
     * - p319 in the IBM redbook.
     */
    connection = factory.createQueueConnection();
    session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    ioQueue = (Queue)ctx.lookup(mq_qname);

    connection.start();
    connection.setExceptionListener(this);

    queueSender = session.createSender(ioQueue);
  }


...

}



Deleting the shaded area - and running the sample under a different user (maybe on another machine) presents the common error:

MQJMS2013 invalid security authentication supplied for MQQueueManager

MQ client console authentication error

SUMMARIZING: authentication is a consequence of the MQ drivers exchanging and comparing contents of the "user.name" environment variable on different machines. You need to deal with it when running on different machines, and there is quite a number of questions on this part in various newsgroups...

SOLUTION: deal with it by setting the "user.name" environment variable - or increasing user access rights on the server for the client user.

Returning to the second problem:

requires definition of a securitusage and a policy file...

MQSecurity.policy

grant codebase "file:*" {
   permission java.io.FilePermission "c:/jms-jndi-directory", "read";
   permission java.io.FilePermission "c:/jms-jndi-directory/.bindings", "read";
   permission java.io.FilePermission "c:/jms-jndi-directory/TOPSECURITY_QCF", "read";
   permission java.io.FilePermission "c:/jms-jndi-directory/TOPSECURITY.QUEUE", "read";
};
grant codebase "file:TopsecurityMQ_client.jar" {
   permission java.util.PropertyPermission "user.name", "read";
   permission java.util.PropertyPermission "user.name", "write";
};
grant codeBase "file:com.ibm.mq.jar" {
permission java.net.SocketPermission "*","connect";
permission java.lang.RuntimePermission "loadLibrary.*";
};
grant codeBase "file:com.ibm.mqjms.jar" {
permission java.util.PropertyPermission "MQJMS_LOG_DIR","read";
permission java.util.PropertyPermission "MQJMS_TRACE_LEVEL","read";
permission java.util.PropertyPermission "MQJMS_TRACE_DIR","read";
permission java.util.PropertyPermission "MQ_JAVA_INSTALL_PATH","read";
permission java.util.PropertyPermission "file.separator","read";
permission java.util.PropertyPermission "os.name","read";
permission java.util.PropertyPermission "user.name","read";
permission java.util.PropertyPermission "com.ibm.mq.jms.cleanup","read";
permission java.util.PropertyPermission "com.ibm.mq.localaddress","read";
};

Maybe access to the external JNDI provider could be restricted more - but the basic idea here is to show that different parts of the allication requires access to different ressources. The external JNDI provider is pritty fundamental here.

It is necessary to be very carefull to reference .jar files from same locations as mentioned in the policy file. Otherwise, a very common error will be: java.security.AccessControlException: access denied An example of an example with security manager and policy file could be:

sendMQsecurity.cmd

set BEA_HOME=C:\bea
set WL_HOME=C:\bea\weblogic81
java -classpath .;.\weblogic.jar;.\com.ibm.mq.jar;.\com.ibm.mqjms.jar;.\fscontext.jar;.\providerutil.jar;.\dbhcore.jar;TopsecurityMQ_client.jar      -Djava.security.manager -Djava.security.policy=MQSecurity.policy  dk/topsecurity/TopsecurityMQClient


and output could be somewhat like:

MQ client with security manager







Summary: With best hopes that this text will be of help to others... /topsecurity.dk, december 2005