MQ API Verbs that IBM Forgot!!

Every couple of months, I get an email from someone asking me if they can use MQAUSX client-side security exit with IBM MQ V8 or V9 to perform authentication via CONNAUTH. The answer is no – the MQAUSX client-side security exit only works with the MQAUSX server-side security exit.

IBM added the MQCSP (Connection Security Parameters) structure in MQ V6, so that applications could send a UserId and Password (in plain text) to a remote queue manager. At that time, the queue manager would not do anything with the UserId and Password except pass it to a channel security exit (i.e. MQAUSX), if one was in use.

In MQ V7, MQ had an explosion of new MQ API verbs. MQ V6 had 13 verbs and MQ v7.0 introduced 12 new API verbs (basically, the verb count doubled). Why IBM did not enhance or add new MQCONN/MQCONNX verbs to include a UserId and Password for MQ V7, V7.1 or V7.5 is debatable. But when IBM introduced CONNAUTH in MQ V8, IBM absolutely should have made the developers life easier by introducing new MQCONN/MQCONNX verbs.

Since, IBM is not interested or unwilling to introduce 2 new MQ API verbs, I will.

Here are the standard MQCONN and MQCONNX verbs:

MQCONN(QMgrName, &Hconn, &CompCode, &Reason);

MQCONNX(QMgrName, &ConnectOpts, &Hconn, &CompCode, &Reason);

Today, I will introduce 2 new MQ verbs: MQCONNU and MQCONNUX for MQ applications written in C.

MQCONNU(UserId, Password, QMgrName, &Hconn, &CompCode, &Reason);

MQCONNUX(UserId, Password, QMgrName, &ConnectOpts, &Hconn, &CompCode, &Reason);

I have created a C source file called ‘mqconnu.c’ that has the prototypes and code to handle the new MQ verbs. All the developer needs to do is include the ‘mqconnu.c’ in their MQ C applications then they can use the new MQ verbs.

I have created 2 MQ tester programs to demonstrate the 2 new MQ verbs called: ‘test_mqconnu.c’ and ‘test_mqconnux.c’. You can download a zip file that contains the 3 files from here.

So, lets have a look at the ‘test_mqconnu.c’ program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h>

#include "mqconnu.c" /* prototypes and code for MQCONNU and MQCONNUX */

int main(int argc, char **argv)
{
   MQHCONN  Hcon;                   /* connection handle  */
   MQLONG   CompCode;               /* completion code    */
   MQLONG   Reason;                 /* reason code        */
   char     QMgrName[MQ_Q_MGR_NAME_LENGTH+1];
   char     userId[64];
   char     passwd[64];

   if (argc != 4)
   {
      printf("test_mqconnu QMgrName userid password\n");
      return(1);
   }

   printf("test_mqconnu start\n");

   strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH);
   strncpy(userId, argv[2], sizeof(userId));
   strncpy(passwd, argv[3], sizeof(passwd));

   printf("Using values:\n");
   printf("   QMgrName   : %s\n", QMgrName);
   printf("   UserID     : %s\n", userId);
   printf("   Password   : %s\n", passwd);

   MQCONNU(userId,                  /* UserId             */
           passwd,                  /* Password           */
           QMgrName,                /* queue manager      */
           &Hcon,                   /* connection handle  */
           &CompCode,               /* completion code    */
           &Reason);                /* reason code        */

   printf("MQCONNU CC=%d RC=%d\n", CompCode, Reason);

   if (CompCode == MQCC_OK)
   {
      MQDISC(&Hcon,                 /* connection handle  */
             &CompCode,             /* completion code    */
             &Reason);              /* reason code        */

      printf("MQDISC  CC=%d RC=%d\n", CompCode, Reason);
   }

   printf("test_mqconnu end\n");
   return(0);
}

As you can see, MQCONNU is a direct replacement for MQCONN with the added benefit of passing the UserId and Password to MQ.

Now lets have a look at the ‘test_mqconnux.c’ program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h>
#include <cmqxc.h>

#include "mqconnu.c" /* prototypes and code for MQCONNU and MQCONNUX */

