Using the PAM Authentication Method with ESQL/C

Authentication has been taken to a new level with pluggable authentication modules provided with IBM® Informix® Dynamic Server. This article tells you how to implement this mechanism within the ESQL/C applications using a sample ESQL/C program.

Share:

Abhishek Mathur (abhishek@us.ibm.com), Software Architect, IBM

Abhishek Mathur is a software architect responsible for driving installation and administrative tools initiatives for IBM Informix Dynamic Server. His previous role included working in the Client SDK development team in the IBM Lenexa lab, where he worked primararily on feature enhancements and code maintanance for the ESQL/C, LIBDMI, and LIBC++ components of CSDK. All these components are a collection of application programming interfaces used to develop applications for Informix Servers.



05 June 2003

Introduction

Authentication is the process of verifying a user's or application's identity when connecting to a database. It is very important that databases and servers that give privileges to users properly authenticate each user in the first place. Traditionally Informix servers and clients have only supported simple authentication mechanisms, either the use of trusted hosts or authentication based on a password file. Now your choices for authentication have been expanded with the option of using a pluggable authentication module (PAM) mechanism. Support for this new authentication mechanism is available with ESQL/C version starting with 9.53.xC2, being shipped with CSDK 2.81.xC2.

With trusted hosts, the database assumes trust based on the source of the connection request. If the machine that the request comes from is trusted, then the user is trusted. With password file-based authentication, authentication is based on the password and shadow files or interaction with Network Information System (NIS), on the machine where the database server is installed. The limitation with these existing mechanisms is that there is no way to use the enhanced authentication that the operating system may provide.

With the implementation of PAM in IBM Informix Dynamic Server, all new and old ESQL/C applications (by implementing small changes and recompiling the older applications) can now make use of this new authentication module, thereby improving the way the clients talk and authenticate with the database server. The implementation of the PAM mechanism enables the user to set an additional flag in the sqlhosts file on the server to use external authentication as desired by the user. The ESQL/C applications will need to be built around this authentication service to handle all the challenges and respond to these challenges for authentication.

Framework and supported platforms

In order to use the new PAM mechanism for authentication, the primary requirement is that you must have the latest ESQL/C version - 9.53.xC2 shipped with CSDK2.81.xC2 connecting to Informix Dynamic Server Version 9.40.UC2. If either the client or the server is older than these versions, the PAM mechanism cannot be used. I will talk about the various client-server compatibilities a little more later on in the article.

The main idea behind supporting the PAM mode of authentication is to be able to use the enhanced OS-level authentication. Since the authentication happens at the server, it is important that the IBM Informix Dynamic Server be on one of the platforms that supports PAM. At the moment, PAM support is available for AIX® 32 bit, AIX 64 bit, HP 32 bit, HP 64 bit , Solaris 32 bit, Solaris 64 bit and Linux. If the server you are connecting to is on any other operating system, then the applications will connect to the server using the traditional authentication mode.

Of course, since the authentication happens at the server end, we can have the client (ESQL/C application) on any platform. As long as there is a callback function registered and written to handle the challenges thrown by the server, the client application is not platform dependent.


Writing PAM-enabled ESQL/C applications

New users of the latest IBM Informix ESQL/C and IBM Informix Dynamic Server can quickly make use of this feature and lend more credibility to the authentication process by writing ESQL/C applications so that users will be authenticated by the server using PAM. PAM allows database and system administrators to set authentication policies for PAM-aware applications with greater flexibility and by utilizing a pluggable, modular architecture. This mode of authentication offers greater control over the authentication process.

For all applications that need to use the PAM mechanism, you will first need to write an authentication module that will "throw the challenges" and match the responses to the challenges during the authentication process. For instance, if you log into a system, it would typically ask you to enter a 'username,' and then if need be, also prompt you for a 'password'. Username and password are very simple cases of challenges that are being thrown by the system. With PAM, you can go a step further, and have your applications successfully communicate and respond to more challenges thrown by the module written for such database authentication. Typically a challenge may be a pre-fed question for every user, and you would need to answer it correctly to allow you access to the database. The nature of these challenges, will vary for every user, and will depend on the way the PAM module has been written.

For an ESQL/C application to access such PAM enabled Informix Dynamic Servers, it is essential that the application support such access, as we'll show in the example below. This is called the PAM service . For most platforms the PAM service module resides in the /usr/lib/security directory. The developer will need to write a PAM service module and place it in the /usr/lib/security directory on the machine where the IBM Informix Dynamic server resides. The IBM Informix Dynamic Server will load this library (service) and use it to authenticate the client.

The pam.conf file establishes the mappings between the services, the library and the module. A typical entry would look like this:

login auth required /usr/lib/security/pam_unix.so.1

