DB2 9部署定制的安全性插件(3)
DB2 9 中 DB2 安全性插件的增强
DB2 9 中对 DB2 安全性插件基础设施进行了很多增强,包括基于轻量级目录访问协议(Lightweight Directory Access Protocol,LDAP)的身份验证插件的输送、基于 LDAP 的组成员查找插件的输送、及 client connection details 的增强以包括对 TCP/IP 版本 6 和客户机操作系统平台信息的支持。
可以从 DB2 LDAP 验证插件 下载受 IBM 支持的基于 LDAP 的身份验证插件和组成员查找插件。
如果已经通过 TCP/IP 地址实现了连接限定,且您的公司正准备实现 TCP/IP 版本 6,则需要修改安全性插件,从而进行对应的操作。
首先,需要从使用下面所列的版本 2 或 3 的连接详细信息结构(节选自 IBM 发布的头文件 db2secPlugin.h)开始。版本 2 和 3 的区别在于版本 3 还给出了客户机操作系统平台。
清单 1. 客户机连接详细信息结构的新版本
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;
然后,在调用回调函数时,使用 DB2SEC_CON_DETAILS_VERSION_2 或 DB2SEC_CON_DETAILS_VERSION_3 来代替 DB2 V8.2 文档所建议的 DB2SEC_API_VERSION_1 或数字 1。例如,假定要使用连接详细信息版本 3;可以在插件中进行下面的回调:
struct db2sec_con_details_3 con_struct3;
rc = (getConDetails_fn)(DB2SEC_CON_DETAILS_VERSION_3, &con_struct3);
由于在整个机构上使用 TCP/IP 版本 6 是一个较长的过程,因此 DB2 可能会遇到一些仍使用 TCP/IP 版本 4 的客户机或其他切换到 TCP/IP 版本 6 的客户机。为了帮助使用者区分客户机,结构中 clientProtocol 字段现在可以返回 SQL_PROTOCOL_TCPIP4 或 SQL_PROTOCOL_TCPIP6,用来指示客户机正在使用的 TCP/IP 协议是版本 4,还是版本 6。
如果需要找到客户机的操作系统,则可以检查 DB2 通过回调函数返回到字段 clientPlatform 中的整数。整数到相应平台的映射如下(节选自 IBM 发布的头文件 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 */
下面是示例代码片断,其中阻塞了数据库服务器上的回路连接:
清单 2. 来自本系列第 2 部分的连接限定代码
/* 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;
}
}
为了使用 TCP/IP 版本 6,需要修改为以下代码:
清单 3. 使用 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);
}
结束语
本文给出了 DB2 9 中 DB2 安全插件的增强信息,详细阐述了安全性插件的职责。本文还提出了基于这些职责的最小完备测试列表。现在您应知道如何使用安全性插件 loader 来测试定制的安全性插件,该 loader 可以在 下载 部分中找到。