2
votes

Can you please help me, I am trying to find the ibm mq depth with PCFAgent over SSL channel.

Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
     Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");
     System.setProperty("javax.net.ssl.trustStore","abc-dev.jks");
     System.setProperty("javax.net.ssl.trustStorePassword","abcdabcd");

     System.setProperty("javax.net.ssl.keyStore", "abc-dev.jks");
     System.setProperty("javax.net.ssl.keyStorePassword", "abcdabcd");

     MQEnvironment.sslCipherSuite = "TLS_RSA_WITH_AES_128_CBC_SHA";



    int attrs[] = { 2016, 3 };
    System.out.println("parameter creation");
    PCFParameter parameters[] = { new MQCFST(2016, "*"), new MQCFIN(20, 1),
            new MQCFIL(1002, attrs) };
    String name = null;
    Integer depth = null;
    System.out.println("parameter creation end");



    try {
        PCFAgent agent;
        if (args.length == 1) {
            System.out.print("Connecting to local queue manager " + args[0]
                    + "... ");
            agent = new PCFAgent(args[0]);
        } else {
            System.out.print("Connecting to queue manager at " + args[0]
                    + ":" + args[1] + " over channel " + args[2] + "... ");
            agent = new PCFAgent(args[0], Integer.parseInt(args[1]),
                    args[2]);
        }
        System.out.println("Connected.");
        System.out.print("Sending PCF request... ");
        com.ibm.mq.MQMessage responses[] = agent.send(13, parameters);
        System.out.println("Received reply.");
        for (int i = 0; i < responses.length; i++) {
            MQCFH cfh = new MQCFH(responses[i]);
            if (cfh.reason == 0) {
                for (int j = 0; j < cfh.parameterCount; j++) {
                    PCFParameter p = PCFParameter
                            .nextParameter(responses[i]);
                    switch (p.getParameter()) {
                    case 2016:
                        name = (String) p.getValue();
                        break;

                    case 3: // '\003'
                        depth = (Integer) p.getValue();
                        break;
                    }
                }

                System.out.println("Queue " + name + " curdepth " + depth);
            } else {
                System.out.println("PCF error:\n" + cfh);
                for (int j = 0; j < cfh.parameterCount; j++)
                    System.out.println(PCFParameter
                            .nextParameter(responses[0]));

            }
        }

        System.out.print("Disconnecting... ");
        agent.disconnect();
        System.out.println("Done.");
    } catch (ArrayIndexOutOfBoundsException abe) {
        System.out
                .println("Usage: \n\tjava ListQueueDepth queue-manager\n\tjava ListQueueDepth host port channel");
    } catch (NumberFormatException nfe) {
        System.out.println("Invalid port: " + args[1]);
        System.out
                .println("Usage: \n\tjava ListQueueDepth queue-manager\n\tjava ListQueueDepth host port channel");
    } catch (MQException mqe) {
        System.err.println(mqe);
    } catch (IOException ioe) {
        System.err.println(ioe);
    }

When I try run this program remotely, I am getting the following exception:

com.ibm.mq.MQException: MQJE001: Completion Code 2, Reason 2035

EDIT to add additional clarifying details from the comments:

The MQ Admin found an error in the AMQERR01.LOG related to the SYSTEM.DEFAULT.MODEL.QUEUE at the same time the application receives the 2035.

The same program works for a non-SSL channel when I take off the security settings and ciphersuite.

2

2 Answers

2
votes

Well, I don't see where you set a UserID in the code. Therefore, you are sending a blank UserID which if the channel's MCAUSER is blank means, it becomes 'mqm' UserID because of an old security hole.

For MQ v7.1 or higher, the default CHLAUTH rule will block the connection if you are on a 'SYSTEM' channel. Or for MQ v8.0 or higher, the channel may require a UserID and Password. You need to look at either the event queue or queue manager logs for the reason for the RC of 2035 (not authorized).

int attrs[] = { 2016, 3 };
PCFParameter parameters[] = { new MQCFST(2016, "*"),
                              new MQCFIN(20, 1),
                              new MQCFIL(1002, attrs) };

Also, what is with the hard-coded values? Did you decompile someone else's program?

Why aren't you using the IBM MQ supplied defines? Here's what it should look like:

int[] attrs = {
                CMQC.MQCA_Q_NAME,
                CMQC.MQIA_CURRENT_Q_DEPTH
              };
PCFParameter[] parameters = {
                               new MQCFST (CMQC.MQCA_Q_NAME, "*"),
                               new MQCFIN (CMQC.MQIA_Q_TYPE, CMQC.MQQT_LOCAL),
                               new MQCFIL (CMQCFC.MQIACF_Q_ATTRS, attrs)
                            };
1
votes

The PCFAgent class creates a dynamic queue for the response messages from the command server. By default the model queue used is SYSTEM.DEFAULT.MODEL.QUEUE. The user needs to have OAM permission +get +dsp on the model queue.

If the program works when connecting to a non-SSL channel then the connection must be resolving to a different userid that has the required OAM permission against the SYSTEM.DEFAULT.MODEL.QUEUE.

The error in the queue manager's AMQERR01.LOG would show the userid that is missing the permission(s) along with the the specific permission(s) missing.

Depending on what version of MQ client jar files you are using, if you do not specify a UserID the MQ client will either send blank UserID or the UserID the java process is running under. On the queue manager side if the MCAUSER attribute of the channel is blank, then it would inherit either mqm if a blank UserID was received or the UserID your process is running under. If the MCAUSER attribute of the channel is not blank that is the UserID that will be used for permission.