In part 2 of this series, DB2 security plug-ins were introduced, as well as the method in which DB2 security is implemented, and a list of relevant detailed information about security plug-ins. In part 6 of this series, the DB2 shipped Kerberos security plug-ins were introduced as well as how to deploy Kerberos authentication using this plug-in. This article explains what the plug-in writer or database administrator should test before deploying the customized security plug-ins to the DB2 system.
Authorization in DB2 is based on two things:
- The effective database authorization ID (authid) of the external user performing a particular task
- The membership of that user in particular groups
Before knowing if a user is authorized to do a particular operation, DB2 must be able to know the effective database authorization ID of the external user, and in which groups that user belongs. In order to find the effective database authorization ID, you need to ensure that the external user is who they say they are, and then map their external user ID to an internal DB2 authorization ID. The process of doing this is referred to as authentication. DB2 does not have its own mechanism for maintaining user IDs and passwords, or user ID group memberships.
What does a security plug-in do?
There are two events that require the use of either (client-side or server-side) an authentication plug-in or group membership look-up plug-in:
- During the connection or instance attachment
- During instance-level operation authorization
Instance-level operation is any operation that has to due with the maintenance of a DB2 instance. Some typical examples of instance-level operations are update database manager, configuration parameter, and start database manager.
Take a look at instance-level operations first. Most instance-level operation commands do not accept user IDs or passwords as part of the input. In this case, you have to employ the client-side authentication plug-in (also known as the client auth plug-in) to find out who is the current logon user that is issuing the command. (This is what is referred to as getting a default login context. A login context can be a user ID/password pair or a Generic Security Services API [GSS-API] credential such as a Kerberos ticket). Once the user's identity is obtained, the DB2 group membership lookup plug-in (also known as the group plug-in) is used to generate a list of group authorization IDs for the user.
During a connection establishment or instance attachment, user IDs and passwords are optional. If the user chooses to opt out of specifying the user ID and password, DB2 employs the client auth plug-in to get the default login context. Then, the login context is sent to the server for obtaining group authorization IDs for the user. If the user chooses to specify a user ID and password, DB2 performs the following steps if the authentication type database manager configuration parameter is not specified as CLIENT:
Table 1. Flow of information for authentication other than CLIENT
| Client | Flow of information (if applicable) | Server |
|---|---|---|
| (Client auth plug-in) Remap user ID, password, and namespace if the db2secRemapUserid is implemented and the authentication plug-in is user ID/password based. Note that this process also applies to the default login context case. | ||
| Sent the login context to the server. | Login context -> | Server received the login context. |
| (Server auth plug-in) Validate the login context (validate the user ID and password or the GSS-API credential such as Kerberos ticket) and obtained the authorization ID for the user. | ||
| Obtained the group authorization ID for the user using the group plug-in on the server. |
If the authentication type is specified as CLIENT authentication on the database server, the following step occurs:
Table 2. Flow of information for CLIENT authentication
| Client | Flow of information (if applicable) | Server |
|---|---|---|
| (Client auth plug-in) Remap user ID, password, and namespace if the db2secRemapUserid is implemented and the authentication plug-in is user ID/password based. Note that this process also applies to the default login context case. | ||
| (Client auth plug-in) Validate the login context (validate the user ID and password or the GSS-API credential such as Kerberos ticket) and obtained the authorization ID for the user. | ||
| Sent the user ID to the server. | user ID -> | (Server auth plug-in) Server received user ID and obtained the authorization ID for the user. |
| Obtained the group authorization ID for the user using the group plug-in on the server. |
Suggested minimum sanity testing
Based on the duties of the security plug-in that was described in the previous section, it is suggested that the security plug-in should go through the following testing at a minimum:
- Using an unauthorized user, attempt to perform instance-level operations such as get the database manager configuration parameter. This should fail.
- Using an authorized user, attempt to perform instance-level operations. This should succeed.
- Using a valid user ID and password, establish a connection to a database and attempt to exercise the privilege granted to one of the group authorization IDs. This should succeed.
- Attempt to use either an invalid user ID or an invalid password to connect. This should fail.
- Attempt to connect without specifying a user ID and password. This should only work if the client and the server are on the same machine, and no special restriction logic is implemented in the customized security plug-ins. This ensures the right login user credential is returned by the customized security plug-in to DB2.
- If you are implementing customized group plug-ins, make sure your db2secGetGroupForUser API understands authorization ID and is always uppercased, despite the fact that your customized authentication plug-in might have returned an authorization ID that is of mixed case or lower case.
The security plug-in loader program allows you to simulate DB2s responses to the suggested testing above. This could be very useful if you want to figure out whether a particular problem is due to code within your plug-in or on the DB2 side.
Program inputs are:
- -c option: The fully qualified path and the plug-in name for the client-side auth plug-in.
- -s option: The fully qualified path and the plug-in name for the server-side auth plug-in.
- -g option: The fully qualified path and the plug-in name for the group plug-in.
- -u option: User ID.
- -p option: Password. (For GSS-API or Kerberos, this is the password that is used to get the user credential.)
- -d option: Database name.
- -n option: New password.
- -a option: User authorization ID.
At the launch or execution time of the loader, all three specified security plug-ins (client auth plug-in, server auth plug-in, and group plug-in) are loaded as needed and the type of authentication plug-in (such as user ID/password-based, Kerberos-based, or GSS-API-based) is determined. The initialization functions for each plug-in are called and all the function pointers for each plug-in are retrieved.
Based on the combination of the options you specified, it performs one of the following four types of testing for you.
For simplicity, this loader does not support testing of client authentication, and it does not provide the get Client connection details callback functions to your customized plug-in (such as, db2secGetConDetails). The db2secLogMessage is provided to the plug-in, but the output is directed to your standard output (screen).
The following four testing functionalities are provided by the loader to simulate the usage of the security plug-in on a DB2 environment calling the exact same sequence of APIs.
Establish a connection with the given user ID and password, and validate the password or credentials. The output is the authid and the group authids list.
- The following is the API calling sequence if a Kerberos or GSS-API-based authentication plug-in is in use:
- Client plug-in: db2secProcessServerPrincipalName
- Client plug-in: db2secGenerateInitialCred
- Client plug-in: gss_init_sec_context
- Server plug-in: gss_accept_sec_context
There is a loop between the client-side API: gss_init_sec_context and the server-side API: gss_accept_sec_context, until one side returns GSS_S_COMPLETE. If more tokens are expected from the other side, the API should return GSS_S_CONTINUE_NEEDED.
- Client plug-in: gss_release_buffer, gss_release_name, gss_release_cred, db2secFreeInitInfo, gss_delete_sec_context
- Server plug-in: gss_release_buffer, db2secGetAuthIDs
- Group plug-in: db2secGetGroupForUser
- Client plug-in: db2secFreeToken
- Server plug-in: gss_delete_sec_context
- Group plug-in: db2secFreeGroupListMemory
Figure 1. API calling sequence with a Kerberos or GSS-API-based authentication plug-in
- The following is the API calling sequence if a user ID/password-based authentication plug-in is in use:
- Client plug-in: db2secRemapUserid if it is optionally implemented
- Server plug-in: db2secValidatePassword, db2secGetAuthIDs
- Group plug-in: db2secGetGroupForUser
- Server plug-in: db2secFreeToken
- Group plug-in: db2secFreeGroupListMemory
Figure 2. API calling sequence with a user ID/password-based authentication plug-in
Establish a connection without providing a user ID and password (default login context). The output is the authid and group authids list.
- The following is the API calling sequence if a Kerberos or GSS-API-based authentication plug-in is in use:
- Client plug-in: db2secGetDefaultLoginContext
- Client plug-in: db2secProcessServerPrincipalName
- Client plug-in: gss_init_sec_context
- Server plug-in: gss_accept_sec_context
There is a loop between the client-side API: gss_init_sec_context and the server side API: gss_accept_sec_context, until one side returns GSS_S_COMPLETE. If more tokens are expected from the other side, the API should return GSS_S_CONTINUE_NEEDED.
- Client plug-in: gss_release_buffer, gss_release_name, gss_delete_sec_context
- Server plug-in: gss_release_buffer, db2secGetAuthIDs
- Group plug-in: db2secGetGroupForUser
- Client plug-in: db2secFreeToken
- Server plug-in: gss_delete_sec_context
- Group plug-in: db2secFreeGroupListMemory
Figure 3. API calling sequence with a Kerberos or GSS-API-based authentication plug-in
- The following is the API calling sequence if a user ID/password-based authentication plug-in is in use:
- Client plug-in: db2secGetDefaultLoginContext, db2secFreeToken
- Server plug-in: db2secGetAuthIDs
- Group plug-in: db2secGetGroupForUser
- Server plug-in: db2secFreeToken
- Group plug-in: db2secFreeGroupListMemory
Figure 4. API calling sequence with a user ID/password-based authentication plug-in
Given a user authorization ID, the output is the group authids list.
The following is the API calling sequence:
- Group plug-in: db2secGetGroupsForUser
Figure 5. API calling sequence
Simulate the testing of the local authorization for an instance-level operation (without the user ID and password). The output is the group authids list.
The following is the API calling sequence:
- Client plug-in: db2secGetDefaultLoginContext
- Group plug-in: db2secGetGroupForUser
- Client plug-in: db2secFreeToken
- Group plug-in: db2secFreeGroupListMemory
Figure 6. API calling sequence
Enhancements to DB2 security plug-ins in DB2 9
In DB2 9, there have been numerous enhancements to the DB2 security plug-in infrastructure, including the shipping of the Lightweight Directory Access Protocol (LDAP)-based authentication plug-in, the shipping of the LDAP-based group membership look-up plug-in, and enhancement to the client connection details to include support for TCP/IP Version 6 and the client machine operating system platform information.
You can download the IBM supported LDAP-based authentication plug-in and group membership look-up plug-in from DB2 LDAP Authentication Plugins.
If you have implemented a connection restriction through a TCP/IP address (An example of how to do so is found in the "Steps to test connection restriction ability of the plug-in" section in part 2 of this series.), and your company is moving toward implementing TCP/IP Version 6, you need to modify your security plug-in to handle it.
First of all, you need to start using either Version 2 or 3 of the connection details structure listed below (extracted from IBM-shipped header file db2secPlugin.h). The difference between Version 2 and 3 is that the Version 3 also gives you the client machine operating system platform.
Listing 1. New version of client connection details structure
typedef struct db2sec_con_details_2
{
db2int32 clientProtocol; /* See SQL_PROTOCOL_ in sqlenv.h */
db2Uint32 clientIPAddress; /* Set if protocol is TCPIP4 */
db2Uint32 connect_info_bitmap;
db2int32 dbnameLen;
char dbname[DB2SEC_MAX_DBNAME_LENGTH + 1];
db2Uint32 clientIP6Address[4];/* Set if protocol is TCPIP6 */
} db2sec_con_details_2;
typedef struct db2sec_con_details_3
{
db2int32 clientProtocol; /* See SQL_PROTOCOL_ in sqlenv.h */
db2Uint32 clientIPAddress; /* Set if protocol is TCPIP4 */
db2Uint32 connect_info_bitmap;
db2int32 dbnameLen;
char dbname[DB2SEC_MAX_DBNAME_LENGTH + 1];
db2Uint32 clientIP6Address[4];/* Set if protocol is TCPIP6 */
db2Uint32 clientPlatform; /* SQLM_PLATFORM_* from sqlmon.h */
db2Uint32 _reserved[16];
} db2sec_con_details_3;
|
Then, use DB2SEC_CON_DETAILS_VERSION_2 or DB2SEC_CON_DETAILS_VERSION_3 instead of using DB2SEC_API_VERSION_1 or the number 1 as suggested by the DB2 V8.2 documentation when you are calling the callback function. For example, assume that you want to use the Version 3 of the information; you can do the following callback inside your plug-in:
struct db2sec_con_details_3 con_struct3;
rc = (getConDetails_fn)(DB2SEC_CON_DETAILS_VERSION_3, &con_struct3);
|
Since rolling out TCP/IP Version 6 over the entire organization can be a long process, it is possible that DB2 will encounter some clients that are still using the TCP/IP Version 4 and other clients that are switched to TCP/IP Version 6. To help the customer to distinguish this client, the clientProtocol field of the structure is now able to return either SQL_PROTOCOL_TCPIP4 or SQL_PROTOCOL_TCPIP6 to indicate whether the client is using Version 4 or Version 6 of the TCP/IP protocol.
If you need to find out the operating system of the client machine, you can check the integer value returned by DB2 through the callback function in the field clientPlatform. The mapping of the integer to the corresponding platform are (extracted from IBM shipped header file sqlmon.h):
#define SQLM_PLATFORM_UNKNOWN 0 /* Unknown platform */ #define SQLM_PLATFORM_OS2 1 /* OS/2 */ #define SQLM_PLATFORM_DOS 2 /* DOS */ #define SQLM_PLATFORM_WINDOWS 3 /* Windows */ #define SQLM_PLATFORM_AIX 4 /* AIX */ #define SQLM_PLATFORM_NT 5 /* NT */ #define SQLM_PLATFORM_HP 6 /* HP */ #define SQLM_PLATFORM_SUN 7 /* Sun */ #define SQLM_PLATFORM_MVS_DRDA 8 /* MVS (client via DRDA) */ #define SQLM_PLATFORM_AS400_DRDA 9 /* AS400 (client via DRDA) */ #define SQLM_PLATFORM_VM_DRDA 10 /* VM (client via DRDA) */ #define SQLM_PLATFORM_VSE_DRDA 11 /* VSE (client via DRDA) */ #define SQLM_PLATFORM_UNKNOWN_DRDA 12 /* Unknown DRDA Client */ #define SQLM_PLATFORM_SNI 13 /* Siemens Nixdorf */ #define SQLM_PLATFORM_MAC 14 /* Macintosh Client */ #define SQLM_PLATFORM_WINDOWS95 15 /* Windows 95 */ #define SQLM_PLATFORM_SCO 16 /* SCO */ #define SQLM_PLATFORM_SGI 17 /* Silicon Graphic */ #define SQLM_PLATFORM_LINUX 18 /* Linux */ #define SQLM_PLATFORM_DYNIX 19 /* DYNIX/ptx */ #define SQLM_PLATFORM_AIX64 20 /* AIX 64 bit */ #define SQLM_PLATFORM_SUN64 21 /* Sun 64 bit */ #define SQLM_PLATFORM_HP64 22 /* HP 64 bit */ #define SQLM_PLATFORM_NT64 23 /* NT 64 bit */ #define SQLM_PLATFORM_LINUX390 24 /* Linux for S/390 */ #define SQLM_PLATFORM_LINUXZ64 25 /* Linux for z900 */ #define SQLM_PLATFORM_LINUXIA64 26 /* Linux for IA64 */ #define SQLM_PLATFORM_LINUXPPC 27 /* Linux for PPC */ #define SQLM_PLATFORM_LINUXPPC64 28 /* Linux for PPC64 */ #define SQLM_PLATFORM_OS390 29 /* OS/390 Tools (CC, DW) */ #define SQLM_PLATFORM_LINUXX8664 30 /* Linux for x86-64 */ #define SQLM_PLATFORM_HPIA 31 /* HP-UX Itanium 32bit */ #define SQLM_PLATFORM_HPIA64 32 /* HP-UX Itanium 64bit */ |
In the sample connection restriction code in part 2 of the series, gethostname and gethostbyname are used to the TCP/IP address of the database server machine. The following is an extract of code from the sample where it is blocking a loopback connection on the database server:
Listing 2. Connection restriction code from part 2 of the series
/* If the connection is not local */
if (!(con_struct.connect_info_bitmap & DB2SEC_CONNECTION_ISLOCAL))
{
struct hostent* hostinfo;
char hostname[256];
int* firstaddr;
/* Get the address of the machine restricted */
gethostname(hostname, sizeof(hostname));
hostinfo = gethostbyname(hostname);
firstaddr = (int *)*(hostinfo->h_addr_list);
/* If the client IP address is the restricted one */
if (*firstaddr == con_struct.clientIPAddress)
{
/* We won't allow behavoir to connect through this IP address */
if (0 == strcmp(userid, "beauvoir"))
return DB2SEC_PLUGIN_CONNECTION_DISALLOWED;
}
}
|
You need to modify to the following in order to work with Version 6 of the TCP/IP protocol:
Listing 3. Connection restriction code that works with IP V6
if (!(con_struct3.connect_info_bitmap & DB2SEC_CONNECTION_ISLOCAL))
{
struct addrinfo* pAddr;
/* find the local IP address to compare it with the one retrieved */
if ((con_struct3.clientProtocol == SQL_PROTOCOL_TCPIP6) &&
(IN6_IS_ADDR_V4MAPPED((struct in6_addr *)con_struct3.clientIP6Address)))
{
/* Comment out the following line of code if your database server is not */
/* running on MS Windows */
aiHints.ai_flags = AI_ALL | AI_V4MAPPED;
}
else
{
aiHints.ai_flags = AI_PASSIVE;
}
aiHints.ai_family = (con_struct3.clientProtocol == SQL_PROTOCOL_TCPIP6)?
AF_INET6 : AF_INET;
aiHints.ai_socktype = SOCK_STREAM;
aiHints.ai_protocol = IPPROTO_TCP;
err = getaddrinfo(hostname, NULL, &aiHints, &aiList);
if (err)
{
Print("getaddrinfo error: %d\n", err);
return DB2SEC_PLUGIN_CONNECTION_DISALLOWED;
}
/* compare the IPs */
if (SQL_PROTOCOL_TCPIP6 == con_struct3.clientProtocol)
{
pAddr = aiList;
while (pAddr)
{
struct sockaddr_in6* s = (struct sockaddr_in6*)pAddr->ai_addr;
struct in6_addr *src = (struct in6_addr*)&s->sin6_addr;
struct in6_addr *dst =
(struct in6_addr*)&con_struct3.clientIP6Address;
/* check if address verified is the same format as the address
* sent by the client: compare only IPv6 format address with
* IPv6 ones or IPv6 mapped IPv4 with the same type */
if ((*(db2Uint32*)(&s->sin6_addr.s6_addr[0]) ==
con_struct3.clientIP6Address[0]) &&
(*(db2Uint32*)(&s->sin6_addr.s6_addr[4]) ==
con_struct3.clientIP6Address[1]) &&
(*(db2Uint32*)(&s->sin6_addr.s6_addr[8]) ==
con_struct3.clientIP6Address[2]) &&
(*(db2Uint32*)(&s->sin6_addr.s6_addr[12])==
con_struct3.clientIP6Address[3]))
{
/* don't allow beauvoir to connect through this ip address */
if (0 == strcmp(userid, "beauvoir"))
{
return DB2SEC_PLUGIN_CONNECTION_DISALLOWED;
}
else
{
break;
}
}
pAddr = pAddr->ai_next;
} /* while (pAddr) */
}
else /* This else clause is need if you have a mix v4 and v6 environment */
{
/* TCPIP4 */
struct sockaddr_in* s = (struct sockaddr_in*)aiList->ai_addr;
if (s->sin_addr.s_addr == con_struct3.clientIPAddress)
{
/* don't allow beauvoir to connect through this ip address */
if (0 == strcmp(userid, "beauvoir"))
return DB2SEC_PLUGIN_CONNECTION_DISALLOWED;
}
}
freeaddrinfo(aiList);
}
|
This article provided you the enhancement information for the DB2 security plug-in in DB2 9, and explained in detail the duties of the security plug-ins. The article also suggested a list of minimum sanity testing based on these duties. You should now understand how to use the security plug-in loader, which is found in the Download section, to test customized security plug-ins.
| Description | Name | Size | Download method |
|---|---|---|---|
| Plug-in loader program | loader.zip | 58KB | HTTP |
Information about download methods
Learn
-
Visit the developerWorks resource page for DB2 for Linux, UNIX, and Windows to read articles and tutorials and connect to other resources to expand your DB2 skills.
-
Learn about DB2 Express-C, the no-charge version of DB2 Express Edition for the community.
-
Stay current with
developerWorks
technical events and Webcasts.
-
developerWorks Information Management zone: Learn more about DB2. Find technical documentation, how-to articles, education, downloads, product information, and more.
- Understanding DB2 9 Security (ISBM: 0131345907) (December 2006); Rebecca Bond, Kevin Yeung-Kuen See, Carmen Ka Man Wong, Yuk-Kuen Henry Chan: Direct from a DB2 Security deployment expert and the IBM® DB2 development team, this book provides you a wealth of security information that isn't available anywhere else.
Get products and technologies
- DB2 LDAP Authentication Plugins: Download the IBM supported LDAP-based authentication plug-in and group membership look-up plug-in.
-
Download a free trial version of DB2 Enterprise 9.
-
Now you can use DB2 for free. Download DB2 Express-C, a no-charge version of DB2 Express Edition for the community that offers the same core data features as DB2 Express Edition and provides a solid base to build and deploy applications.
-
Download IBM product evaluation versions and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
-
Build your next development project with
IBM
trial software, available for download directly from developerWorks.
Discuss
- Participate in the discussion forum.
-
Participate in developerWorks
blogs and get involved in the developerWorks community.

Kevin Yeung-Kuen See, CISSP, has been a software developer at the IBM Toronto Laboratory for the past decade. His experience includes working on the DB2 Security Development team and the DB2 SQL and Catalog Development team. He received a Masters of Mathematics in Computer Science (specializing in software engineering) from University of Waterloo and a Bachelor of Computer Science from Acadia University. He is an IBM Certified Solutions Developer for XML and Related Technologies and a DB2 Certified Solutions Expert (DBA for OS390, DBA for Linux, Unix, and Windows, Advanced DBA for Linux, Unix, and Windows, and DB2 Family Application Development). He is also an ISC2 Certified Information Systems Security Professional (CISSP). He has written a few IBM developerWorks articles on the topic of DB2 security and is co-authoring an upcoming retail book titled "Understanding DB2 9 Security." In his spare time, he enjoys hiking, learning something new, and trying to figure out the world according to Justin, his toddler son.
Yung Chung is a Software Developer at the IBM Toronto Lab working in the DB2 Continuing Engineering team. Prior to that, he worked on the DB2 UNIX Development team. Yung received a Bachelor of Science degree from York University and is is an IBM Certified Solutions Expert (DBA for Linux/UNIX/Windows).
Comments (Undergoing maintenance)