int main(int argc, char **argv)
{
   MQHCONN  Hcon;                    /* connection handle   */
   MQLONG   CompCode;                /* completion code     */
   MQLONG   Reason;                  /* reason code         */
   MQCNO    cno = {MQCNO_DEFAULT};   /* MQCONNX options     */
   MQCD     cd  = {MQCD_CLIENT_CONN_DEFAULT};
   char     QMgrName[MQ_Q_MGR_NAME_LENGTH+1];
   char     userId[64];
   char     passwd[64];

   if (argc != 6)
   {
      printf("test_mqconnux QMgrName ChlName hostname(port) userid password\n");
      return(1);
   }

   printf("test_mqconnux start\n");

   strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH);
   strncpy(cd.ChannelName, argv[2], MQ_CHANNEL_NAME_LENGTH);
   strncpy(cd.ConnectionName, argv[3], MQ_CONN_NAME_LENGTH);
   strncpy(userId, argv[4], sizeof(userId));
   strncpy(passwd, argv[5], sizeof(passwd));

   printf("Using values:\n");
   printf("   QMgrName   : %s\n", QMgrName);
   printf("   ChannelName: %s\n", cd.ChannelName);
   printf("   hostname   : %s\n", cd.ConnectionName);
   printf("   UserID     : %s\n", userId);
   printf("   Password   : %s\n", passwd);

   /* Point the MQCNO to the client connection definition */
   cno.ClientConnPtr = &cd;
   cno.Version = MQCNO_VERSION_5;

   MQCONNUX(userId,                  /* UserId                 */
            passwd,                  /* Password               */
            QMgrName,                /* queue manager          */
            &cno,                    /* options for connection */
            &Hcon,                   /* connection handle      */
            &CompCode,               /* completion code        */
            &Reason);                /* reason code            */

   printf("MQCONNUX CC=%d RC=%d\n", CompCode, Reason);

   if (CompCode == MQCC_OK)
   {
      MQDISC(&Hcon,                  /* connection handle      */
             &CompCode,              /* completion code        */
             &Reason);               /* reason code            */

      printf("MQDISC   CC=%d RC=%d\n", CompCode, Reason);
   }

   printf("test_mqconnux end\n");
   return(0);
}

As you can see, MQCONNUX is a direct replacement for MQCONNX with the added benefit of passing the UserId and Password to MQ.

The new MQCONNU and MQCONNUX verbs can be used in any C MQ application that wants to pass a UserId and Password to MQ for authentication. The 2 new verbs can be used in MQ applications on any platform where the MQ client code-base supports MQCSP structure.

As mentioned above, you can download a zip file that contains the 3 files from here.

Regards,
Roger Lacroix
Capitalware Inc.

This entry was posted in C, IBM i (OS/400), Linux, Mac OS X, MQ, Programming, Unix, Windows.

2 Responses to MQ API Verbs that IBM Forgot!!

  1. Given that MQCONNX was invented because there was no options structure on MQCONN, you could avoid making the same mistake and only bother to invent MQCONNU which has the parameters your MQCONNUX has. Then if you don’t need an options structure you can just leave it as NULL. No need to have the two. If that had been considered originally by IBM there would never have been an MQCONNX.

    Also, I’m curious, you don’t say what it is you don’t like about the MQCSP method of passing the user ID and password? It would lend weight to your creation to explain the reason why the current verbs are lacking.

  2. Hi Morag,

    I have nothing against MQCSP. If you look at the mqconnu.c file, you will see that it builds the MQCSP structure for the user. You and Paul seem to have missed my point. Simplicity aka make the developers life easy.

    MQCONNU is far simpler to use than coding MQCONNX, MQCNO and MQCSP.

    No regular application developer should be using MQCONNX. They should only be using MQCONN and all connectivity configuration should go in the CCDT (Client Channel Definition Table) file.

    As I mentioned to Paul, I fully agree that developers who build MQ tools have a need for MQCONNX but regular MQ application developers have no need.

    Therefore, why not provide an MQ API verb that developer can use for security. i.e. Ability to specify UserId and Password along with the queue manager name.

    Regards,
    Roger Lacroix
    Capitalware Inc.