Search code examples
javaibm-mqsecuritymanager

MQQueueManager constructor hangs when a SecurityManager is installed


Host foo is an IBM MQ client (i.e. client mode connection over TCP/IP). Host bar is the system on which the queue manager is running. Bar grants permission (by IP address) for foo to instantiate a com.ibm.mq.MQQueueManager object but does not grant permission to host foobar.

Therefore, I am encapsulating all of the IBM MQ contact into a new app running on foo. Together with foobar, a client/server app is forming, using sockets, where foo is the server and foobar is the client. Foo is still the IBM MQ client, as before.

So far, all I’ve tried to do on foo in the new app (MQ-related) is to instantiate an MQQueueManager object. That’s successful, until I introduce java.lang.SecurityManager.

Local applications executed via the java command, such as this one on foo, are by default not run with a SecurityManager installed. Now it is run with a SecurityManager installed. The reason is to control access to this app running on foo. The security policy accepts connections from foobar (java.net.SocketPermission). This works. The owner of foo can now control the permission granted to foobar.

But we’re getting some interference in the interaction between foo and bar. The interference is coming from the SecurityManager. Don’t run with a SecurityManager installed and foo can instantiate MQQueueManager. Run with a SecurityManager and foo hangs in the MQQueueManager constructor.

Foo is using the Policy reference implementation described in https://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html

The following permission on foo results in the MQQueueManager constructor hanging.

permission java.net.SocketPermission "bar", "connect, accept";

-Dcom.ibm.msg.client.commonservices.trace.status=ON

-Djava.security.debug="access,failure"

... access denied ("java.util.PropertyPermission" "mqs.disable.all.intercept" "read") [java.security.AccessControlException] ...

... access denied ("java.util.PropertyPermission" "mqs.intercept.serializeconn" "read") [java.security.AccessControlException] ...

Solution

  • The IBM MQ v8 KC has a page "Running IBM MQ classes for Java applications under the Java Security Manager".

    This page states related to MQ client connections:

    //For the client transport type.
    permission java.net.SocketPermission "*","connect,resolve";
    

    The only thing I noticed is the lack of spaces in the example above compared to what you posted, also you would not need to provide accept permission, and I also noted in sun documentation that resolve is implied with connect so should not be specifically need.

    There are a lot of other settings that related to other permissions you may need so I would suggest reviewing the above page for more specifics.


    You can take a IBM MQ Classes for Java trace using the following java system property:

    -Dcom.ibm.msg.client.commonservices.trace.status=ON
    

    By default the trace will output to a file in the current directory called mqjms_%PID%.trc were %PID% is replaced by the process ID of your java process.

    If you want to specify a different file name or path you can add the following java system property:

    -Dcom.ibm.msg.client.commonservices.trace.outputName=/tmp/x/y/z/mqjms_%PID%.trc 
    

    Example command with both:

    java -Dcom.ibm.msg.client.commonservices.trace.status=ON -Dcom.ibm.msg.client.commonservices.trace.outputName=mqjms_%PID%.trc SomeJavaApp
    

    A java security manager trace could be helpful, you can turn this on by adding the following java system property:

    -Djava.security.debug="access,failure"