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), IBM MQ, IBM MQ Appliance, Linux, macOS (Mac OS X), Programming, Unix, Windows.

2 Responses to MQ API Verbs that IBM Forgot!!