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 users first. At times, the authentication methodologies may need modification or replacement when system administrators want to enforce different security policies. The replacement or modification must be implemented in a way that doesn't affect users and also ensures that users are properly authenticated.
Traditionally, Informix servers and clients have only supported simple authentication mechanisms:
- Trusted hosts: The database assumes trust based on the source of the connection request. If the machine that initiates the request is trusted, then the user is also trusted.
- Password file-base 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 dependency between the system services and the database server makes for difficulties in the following ways:
- These mechanisms cannot accommodate new authentication mechanisms.
- These existing mechanisms cannot utilize any enhanced authentication provided by the operating system.
Moreover, it is cumbersome for the user to maintain multiple passwords.
Now that a Pluggable Authentication Module (PAM) mechanism is available, the scope of authentication is expanded. With the implementation of PAM in IBM IDS, applications can make use of an authentication module and thereby increase the options for authenticating with the database server.
The primary purpose of supporting PAM is having the ability to use enhanced operating system-level authentication. Since the authentication takes place at the server, you must have IBM IDS V9.40 xc2 or a later version. 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®.
You must also have IBM Informix JDBC Driver Version 2.21. JC5 and later. If the server to which you are connecting is on any other operating system, the applications will connect to the server using the traditional authentication mode.
At the client, as long as there is a function to handle the challenges thrown by the server, the client application is platform independent.
Note: If the client is an older version, you cannot use the PAM mechanism.
The PAM framework consists of:
- PAM API, authentication library API (the front-end)
- Authentication specific modules (the back-end)
- Service Provider Interface (SPI) that connects the front-end and the back-end
Figure 1. Illustration of PAM architecture
These are the basic steps of the PAM authentication process:
- When an application calls the PAM API, it loads the appropriate authenticating module as determined by the configuration file, pam.conf.
- The request is then forwarded to the authentication module through the SPI.
- The response from the authentication module is returned to the application.
The PAM interface consists of:
- Authentication Management: This interface deals with authentication in general. This interface includes the pam_authenticate() function to authenticate the user, and the pam_setcred() interface to set, refresh or destroy the user credentials.
- Account Management: This interface deals with the account specifically. This interface includes the pam_acct_mgmt() function to check whether authenticated users should receive access to their accounts. This function can implement account expiration and access hour restrictions.
- Session Management: This interface deals with the session management and accounting. This interface includes the pam_open_session() and pam_close_session() functions for session management. For example, you can store the total time for the session.
- Password Management: This interface deals with the password and related functions, such as changing passwords. It includes the pam_chauthtok() function to change the password.
At this point, IDS provides support for two of those functionalities, the Authentication Management and Account Management interfaces.
This article demonstrates how you would write a PAM module that can later be registered with the server. In this example, you are only implementing the authentication management interface. The remaining interfaces, including pam_sm_setcred, pam_sm_acct_mgmt, pam_sm_open_session, pam_sm_close_session, pam_sm_chauthtok are left in "dummy" status.
Listing 1. C example showing how to write a PAM module
#include <dlfcn.h>
#include <link.h>
#include <string.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#ifndef PAM_EXTERN
#define PAM_EXTERN
#endif
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[])
{
struct pam_conv *conv;
struct pam_message msg[3], *msgp;
struct pam_response *resp;
const char *user;
char *answer, *prompt[3], *vanswer[3];
int pam_err, retry;
int (*xjm)();
void *handle = NULL;
prompt[0] = (char *) strdup("Your school name (MIT):");
prompt[1] = (char *) strdup("Your maiden name (SUZE):");
prompt[2] = (char *) strdup("PAM Text Info");
vanswer[0] = (char *) strdup("MIT");
vanswer[1] = (char *) strdup("SUZE");
vanswer[2] = (char *) NULL;
handle = dlopen(NULL, RTLD_GLOBAL | RTLD_LAZY);
xjm = dlsym(handle, "CRYPTO_new_ex_data");
dlclose(handle);
pam_err = pam_get_item(pamh, PAM_CONV, (void **)&conv);
if (pam_err != PAM_SUCCESS)
return (PAM_SYSTEM_ERR);
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
msg[0].msg = prompt[0];
msg[1].msg_style = PAM_PROMPT_ECHO_ON;
msg[1].msg = prompt[1];
msg[2].msg_style = PAM_TEXT_INFO;
msg[2].msg = prompt[2];
for (retry=0;retry<3;retry++){
msgp = &msg[retry];
resp = NULL;
pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
if (pam_err == PAM_SUCCESS){
/* No response needed for text info and error msg */
if ((msg[retry].msg_style == PAM_TEXT_INFO) ||
(msg[retry].msg_style == PAM_ERROR_MSG))
{
continue;
}
answer = resp->resp;
if (!answer){
pam_err = PAM_AUTH_ERR;
break;
}
if (strcmp(answer, vanswer[retry])){
pam_err = PAM_AUTH_ERR;
break;
}
}
}
if (resp){if (resp>resp){free(resp->resp);}free (resp);}return (pam_err);
}
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_close_session(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
return (PAM_SERVICE_ERR);
}
|
The C module includes a callback function. This function must be registered. The primary purpose of the callback function is to allow you to handle all the challenges thrown your way by the PAM service. The callback function accepts the challenges from the server, sends them to the user, brings back the responses to those challenges, and passes the responses to the server.
Compiling the module and updating the configuration file
Solaris-32:
- Compile the module:
Listing 2. Compile the modulecc -g -Xa -D_REENTRANT -K PIC -DSHARED_FLAG -c pam_chal.c ld -G -B dynamic -o pam_chal.so pam_chal.o -lw -ldl -lgen -lelf -lc -lpam
- Update the configuration file (for example, etc/pam.conf) as shown below:
Listing 3. Example configuration file# PAM Challenge module #service Module-type Control-flag Module path Options login auth required pam_unix_auth.so nowarn pam_chal auth required /usr/lib/security /pam_chal.so
The following parameters are included in the configuration file:
- Service: This is the name of the service. Generally, it is the name of system-entry applications such as login.
- Module-type: This specifies the type of module. The value could be auth, account, session or password module types.
- Control-flag: This defines the behavior of stacking modules by specifying whether any particular module is requisite, required, optional, or sufficient.
- Module Path: This specifies the location of the module. You can use a default directory path to make administration easier. In this case, it is /usr/lib/security.
- Options: These are options that can be interpreted by the modules.
Configuring connectivity between client and server to use PAM
The connectivity is defined in the SQLHOSTS file of the server. Listing 4 shows a sample SQLHOSTS file on a PAM-enabled server.
Listing 4. Sample SQLHOSTS file
#Server-name service machinename portno Options
Ids_950ucx ontlitcp idc1ul14 950ucx_serv s=4,pam_serv=(pam servicename),
pamauth=(challenge)
|
Here are the parameters that are included in the in the SQLHOSTS file:
- Server-name: Name of the IBM IDS server (as present in the onconfig file)
- Service: This defines which service to use (for example, ontlitcp, onsoctcp, onipcshm, and so on.)
- Machinename: Name of the machine where the IBM IDS server resides.
- Portno: Number of the port used for communication between client and server.
-
Options:
- pam_serv = pam servicename: Name of the PAM service module written by the user and placed in the /usr/lib/security directory of the machine where the IDS server resides. This is the service that authenticates users.
-
pamauth = challenge: The IDS server is brought up in challenge mode.
The valid values for pamauth are challenge and password.
Challenge - In this case, the server authentication follows a challenge-response dialog.
Password - In this case, the server follows simple password authentication.
Implementing the callback module using Informix JDBC client
The sample module illustrates how you can implement PAM in the IBM Informix JDBC driver. This module supports a challenge-response dialog.
Listing 5. Sample callback module using JDBC driver
import com.informix.jdbc.IfmxPAM;
import com.informix.jdbc.IfxPAMChallenge;
import com.informix.jdbc.IfxPAMResponse;
public class InfxPAMModule implements IfmxPAM
{
public IfxPAMResponse IfxPAM(IfxPAMChallenge challengeMessage)
{
IfxPAMResponse r = new IfxPAMResponse();
String cm = challengeMessage.getChallenge();
if (cm==null )
{
r.setResponse("UNKNOWN RESPONSE MESSAGE!");
}
else
{
if (challengeMessage.getChallengeType() == IfxPAMChallenge.PAM_PROMPT_ECHO_OFF)
r.setResponse("MIT");
else if (challengeMessage.getChallengeType() == IfxPAMChallenge.PAM_PROMPT_ECHO_ON)
r.setResponse("SUZE");
}
return r;
}
|
JDBC developers using PAM for authentication must implement the com.informix.jdbc.IfmxPAM interface. The following set of events occurs during authentication.
- The JDBC driver, when detecting communication with a PAM-enabled server, contacts the IfxPAM() method and passes it a IfxPAMChallenge object containing the PAM challenge question.
- A dialog box you create appears with a text question containing the challenge message that PAM set up.
- When the user furnishes the response, it is packaged into an IfxPAMResponse object, and it is returned to the JDBC driver by exiting the IfxPAM() method and returning the IfxPAMResponse object.
- When PAM receives the response from the challenge question, it can authorize the user, deny access to the user, or issue another challenge question, in which case the above process is repeated. The process continues until the user is authorized or access is denied.
Note: The response from this module should be the same as is expected by the server.
The sample application establishes connection to the IBM IDS server using the above JDBC PAM module.
Listing 6. Sample JDBC client application implementing the callback module
public class IDSConnectTest {
Connection conn = null;
public IDSConnectTest() {
super();
try {
Class.forName("com.informix.jdbc.IfxDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String url = "jdbc:informix-sqli://celmis.lenexa.ibm.com:9899/"+"test"+":"
+ "INFORMIXSERVER=ol_cheetah;IFX_PAM_CLASS=InfxPAMModule";
String user = "userid";
String password = "password";
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String argc[])
{
IDSConnectTest test;
test = new IDSConnectTest();
}
}
|
The IFX_PAM_CLASS value that is specified is intended to inform the JDBC driver what class (module) has implemented the PAM interface.
Note: The IFX_PAM_CLASS is mandatory when the server is brought up in challenge mode. However, it is not mandatory when
the server is brought up in password mode.
This article discusses the issues in the existing system services. PAM offers database and system developers a great deal of flexibility and control over authentication policies. You can use existing PAM modules written for other applications for client-server authentication, thereby facilitating a common authentication strategy for a wide variety of applications and reducing maintenance costs. After reading this article, you should be able to configure a PAM-enabled IBM IDS and be able to write a JDBC application in a client-server environment.
Learn
-
General PAM information: This article provides additional background on PAM.
-
Using the PAM Authentication Method with ESQL/C: Learn how to implement the PAM mechanism within the ESQL/C applications using a sample ESQL/C program.
-
IBM Informix JDBC Driver Programmer's Guide: Learn more about the PAM authentication method in IBM Informix JDBC.
Get products and technologies
-
Download a free trial version of Informix Dynamic Server.
-
Download
IBM product evaluation versions and get your hands on application development tools
and middleware products from DB2®, Lotus®, Rational®, Tivoli®,
and WebSphere®.
Discuss
- Participate in the discussion forum.
-
Check out developerWorks
blogs and get involved in the developerWorks community.

Manoj Mohan has worked in the IBM-IDS Team as a software developer for five years. His experiences include designing and implementing Pluggable Authentication Module (PAM) and IP V6 support in IDS Server. Manoj was also involved in designing and implementing trusted context support in DB2 for Linux, UNIX, and Windows.
Comments (Undergoing maintenance)







