|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
Bug found in MS0B - Java / PCF |
« View previous topic :: View next topic » |
Author |
Message
|
RogerLacroix |
Posted: Thu Jul 22, 2004 1:01 pm Post subject: Bug found in MS0B - Java / PCF |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
All,
Well, it must be my lucky week because I have found a very weird bug in SupportPac MS0B. It has to do with non mqm accounts doing a PCF command to get queue attribute information via client mode connection. I believe the problem is with the SupportPac rather than WMQ.
If anyone would like to test this out (IBM Hursley!?!), here's what you need to do. First get the latest release of MS0B SupportPac and have WMQ V5.3 (any CSD level) installed.
I did the test with the queue manager on Solaris but any platform should give the same results. Now create a group and user account.
i.e.
Code: |
groupadd mygrp
useradd -d /export/home/fredf -m -g mygrp -s /bin/sh -c "Fred Flinstone" fredf |
If you want to, create a new create queue manager or use an existing queue manager (same box that you created the goup & user accounts on) and then do the following commands (I'll use TESTQM as the queue manager):
Code: |
setmqaut -m TESTQM -t qmgr -g mygrp +dsp +allmqi
setmqaut -m TESTQM -t q -n SYSTEM.** -g mygrp +dsp +allmqi |
Now do the following 2 MQSC via runmqsc for TESTQM queue manager:
Code: |
define channel(TESTQM_SVR.CH01) chltype(SVRCONN) trptype(TCP) MCAUSER('fredf')
REFRESH SECURITY |
Yes, I put the 'fredf' UserID in the MCAUSER on purpose.
Now from your PC or any box, but in client mode, run some of the MS0B examples.
i.e
PCFMessageListQueueNames works as expected:
Code: |
java PCFMessageListQueueNames 1.2.3.4 1414 TESTQM_SVR.CH01 |
PCFMessageListQueueDepth throws an exception at the 'agent.send()' method but it IS supposed to work basic on the setmqaut commands:
Code: |
java PCFMessageListQueueDepth 1.2.3.4 1414 TESTQM_SVR.CH01 |
After a LOT of testing I finally discovered something VERY interesting. Run the attached PCFMessageListQueueDepth2.
Code: |
java PCFMessageListQueueDepth2 1.2.3.4 1414 TESTQM_SVR.CH01 |
Either I found a security hole or I found a work-around for the bug (I believe it is the latter). I created a 'dummy' PCFAgent and connected it to queue manager BEFORE the real PCFAgent call. Now the code works fine. The only other thing I added is a CompCode check in the loop to make sure it is 0.
Now here is why I think it is a bug in MS0B rather than anything else (i.e. security hole).
It appears that IBM decided that absolutely nobody can have any access to the 'SYSTEM.AUTH.DATA.QUEUE' queue except for mqm. This is where the problem lies with MS0B.
For PCFMessageListQueueDepth, the exception is thrown on the 'agent.send()' with CompCode of 2 & ReasonCode of 2035. The agend.send() method is supposed to return a group of MQCFH structures. Each with its own CompCode & ReasonCode. But MS0B throws an exception for the entire group (CompCode of 2 & ReasonCode of 2035 plus lots of other items.).
For PCFMessageListQueueDepth2, I don't know 'what' is getting correctly set in MS0B with the 'dummy agent' but it is returning a correct set of MQCFH structures where all but one have a CompCode of 0 & ReasonCode of 0. The MQCFH structure for 'SYSTEM.AUTH.DATA.QUEUE' does have CompCode of 2 & ReasonCode of 2035.
Can someone from IBM Hursley have a look at this problem and comment? (Primary tests were conducted from Windows 2000 to a Solaris 8 box).
Regards,
Roger Lacroix
Capitalware Inc.
Code: |
import java.io.*;
import com.ibm.mq.*;
import com.ibm.mq.pcf.*;
/**
* PCF example class showing use of PCFMessageAgent and
* PCFMessage to generate and parse a PCF query.
*
* @author Chris Markes
*/
public class PCFMessageListQueueDepth2
{
final public static String copyright
= "Copyright (c) IBM Corp. 1998, 2000 All rights reserved.";
public static void main (String [] args)
{
try
{
PCFMessageAgent agent;
PCFMessageAgent agentDummy;
PCFMessage request;
PCFMessage [] responses;
// Connect a PCFAgent to the specified queue manager
if (args.length == 1)
{
System.out.print ("Connecting to local queue manager " +
args [0] + "... ");
agentDummy = new PCFMessageAgent (args [0]);
agent = new PCFMessageAgent (args [0]);
}
else
{
System.out.print ("Connecting to queue manager at " +
args [0] + ":" + args [1] + " over channel " + args [2] + "... ");
agentDummy = new PCFMessageAgent (args [0], Integer.parseInt (args [1]), args [2]);
agent = new PCFMessageAgent (args [0], Integer.parseInt (args [1]), args [2]);
}
System.out.println ("Connected.");
// Build the request
request = new PCFMessage (CMQCFC.MQCMD_INQUIRE_Q);
request.addParameter (CMQC.MQCA_Q_NAME, "*");
request.addParameter (CMQC.MQIA_Q_TYPE, CMQC.MQQT_LOCAL);
request.addParameter (CMQCFC.MQIACF_Q_ATTRS,
new int [] { CMQC.MQCA_Q_NAME, CMQC.MQIA_CURRENT_Q_DEPTH });
// Use the agent to send the request
System.out.print ("Sending PCF request... ");
responses = agent.send (request);
System.out.println ("Received reply.");
// Display the results
for (int i = 0; i < responses.length; i++)
{
if (responses [i].getCompCode() == MQException.MQCC_OK)
{
String name = responses [i].getStringParameterValue (CMQC.MQCA_Q_NAME);
int depth = responses [i].getIntParameterValue (CMQC.MQIA_CURRENT_Q_DEPTH);
System.out.println ("Queue " + name + " curdepth " + depth);
}
}
// Disconnect
System.out.print ("Disconnecting... ");
agent.disconnect ();
agentDummy.disconnect ();
System.out.println ("Done.");
}
catch (ArrayIndexOutOfBoundsException abe)
{
System.out.println ("Usage: \n" +
"\tjava PCFMessageListQueueDepth queue-manager\n" +
"\tjava PCFMessageListQueueDepth host port channel");
}
catch (NumberFormatException nfe)
{
System.out.println ("Invalid port: " + args [1]);
System.out.println ("Usage: \n" +
"\tjava PCFMessageListQueueDepth queue-manager\n" +
"\tjava PCFMessageListQueueDepth host port channel");
}
catch (PCFException pcfe)
{
System.err.println ("Error in response: ");
PCFMessage [] responses = (PCFMessage []) pcfe.exceptionSource;
for (int i = 0; i < responses.length; i++)
{
System.out.println (responses [i]);
}
}
catch (MQException mqe)
{
System.err.println (mqe);
}
catch (IOException ioe)
{
System.err.println (ioe);
}
}
} |
_________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
RogerLacroix |
Posted: Fri Jul 23, 2004 9:28 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Here's the reply I received from Chris Markes of IBM:
Thanks very much for your post and careful explanation. I'm sorry to hear you've run into a problem, and at the moment a bit mystified about how connecting a dummy agent should make any difference to anything -- but there are a couple of things I can suggest right away.
First, there are two things you can do if you want to see exactly what PCFMessages the agent is receiving, under the conditions where you get an exception:
- You can retrieve the array of PCFMessages received from the exceptionSource field of the PCFException; it contains all the responses received.
- Alternatively, you can use the variant of the PCFMessageAgent.send() method with the check flag:
public PCFMessage [] send (PCFMessage request, boolean check)
and set the check flag to false. This means the agent won't look at the completion and reason codes in the responses; it will just return them all to you directly without ever throwing a PCFException.
Now, the interesting thing is where you say you get a non-zero reason code in the middle of the set of list queue depth responses. That's not something I've seen before. The agent only checks the first response message when evaluating whether or not the command succeeded (the PCFException is thrown based upon the content of the first response). But, if you have different authorities set on different queues, it seems plausible that some individual items might succeed while others fail.
It would be interesting to compare the list of responses you get in the PCFMessageListQueueDepth and PCFMessageListQueueDepth2 cases. One explanation could be that connecting the dummy agent affects the order in which individual queue records are returned, such that a response with a reason code of zero appears first when you connect the dummy agent. If you're able to extract the two sets of responses from running the code on your system, that would be very useful.
If this turns out to be the case, then I may need to consider something like checking through all the responses looking for MQRCCF_FAILED (which indicates an error summary response) in order to determine whether or not to throw the exception.
Chris Markes
IBM Hursley |
|
Back to top |
|
 |
RogerLacroix |
Posted: Fri Jul 23, 2004 9:41 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
And here was my reply to him:
All,
Well, I feel like Elmer Fud. 'Where's the wabbits?'
Just to make sure things were clean; I deleted the queue manager and started over - following my instructions. I did not create any MQ objects or put any messages to any queues - other than doing the 2 MQSC as per my description.
I started the queue manager as follows:
Code: |
strmqm TESTQM
strmqcsv TESTQM
nohup /opt/mqm/bin/runmqchi -m TESTQM &
nohup /opt/mqm/bin/runmqlsr -t tcp -p 1414 -m TESTQM & |
When I started my tests I actually tripped over what is causing the bug. Ooooooo, it's so cool but first the foreplay.
So, here are my tests - see attachments for full details. Nothing is connected to the queue manager.
Test #1:
Ran PCFMessageListQueueDepth as per instructions.
See results: http://www.capitalware.biz/logs/T1_LQD_MQExpl_not_connected.txt
Connected to TESTQM with MQ Explorer reran the test:
See results: http://www.capitalware.biz/logs/T1_LQD_MQExpl_connected.txt
Hummmm!! How unusual!! Skipped doing PCFMessageListQueueDepth2 because it works.
Test #2:
Added the following lines of code to PCFMessageListQueueDepth just after agent.send():
Code: |
for (int i = 0; i < responses.length; i++)
{
System.out.println ("responses[" + i +"] received" );
System.out.println (responses[i] );
} |
Closed MQ Explorer and ran PCFMessageListQueueDepth as per instructions.
See results: http://www.capitalware.biz/logs/T2_LQD_MQExpl_not_connected.txt
Connected to TESTQM with MQ Explorer reran the test:
See results: http://www.capitalware.biz/logs/T2_LQD_MQExpl_connected.txt
Aaaaaaaaaaaaaaaaaaaaaaaah HA!!!!
Added the following lines of code to PCFMessageListQueueDepth2 just after agent.send():
Closed MQ Explorer and ran PCFMessageListQueueDepth2 as per instructions.
See results: http://www.capitalware.biz/logs/T3_LQD2_MQExpl_not_connected.txt
Connected to TESTQM with MQ Explorer reran the test:
See results: http://www.capitalware.biz/logs/T3_LQD2_MQExpl_connected.txt
Test #3 worked as expected.
Now to the juicy part. You remember your statement:
The agent only checks the first response message when evaluating whether or not the command succeeded (the PCFException is thrown based upon the content of the first response).
You baaaaaaaaaad boy.
Your code is making a terrible assumption that the entire group of MQCFH structures is invalid. The very first MQCFH structure is returning CompCode of 2 & ReasonCode of 2035 but the rest are valid (actually another structure has 2035 too).
As I was scratching my head thinking about the above tests and it occurred to me what was happening. When I connected with MQ Explorer with my normal UserID, an AMQ**** queue was being created. When I started PCFMessageListQueueDepth, it was running under 'fredf' UserID (because of the MCAUSER field) and it does NOT have authority to list the attributes of that particular AMQ.*** queue. Hence the 2035 AND hence the first queue in the returned group of MQCFH structures.
Personally, I do not think checking the first MQCFH structure in the group of MQCFH structures and throwing an exception is a good idea.
On the bright-side, forcing MS0B not to check via the 'check flag' of send() method does work. So, I don't need my 'dummy agent'.
I think this is a terrible default value for the check flag. Actually, I really don't see the point of it. If you were scanning all MQCFH structures in the group of MQCFH structures and throwing the highest exception I 'might' agree but just checking the first one and throwing an exception, I do NOT agree with.
I strongly recommend fixing this or dropping the 'check only first MQCFH structure' function all together. I definitely think it is a bug.
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
RogerLacroix |
Posted: Mon Jul 26, 2004 12:52 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Here's the reply I received from Chris Markes of IBM:
Roger,
Well, congratulations, and thank you... It looks like you have
discovered a bug in the PCFMessageAgent class, and the good news is that
it's one that's easily fixed. You're right to observe that a PCF
command operating on a wildcard object name can potentially result in a
mixture of success and failure responses, and that means that it's
incorrect to take the first response as an indication of success or
failure.
> Your code is making a terrible assumption that the entire group of
> MQCFH structures is invalid.
Yes, it is. Mea culpa. It wasn't a shortcut; the intention is
absolutely that the agent should 'do the right thing', so your
application doesn't have to worry about that level of detail. I'll be
happy to produce an update that avoids this assumption.
Chris Markes
IBM Hursley |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|