This entry in the pam.conf file means that for the "login" service, the PAM library "/usr/lib/libpam" needs to use the pam_unix.so module.

Similarly for the IBM Informix Dynamic Server to understand that a PAM service is to be used for authenticating every connection, an entry must be made in the SQLHOSTS file of the server. A typical SQLHOSTS file for a server that is capable of handling this new authentication module will look like this:

Listing 1. Sample sqlhosts file of a PAM-enabled server
<servername><service(ontlitcp/onsoctcp)><machinename><portno>
s=4,pam_serv=<pam servicename>,pamauth=(challenge).
  • <servername>— Name of the IBM Informix Server (as present in the onconfig file)
  • <service>— What service to use: ontlitcp, onsoctcp, onipcshm, etc.
  • <machinename>— Name of the machine where the server resides
  • <portno>— Number of the port used for communication between client and server
  • pam_serv=<servicename>— Name of the PAM service module written by the user and placed in the /usr/lib/security directory of the machine where the IBM Informix Dynamic Server resides. This is the service, written and placed in /usr/lib/security that throws challenges to authorize the users.
  • pamauth=(challenge)

Once a PAM service module is written and saved in the /usr/lib/security directory, a flag (pamauth=challenge) is set in the sqlhosts file at the server to indicate to the server to use external authentication, and the server is brought up in the 'challenge' mode, we can now proceed to write ESQL/C applications that can handle the external authentication being demanded by the server. A typical PAM service module would consist of several challenges being thrown to the user, and authenticating the user on the basis of the responses to these challenges. So, we need to have an ESQL/C application that can handle these challenges and throw back the responses.

I have written a typical sample program (pamdemo.ec), which is shipped with the latest ESQL/C product. It illustrates how an ESQL/C application can be written to make use of the PAM service.

The sample demo program follows, and with it several comments included in shaded boxes explaining the program. The program illustrates how ESQL/C can be used authenticate with IBM IDS using PAM.

Listing 2. pamdemo.ec
#include <stdio.h>
      
#define PAM_PROMPT_ECHO_OFF 1 /*Echo off when getting response*/ 
      
#define PAM_PROMPT_ECHO_ON 2 /*Echo on when getting response*/ 
      
#define PAM_ERROR_MSG 3 /* Error Message */ 
      
#define PAM_TEXT_INFO 4 /* Textual Information */ 
      
#define PAM_MAX_MSG_SIZE 12 /* max size of each message */

These definitions typically reside in the /usr/include/security/pam_appl.h file on a system that supports PAM. At the moment, only AIX 32/64 bit, HP 32/64 bit, Solaris 32/64 bit and Linux support this kind of PAM authentication. It is essential that the server be installed on one of these platforms if it is to make use of PAM authentication. The client (ESQL/C application) though can reside on any platform/OS. With every message that is returned by the PAM service, a message type is also returned. For client applications residing on non-PAM systems these definitions need to be explicitly defined as shown. These return type messages are important in determining the further course of action by the applications. If the ESQL/C application resides on the system that supports PAM (AIX 32/64 bit, HP 32/64 bit, Solaris 32/64 bit and Linux) the four definitions can simply be defined by including the /usr/lib/security/pam_appl.h file as follows: #define <security/pam_appl.h>

EXEC SQL define FNAME_LEN 15; 
EXEC SQL define LNAME_LEN 15;

int callback(char *challenge, char *response, int msg_style);

For any ESQL/C applications to use PAM, it must include a callback function. This callback function must first be registered. Here we are defining this callback function. I will talk more about the callback function below.

int main()
{ 
EXEC SQL BEGIN DECLARE SECTION; 
  char fname[ FNAME_LEN + 1 ]; 
  char lname[ LNAME_LEN + 1 ];
EXEC SQL END DECLARE SECTION;

int retval = 0;

/* First register the callback. This needs 
* to be done before establishing the 
* connection as done here. 
*/

Like the comments say, the callback function needs to be registered. The main purpose of the callback function is to be able to handle all the challenges thrown by the PAM service, when the application connects to the PAM-enabled IBM IDS server. The callback function will need to be able to accept these challenges from the server, and send them to the user (maybe another application or a user interface), and bring back the responses to those challenges, and in turn pass them back to the server for authentication with the PAM service. The function needs to be registered before the first connection is made to the server. This callback function will be called by the ESQL/C library whenever the server throws the challenge based on the PAM module written for the application to respond accordingly. Even if you are connecting to several servers, some that understand the PAM modules and some that don't through a single application, you will still need to register the callback function for the servers that understand the PAM service. There should not be any problems while connecting to the non-PAM servers even if the application is registered, because in those cases the callback function will never be called.

printf("Starting PAM demo \n"); EXEC SQL
        WHENEVER ERROR STOP;

        retval = ifx_pam_callback(callback);

This is where we are registering the callback function. The name of the callback function is 'callback'. Registering the callback function is essential in order for the sqli library to be able to call this function anytime it receives a challenge from the server. The error check for the registering of the callback function follows:

if (retval == -1) { 
        printf("Error in registering callback\n"); return (-1); 
      } else { printf( "Callback function registered.\n"); 
      EXEC SQL database stores_demo; 
      printf ("SQLCODE ON CONNECT = %d\n", SQLCODE);

At this point, when the client makes the connection to the server, the sqli library will call the callback function that had been registered. The program will proceed only if the callback function has been registered correctly, and if the user is able to supply the correct responses to the challenges being thrown by the PAM service. The rest of the program is a simple demo program (the original demo1.ec shipped with previous ESQL/C) followed by the callback function callback.

EXEC SQL declare pamcursor cursor for 
        select fname, lname 
        into :fname, :lname 
        from customer 
        where lname < "C"; 
        EXEC SQL open pamcursor; for (;;) { EXEC SQL fetch pamcursor; 
        if (strncmp(SQLSTATE, "00", 2) != 0) break; 
        printf("%s %s\n",fname, lname); } if (strncmp(
        SQLSTATE, "02", 2) != 0) printf("SQLSTATE
        after fetch is %s\n", SQLSTATE); 
        EXEC SQL close pamcursor; 
        EXEC SQL free pamcursor; 
        EXEC SQL disconnect current; 
        printf("\nPAM DEMO run completed successfully\n");
         }
          }

        /* The callback function which will * provide responses
        to the challenges. */

This is the callback function that was previously registered even before the first connection is made to the PAM-enabled IBM Informix Dynamic server. This function can be written in several ways depending on how the user wants to handle the challenges being thrown by the PAM enabled server. The code below shows a very simple approach. Here the callback function takes three parameters returning an integer. Based on message type (msg_style), the function (and in turn the ESQL/C application) decides the kind of response that needs to be given to the server. For all the challenges a response is expected. If there is an error message, or simply a message that does not need a response, the message is displayed at the prompt. The challenge is thrown at the user, and the response to the challenge is expected and provided back to the user. The non-challenge responses can be one of several such as 'authentication successful,' depending on the way the PAM module (service) has been written. Once again, this callback function is called every time a new connection is made to the database server, and the server throws back a challenge demanding more information, rather than using a simple username and password mechanism for authentication.

int callback(char *challenge, char *response, int msg_style) { 
        switch (msg_style){ 
          case PAM_PROMPT_ECHO_OFF: 
          case PAM_PROMPT_ECHO_ON : 
            printf("%s: %d:",challenge, msg_style); 
            scanf("%s:",response); 
            break; 
          case PAM_ERROR_MSG: 
          case PAM_TEXT_INFO: 
          default: printf("%s: %d\n",challenge, msg_style); 
        } return 0; 
      }

The above program can be compiled and run on any operating system, and can talk to both a non-PAM server, and to a PAM server. Only when the client connects to a PAM-capable server will the callback function come into play and ask the user to type in the responses to the challenges thrown by the server it is connecting to.


Client-server compatibilities using the PAM module

The developers of the PAM authentication feature took care to avoid client-server compatibility issues. Users can move to the latest ESQL/C client (libraries), without having to worry too much about PAM, even if they are connecting to the latest IBM Informix Dynamic Server. Migrating or upgrading to the latest ESQL/C version does not mean that you will have to provide a callback function and necessarily use the PAM functionality to connect to the server. This feature is optional, and only functional if the server to which the application connects is brought up in a PAM mode.

Also, while you are writing new applications, users can continue to use the older method of authentication with the servers. Using the PAM mode of authentication is completely optional. Remember that the same application can talk to both a non-PAM capable server, and to a PAM capable server. No separate applications will need to be written for connecting to two such servers.

To date no incompatibilities have been observed in terms of the client-server communication.


Conclusion

The pluggable authentication module offers database administrators a great deal more flexibility and control over authentication policies for Informix Dynamic Server databases. Existing PAM modules written for other applications can be used for the client-server authentication, thereby employing a common authentication for a wide variety of applications, and reducing maintenance cost.

In the past you would need a separate authentication scheme for every type of user, and would need to write a program for each type. Now PAM allows the ESQL/C application developers to focus on the function of the core program itself, while letting the database administrator, and the PAM modules written earlier, take control of the authentication process. This pluggable flexibility is really the future of client-server authentication, and as a matter of fact, the future for every program that requires authentication.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Information management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=219869
ArticleTitle=Using the PAM Authentication Method with ESQL/C
publish-date=06052003