级别: 中级 Kevin Yeung-Kuen See (see@ca.ibm.com), 软件开发人员, IBM Sushma Narisetty (sushma.narisetty@utoronto.ca), 信息开发人员, IBM Raul F. Chong (rfchong@ca.ibm.com), DB2 UDB 专家, IBM Il-Sung Lee (ilsung@microsoft.com), 程序经理, Microsoft Corporation
2005 年 12 月 01 日 学习 8.2 版中新引入的 DB2 UDB 安全性插件。本文解释安全性插件的功能,并教您如何启用和编写自己的安全性插件。
简介
本系列的 第 1 部分 介绍了 DB2 安全性模型,并讨论了用户和组帐户如何与 DB2 Universal Database(UDB)交互。本系列的第 2 部分主要关注 DB2 安全性插件,这是实现 DB2 安全性的新方法。本文讨论为了很好地理解 DB2 安全性插件而需要知道的方方面面,并讨论不同类型的安全性插件,它们为什么如此重要,以及如何使用它们。本文还提供了一些安全性插件程序示例,并展示如何逐步实现它们。阅读本文之后,您应该能够编写基本的安全性插件程序,并且可以避免使用那些插件时遇到的常见错误。
DB2 UDB 安全性插件 —— 概述
安全性插件是动态可装载库,当 DB2 UDB 进行身份验证或者从组成员中查找某个用户的时候,便调用这些库。在 8.2 版之前,这些操作是由 DB2 UDB 之外的设施管理的,例如操作系统、域管理器或 Kerberos 安全性系统。图 1 提供的场景说明了在 8.2 版之前 DB2 UDB 安全性的工作原理。下一节将描述 8.2 版中发生的变化。
图 1. 安全性场景
图 1 说明了 4 个安全性场景:
- 客户机系统通过服务器系统连接到数据库时的安全性考虑。
在图 1 左侧,一个用户在 DB2 客户机系统的命令行处理程序(CLP)窗口中发出了语句 connect to mydb user raul using raulpsw,以连接到位于 DB2 数据库服务器 Aries 上的数据库 mydb。DB2 客户机与服务器通信,协商采用何种身份验证方法。为简单起见,我们假设客户机使用服务器返回的身份验证方法。在图中,AUTHENTICATION 被设置为 SERVER。这意味着,服务器(I)上的操作系统将通过检查提供的用户 ID 和密码是否与存储在操作系统安全性数据库中的值匹配,来进行身份验证。一旦用户通过身份验证,DB2 将从操作系统获得组成员信息。从此以后,DB2 不再在以后的检查中使用用户 ID 或密码;相反,DB2 将使用授权 ID(authID)。通常,authID 是用户 ID 的大写版本。
- 连接到数据库之后执行 SQL 语句时的安全性考虑。
图 1 的左下部分展示了一条 SELECT 语句,该语句是在以 authID RAUL 连接到数据库 mydb 的情况下发出的。在这个例子中,内部的 DB2 安全性设施审核 DB2 编目表,以确认 authID RAUL 被授予对表 KEVIN.TABLE1 执行 SELECT 操作的权限,以此来执行授权(authorization) 检查。如果 authID RAUL 和 PUBLIC 没有被授予这种权限,DB2 将检查该用户是否为几个特殊的组(例如 SYSADM、SYSCTRL、SYSMAINT 或 SYSMON)的成员。对于这些组中的每一个组,都有数据库管理器配置(dbm cfg)参数,可以将这些参数设置为一个操作系统组的值。在连接时,DB2 从操作系统中获取用户的组信息,并缓存在内存中。然后,DB2 审核这个缓存的数据(II),以检查 authID RAUL 是否为这些组中某个组的成员。例如,如果 authID 是 SYSADM 组的成员,那么 SELECT 可以继续,否则将返回一条错误消息(SQLCODE -551)。
- 在客户机实施安全性时的安全性考虑。
在图 1 中,如果 AUTHENTICATION 被设置为 CLIENT,那么客户机上的操作系统将实施身份验证(III)。对于 SELECT 语句的授权检查将如前面所说的一样进行:DB2 从数据库的 DB2 编目表中检验 authID RAUL 是否有对 KEVIN.TABLE1 表的 SELECT 权限。如果 authID RAUL 和 PUBLIC 没有该权限,将进行组成员检查。在连接时,DB2 从客户机获得组成员信息,并缓存在服务器上。
- 发出实例级命令时的安全性考虑。
在图 1 中的服务器上,DB2 实例所有者 db2inst1 发出命令 db2stop。DB2 检查当前登录进来的用户是否属于 SYSADM_GROUP、SYSCTRL_GROUP 或 SYSMAINT_GROUP 中定义的组。(IV)如果用户 ID 属于以上任何一个组,那么 db2stop 命令将得以执行。否则,将返回一条错误消息。取决于实例级操作,用户可能必须属于 SYSADM、SYSCTRL、SYSMAINT 或 SYSMON 中的一个组。
在以上每个场景中,都调用了操作系统来进行安全性检查。而从 8.2 版开始,以上每种情况都可以使用安全性插件。因而,不必总是调用操作系统,在场景 1 中可以调用服务器和组插件,在场景 2 中可以调用组插件,在场景 3 和场景 4 中可以调用客户机和组插件。
这个例子介绍了三种类型的安全性插件:
- 服务器端身份验证安全性插件(即服务器身份验证插件)
- 客户端身份验证安全性插件(即客户机身份验证插件)
- 组成员查找安全性插件(即组插件)
服务器身份验证插件在数据库服务器上执行身份验证。它还用于检查一个 authID 是否为插件所知。例如,考虑 SQL 语句 grant select on table user1.t1 to FOO,DB2 不知道 FOO 是用户还是组。在这种情况下,DB2 询问所有服务器端插件和组成员插件,以检查 FOO 是用户还是组,或者两者都是,或者无法确定,从而可以对该 SQL 语句作出响应。
客户机身份验证插件在客户机上执行身份验证。在执行实例级命令(例如 db2start、db2stop、db2trc、update dbm cfg 等)时,它还用于执行实例级本地授权。因此,常常可以看到在一个数据库服务器上同时指定了客户机身份验证插件和服务器身份验证插件。
组插件在客户机和数据库服务器上执行组成员查找。它还用于检查一个 authID 是否为插件所知。
每个安全性插件由一组 API 组成,需要实现这些 API。DB2 提供安全性插件基础设施和一些缺省的安全性插件。定制的安全性插件的实现则有待您来决定。
使用安全性插件的优点
使用新的 DB2 UDB 安全性机制的主要优点是安全性插件能提供灵活性和可扩展性。不必依赖于操作系统之类的标准设施,相反,可以定制安全性机制以满足自己的需求。例如,在 8.2 版之前,任何登录进系统的操作系统用户都可以发出一条连接语句,而不必传递用户 ID 和密码(即所谓的隐式连接),并假定用户 ID 有 DB2 CONNECT 权限,他可以成功地完成连接。有了安全性插件之后,就可以改变这种行为,从而禁止隐式连接。
另一个例子是 LDAP。在 DB2 UDB 中,LDAP 目前不是受支持的身份验证方法。但是,可以用一个安全性插件来实现它。一个简单的例子是,使用 Microsoft Active Directory 实现基于 LDAP 的身份验证,本文后面会讲到这个例子。
安全性插件是按每个实例实现的,因此可以创建不同的实例,使用不同的安全性插件实现。图 2 展示了安全性插件所提供的灵活性和可扩展性。
图 2. DB2 安全性插件:灵活性和可扩展性
缺省安全性插件
安装或迁移到 DB2 UDB version 8.2 之后,不需要编写自己的安全性插件或者执行任何安装过程。缺省情况下,DB2 UDB 被配置为使用附带的缺省安全性插件。这些缺省安全性插件调用操作系统的安全性 API,所以缺省安全性行为与之前的 DB2 UDB 版本中的安全性行为是一样的。
图 3 展示了 DB2 附带的缺省插件,以及它们在 Windows 系统上的位置。
图 3. 缺省安全性插件库在 Windows 上的目录结构
图 3 中每个窗口中的右面板展示了不同的缺省插件。下面的表 1 对每个插件做了描述。
表 1. IBM DB2 缺省插件
| 插件名称 | 描述 |
|---|
| 1 | IBMOSauthclient | 这是客户端基于操作系统的身份验证插件 | | 2 | IBMOSauthserver | 这是服务器端基于操作系统的身份验证插件 | | 3 | IBMOSgroup | 这是基于操作系统的组成员插件 | | 4 | IBMkrb5 | 这是 Kerberos 安全性插件(它在同一个库内同时具有客户端和服务器端代码) |
图 3 中任何有后缀 “TwoPart” 的插件与没有该后缀的插件实现的是相同的身份验证方法,但是它添加了用于处理双节式 authID 的功能。双节式 authID 允许使用名称空间 [c1],这样一来,多个帐户可以使用相同的 authID,只要它们在不同的名称空间中就行了。例如,对于可以处理双节式 authID 的插件,DOMAIN1\SUSHMA 和 DOMAIN2\SUSHMA 都是有效的 authID。这个例子中的名称空间是 DOMAIN1 和 DOMAIN2(在 Windows 中,它通常是 Windows 域)。
如果不想使用缺省插件,那么既可以编写自己的安全性插件,也可以从第三方供应商购买安全性插件。无论选择哪种方法,都需要遵从 DB2 UDB 设立的规则来编写安全性插件。后面有一个小节会对此进行详细的讨论。
用户 ID/密码插件与 GSS-API 插件
在开始开发自己的插件之前需要理解,使用插件的身份验证可以通过两种方式来进行:
- 使用基于用户 ID/密码的插件 —— 这意味着要将一个用户 ID 和密码传递给插件以供检查。这是一种更简单的实现,比较容易理解。但是,只有用户 ID 和密码被发送到服务器,并且只支持一个服务器插件或客户机插件。
-
使用基于 GSS-API 的插件 —— 这意味着身份验证使用 Generic Security Service Application Programming Interface (GSS-API) standard version 2,即 RFC 2743 和 2744 中说明的那个版本。GSS-API 是用于执行客户机 - 服务器身份验证的通用 API。GSS-API 是解决目前存在相似但不兼容的安全性服务的问题的标准。使用 GSS-API 的主要优点是,通过使用这种通用 API 编写代码,您的实现可以与不同的安全性系统互操作。Kerberos 和 PKI 已经支持 GSS-API,实际上,DB2 中的 DB2 Kerberos 身份验证是使用 GSS-API 模型实现的。
使用这种插件身份验证的另一个优点是,任何身份验证数据(包括二进制数据)都可以在客户机和服务器之间传递。身份验证是在客户机和服务器两端执行的,因此需要配置客户机和服务器,以便使用相同的 GSS-API 插件。为了配置客户机,只需将 GSS-API 插件复制到客户机插件目录。在服务器上,在 SRVCON_GSSPLUGIN_LIST 数据库管理器配置参数中指定一个有序的 GSS-API 插件列表。如果客户机上复制了不只一个 GSS-API 插件,那么服务器将根据这个有序列表来确定使用哪个插件。图 4 解释了这个概念。
图 4. 在客户机和服务器系统中指定的 GSS-API 插件
该图展示了三个使用不同 GSS-API 插件的 DB2 客户机,以及一个带有支持的 GSS-API 插件列表的 DB2 服务器。当客户机 #1 连接到服务器时,它将从左至右搜寻服务器的插件列表,直至找到与客户机的插件匹配的插件,然后使用这个插件。因此,对于这个客户机,它发现服务器支持的第一个插件是 ABC,它与 ABC.dll 相匹配,因此它选择这个插件。之后,即使插件 DEF 也受客户机和服务器的支持,也不必再进一步查找这个列表。对于客户机 #3,将返回一条错误(sqlcode -30082 reason code 15),因为客户机和服务器之间没有匹配的 GSS-API 插件。
一个 DB2 服务器实例只能支持一个用户 ID/密码身份验证模块,但是可以支持一组 GSS-API 插件。然而,一组插件中只能有一个插件是 Kerberos 插件。DB2 客户机应用程序也只能支持一个用户 ID/密码模块,但是可以与服务器协商支持一个特定的 GSS-API 插件。
GSS-API 插件比较复杂,您需要很好地理解重要的 GSS-API 概念。
定制安全性插件中提供的新特性
在 8.2 版引入新的安全性插件模型之后,可以:
- 在客户机上执行 userID、密码和名称空间的重新映射。这只适用于基于用户 ID/密码的插件。该特性尤其适用于由 Web 服务器和 DB2 客户机组成中间层的三层系统。示例 小节中的 例 1 给出了用户 ID、密码和名称空间重新映射的一个例子。在这个例子中,在发送连接请求到服务器之前,用户 sugsc1ch 和他的密码被客户机插件重新映射为用户 Newton 和他的密码。
- 在服务器上执行 authID 重新映射。该特性允许经过身份验证的不同用户 ID 共享数据库服务器上相同的授权 ID。在“示例”小节中,例 1 的测试演示了该特性。这个特性很有用,例如,如果一个部门有一些雇员要轮班,并且每天需要以相同的权限执行相似的任务,那么就可以使用该特性。通过使用该特性,可以完全独立地映射那些雇员,并使用与公共 authID 关联的权限来执行他们的任务。为了了解哪个雇员执行了哪个任务以及在何时执行,DB2 允许服务器端插件返回真实姓名,以便进行审计。要了解更多信息,请参考 db2secGetAuthid API 文档。
- 使用用户名称空间(例如,DOMAIN\user)。这在前面的 缺省安全性插件 中已经讨论过。
- 基于通信信息拒绝连接。如果想在一个特定的时候只允许部分 IP 地址登录进数据库,那么可以使用该特性。“示例”小节中的 例 2 说明了如何实现这一点。
创建 DB2 UDB 安全性插件的步骤
创建一个 DB2 UDB 安全性插件需要 6 个步骤。下面的几个小节将详细解释每个步骤:
- 将安全性插件的头文件包括到插件中:
- sqllib/include/db2secPlugin.h
- sqllib/include/gssapiDB2.h
注意:只有在实现基于 GSS-API 的安全性插件时才需要 gssapiDB2.h。
- 编写组成插件的 API。需要编写一个适当的初始化 API 和服务器、客户机或组插件所需的其他一些 API。
- 在返回 DB2 之前填充函数指针结构。
- 指出插件使用的插件 API 版本。
- 指出插件类型,例如用户 ID/密码、GSS-API、Kerberos。
- 编译插件源代码,并创建一个共享库。根据应用程序/服务器实例,编译为 32 位或 64 位。
- 将这个库放在适当的目录中。
- 通过更新数据库管理器参数,启用插件。
步骤 1:将安全性插件头文件包括到插件中
db2secPlugin.h 和 gssapiDB2.h 是实现定制安全性插件所需的两个头文件。只有在构建 GSS-API 插件时才需要 gssapiDB2.h 头文件。图 5 展示了在 Windows 系统上实现安全性插件所需的这两个头文件的位置。
图 5. Windows 系统上插件头文件的位置
步骤 2:编写组成插件的 API
根据创建的是服务器插件、客户机插件还是组插件,需要分别编写以下 API 来初始化插件:
- db2secServerAuthPluginInit
- db2secClientAuthPluginInit
- db2secGroupPluginInit
例如,可以这样编写 db2secServerAuthPluginInit API:
清单 1. db2secServerAuthPluginInit
SQL_API_RC SQL_API_FN db2secServerAuthPluginInit(
db2int32 version,
void* server_fns,
db2secGetConDetails* getConDetails_fn,
db2secLogMessage* logMessage_fn,
char** errormsg,
db2int32* errormsglen)
{
struct userid_password_server_auth_functions_1
*fns = (struct userid_password_server_auth_functions_1*) server_fns;
condetails_fn = getConDetails_fn;
logMessage_Fn = logMessage_fn;
fns->version = DB2SEC_API_VERSION;
fns->plugintype = DB2SEC_PLUGIN_TYPE_USERID_PASSWORD;
fns->db2secDoesAuthIDExist = &is_user;
fns->db2secFreeErrormsg = &free_error_message;
fns->db2secFreeToken = &free_token;
fns->db2secGetAuthIDs = &getauthids;
fns->db2secServerAuthPluginTerm = &terminate_plugin;
fns->db2secValidatePassword = &validatePassword;
/* Example on how to use logMessage_fn */
/* Will log the init successful information into db2diag.log at DIAGLEVEL 3 */
(logMessage_Fn)(DB2SEC_LOG_WARNING,
"db2secServerAuthPluginInit successful",
strlen("db2secServerAuthPluginInit successful"));
return DB2SEC_PLUGIN_OK;
} |
DB2 调用装载后的 db2secServerAuthPluginInit API 来初始化服务器插件库。前面的代码来自文件 txtserver.c,该文件在本文后面附带的 zip 文件中。
除了初始化函数外,还需为服务器、客户机和组插件实现一些插件 API。此外,还有一些用于用户 ID/密码身份验证和用于 GSS-API 身份验证的特定 API。图 6、图 7 和图 8 描述了这些函数的功能。
注意:DB2 UDB 手册有一节详细描述了如何开发安全性插件,并解释了安全性插件 API。那些细节超出了本文的范围。本节只简单地对插件 API 做一个概述。
图 6. 组成员查找插件
图 7. 客户机插件
图 8. 服务器插件
步骤 3:在返回 DB2 之前填充函数指针结构
函数指针返回指向您实现的特定插件库所需的所有 API 的指针。例如,对于组插件,它包含指向 db2secDoesGroupExist、db2secFreeErrormsg、db2secFreeGroupListMemory、db2secGetGroupsForUser 和 db2secPluginTerm API 的实现的指针。
本文后面附带的 zip 文件中的 txtgroup.c 文件提供了一个例子,演示如何填充组插件库的函数指针。下面是该代码的一个片段。
fns->version = DB2SEC_API_VERSION;
fns->db2secDoesGroupExist = &is_group;
fns->db2secFreeErrormsg = &free_error_message;
fns->db2secFreeGroupListMemory = &free_group_list;
fns->db2secGetGroupsForUser = &get_groups;
fns->db2secPluginTerm = &terminate_plugin;
|
步骤 4:编译插件源代码并创建一个共享库
编写好安全性插件后,根据 DB2 实例将其编译成 32 位或 64 位的文件。库的名称必须与插件名称相同。并且,库必须是有适当的特定于平台的扩展名的共享库。例如,如果插件的名称为 myPlugin,那么应使用下面的扩展名:
- myPlugin.dll(Windows)
- myPlugin.a(AIX)
- myPlugin.so(Linux、AIX、Sun Solaris、HP-UX)
- myPlugin.sl(HP-UX)
库必须是线程安全的(可重入的),并且必须使用 C 链接(至少对初始化函数要使用 C 链接)。
步骤 5:将库放入适当的目录
必须将安全性插件库放入特定的目录:
- Windows:
- sqllib\security\plugin\<instance name>\client
- sqllib\security\plugin\<instance name>\server
- sqllib\security\plugin\<instance name>\group
对于 IBM 提供的缺省插件:
- sqllib\security\plugin\IBM\client
- sqllib\security\plugin\IBM\server
- sqllib\security\plugin\IBM\group
- 32 位 Linux 和 UNIX:
- sqllib/security32/plugin/client
- sqllib/security32/plugin/server
- sqllib/security32/plugin/group
对于 IBM 提供的缺省插件:
- sqllib/security32/plugin/IBM/client
- sqllib/security32/plugin/IBM/server
- sqllib/security32/plugin/IBM/group
在 Linux 和 UNIX 中,对于 64 位库,也使用与前面类似的目录,只是要使用子目录名 security64,而不是 security32。在 Windows 64 位实例中,32 位和 64 位插件都在相同的目录中,但是 64 位插件将加上后缀 ‘64’,例如 myplugin64.dll。
注意:IBM 子目录(在插件目录下)是为 IBM 提供的缺省插件预留的。放在该目录中的任何其他定制的插件都将被忽略。
步骤 6:通过更新数据库管理器参数启用插件
在 8.2 版之前,authentication 数据库管理器配置参数指定位置和机制,通过它来执行 CONNECT/ATTACH、组查询和本地授权检查。而在 8.2 版中有更多的配置参数,从而为选择身份验证选项提供了更大的灵活性。
表 2 提供了应用于插件的数据库管理器配置参数列表,并解释了它们如何应用于安全性插件。
表 2. 安全性插件数据库管理器配置参数描述
| 参数名 | 描述 |
|---|
| 1 | 客户机用户 ID/密码插件(CLNT_PW_PLUGIN) | 如果这个值是在客户机上设置的,并且服务器上的 AUTHENTICATION 参数被设置为 CLIENT,那么该参数指定用于在客户机上执行的身份验证的用户 ID/密码插件。如果这个值是在服务器上设置的,那么该参数指定用于实例操作(例如 db2start)授权检查的用户 ID/密码插件。在数据库服务器上本地发出的数据库连接(本地连接)期间,也可以在数据库服务器上使用客户端插件 | | 2 | 客户机 Kerberos 插件(CLNT_KRB_PLUGIN) | 该参数的值指定用于客户端身份验证和本地授权的 Kerberos 插件库的名称。当使用 KERBEROS 或 KRB_SERVER_ENCRYPT 身份验证对客户机进行身份验证时,将使用该插件。在 Windows 上缺省值是 IBMkrb5。在其他平台上,缺省值是 NULL | | 3 | 组插件(GROUP_PLUGIN) | 该参数的值指定用于组成员查找的组插件库 | | 4 | 用于本地授权的 GSS-API 插件(LOCAL_GSSPLUGIN) | 当数据库管理器配置参数 AUTHENTICATION 的值被设置为 GSSPLUGIN 或 GSS_SERVER_ENCRYPT 时,该参数的值指定用于实例级本地授权的 GSS-API 插件库的名称。
GSSPLUGIN 表明服务器将只使用基于它熟悉的 GSS-API 插件进行身份验证。
GSSPLUGIN_SERVER_ENCRYPT 表明服务器将另外接受加密的用户 ID/密码请求。这种类型主要是为向下兼容而提供的 | | 5 | 服务器插件模式(SRV_PLUGIN_MODE) | 该参数指定以 fenced 还是 unfenced 模式运行。缺省值(惟一受支持的值)是 UNFENCED | | 6 | 服务器 GSS-API 插件列表(SRVCON_GSSPLUGIN_LIST) | 该参数指定数据库服务器支持的 GSS-API 插件库的列表,列表中以逗号作为分隔符。这个列表只能包含一个 Kerberos 插件。如果该参数值没有设置,并且 AUTHENTICATION 被设置为 KERBEROS 或 KRB_SVR_ENCRYPT,那么将使用缺省的 DB2 Kerberos 插件(IBMkrb5) | | 7 | 服务器用户 ID/密码插件(SRVCON_PW_PLUGIN) | 该参数的值指定用于服务器端身份验证的用户 ID/密码插件库 | | 8 | 服务器连接身份验证(SRVCON_AUTH) | 该参数的值只用于连接。它覆盖 AUTHENTICATION 中指定的身份验证方法。本地实例操作仍使用 AUTHENTICATION 中指定的操作。缺省值是 NOT_SPECIFIED | | 9 | 数据库管理器身份验证(AUTHENTICATION) | 该参数的值指定为了检查本地实例授权,用户身份验证如何进行,在哪里进行。缺省值是 SERVER |
表 3 展示了使用前面列出的配置参数启用用户 ID/密码身份验证插件的步骤。
表 3. 启用用户 ID/密码身份验证插件的步骤
| 客户机上的步骤 | 服务器上的步骤 |
|---|
| 1 | 用客户机插件的名称更新 CLNT_PW_PLUGIN。
如果 CLNT_PW_PLUGIN 为空,那么将使用它的缺省值 IBMOSauthclient,这是 IBM 提供的插件 | 用服务器插件的名称更新 SRVCON_PW_PLUGIN | | 2 |
| 将 SRVCON_AUTH 设置为一种系统身份验证类型(CLIENT、SERVER、SERVER_ENCRYPT、DATA_ENCRYPT 或 DATA_ENCRYPT_CMP),或将 SRVCON_AUTH 设置为 NOT_SPECIFIED 并将 AUTHENTICATION 设置为一种系统身份验证类型。
如果 SRVCON_PW_PLUGIN 为空,那么将使用它的缺省值 IBMOSauthserver,这是 IBM 提供的插件 |
表 4 展示了使用前面列出的配置参数启用组成员查找插件的步骤。
表 4. 启用组成员查找插件的步骤
| 客户机上的步骤 | 服务器上的步骤 |
|---|
| 1 | 用组插件的名称更新 GROUP_PLUGIN。
如果 GROUP_PLUGIN 为空,那么将使用它的缺省值 IBMOSgroups,这是 IBM 提供的插件 | 用组插件的名称更新 GROUP_PLUGIN。
如果 GROUP_PLUGIN 为空,那么将使用它的缺省值 IBMOSgroups,这是 IBM 提供的插件 |
表 5 展示了使用前面列出的配置参数启用 GSS-API 身份验证插件的步骤。
表 5. 启用 GSS-API 身份验证插件的步骤
| 客户机上的步骤 | 服务器上的步骤 |
|---|
| 1 | 将插件库放在客户机插件目录中 | 将插件库放在服务器插件目录中 | | 2 | 可选:编目(catalog)一个数据库表明客户机将只使用一个 GSS-API 插件进行身份验证。例如:db2 catalog db testdb at node testnode authentication gssplugin。
一个客户机上可以同时存在多个插件。在这种情况下,服务器将指出使用哪个插件 | 用受支持的插件名称的有序列表更新 SRVCON_GSSPLUGIN_LIST。为了启用 GSS-API 插件,可以:
- 将 SRVCON_AUTH 设置为 GSSPLUGIN,或者
- 将 SRVCON_AUTH 设置为 NOT_SPECIFIED,并将 AUTHENTICATION 设置为 GSSPLUGIN。
为了启用本地授权:
- 将客户机插件库放入客户机插件目录。
- 用插件名称更新 LOCAL_GSSPLUGIN。
|
表 6 展示了使用前面列出的配置参数启用 Kerberos 身份验证插件的步骤。
表 6. 启用 Kerberos 插件的步骤
| 客户机上的步骤 | 服务器上的步骤 |
|---|
| 1 | 将插件库放在客户机插件目录 | 将插件库放在服务器插件目录 | | 2 | 用 Kerberos 插件的名称更新 CLNT_KRB_PLUGIN。
- 如果 CLNT_KRB_PLUGIN 为空,那么 DB2 认为客户机不能使用 Kerberos。
- DB2 提供的缺省 Kerberos 插件被命名为 IBMkrb5。
- 对于支持 Kerberos 的平台,IBMkrb5 库已经在客户机插件目录中。
| 用服务器 Kerberos 插件名称更新 SRVCON_GSSPLUGIN_LIST | | 3 | 可选:编目一个数据库表明客户机将使用 Kerberos 插件进行身份验证。例如:db2 catalog db testdb at node testnode authentication kerberos target principal service/host@REALM | 将 SRVCON_AUTH 设置为 KERBEROS 或 KRB_SERVER_ENCRYPT,或将 SRVCON_AUTH 设置为 NOT_SPECIFIED 并将 AUTHENTICATION 设置为 KERBEROS 或 KRB_SERVER_ENCRYPT |
演示如何实现简单安全性插件的示例
本文附带的 zip 文件包括本节使用插件的源代码和一个 README 文件,该文件包含关于这些插件的更多信息。
例 1:实现一个简单的用户 ID/密码安全性插件
需要的文件:txtserver.c、txtclient.c、txtcommon.c 和 txtplugin_makefile。
需要实现一个服务器端插件和一个客户端插件。
- 打开 txtcommon.c,修改下面这一行代码,使之包括用户 ID 和密码。authID 继续保留为 REMAP。将
myuserid 改为您的用户 ID,将 er9etw0 改为您的密码。
{ 0, 0, "REMAP", "REMAP", "myuserid", "er9etw0", "build" }
- 在 C:\...\sqllib\security\plugins 目录下创建一个子目录,以您的实例名来命名这个新目录。
- 在前一步创建的子目录中创建两个分别名为 client 和 server 的子目录。
- 从 DB2 Command Window 发出以下命令,以创建 noplatos 和 sample 数据库。
db2start
db2 create db noplatos
db2sampl
db2stop
- 将文件 txtplugin_makefile 重命名为 makefile 文件。
- 发出以下命令,编译 txtserver.c:
nmake /f makefile txtserver
将生成的 txtserver.dll 复制到 C:\...\sqllib\security\plugins\<instance_name>\server 目录,以使 DB2 能找到它。
- 从 DB2 Command Window 发出以下命令,以更新数据库管理器配置参数:
db2 update dbm cfg using srvcon_auth server srvcon_pw_plugin txtserver
- 从 DB2 Command Window 发出以下命令,以确保配置更改生效:
db2 terminate
db2stop
db2start
- 现在,可以开始测试服务器端用户 ID/密码身份验证插件。从 DB2 Command Window 发出以下命令/语句。
db2 connect to sample user <your user ID> using <your password>
该语句应该返回用户 ID 的 authID 映射。db2secGetAuthIDs API 从 txtcommon.c 中的表中获取 authID。应该可以得到如图 9 所示的输出:
图 9. 测试 db2secGetAuthIDs API
db2 connect to noplatos user plato using er9etw0
该语句将失败,并返回 sqlcode 30082 reason code 25。如果调用服务器端插件进行身份验证,则用户 ID plato 不能访问 noplatos 数据库。这是因为 txtserver.c 中的 validatePassword 函数限制了用户 plato 对 noplatos 数据库的访问。
db2 connect to sample user plato using er9etw0
该语句将成功。当调用服务器端插件进行身份验证时,用户 ID plato 可以访问 noplatos 之外的数据库。图 10 展示了这种情况下的输出。
图 10. 展示 plato 不能访问 noplatos 的测试
- 发出以下命令来编译 txtclient.c
nmake /f makefile txtclient
将生成的 txtclient.dll 复制到 C:\...\sqllib\security\plugins\<instance_name>\client 目录,以便 DB2 能找到它。
- 从 DB2 Command Window 发出以下命令,以更新数据库管理器配置参数:
db2 update dbm cfg using srvcon_auth client clnt_pw_plugin txtclient
- 从 DB2 Command Window 发出以下命令,以确保配置更改生效:
db2 terminate
db2stop
db2start
- 现在可以开始测试客户端用户 ID/密码身份验证插件。从 DB2 Command Window 发出以下命令。
db2 connect to sample user sugsc1ch using cdsecpwd
首先调用 db2secRemapUserid API,接着将用户 sugsc1ch 和密码 cdsecpwd 重新映射为用户 newton 和密码 er9etw0,然后使用 newton 的 authID 连接到数据库。该功能是在 txtclient.c 中的 remap_userid 函数中实现的,如下所示:
/* remap the userid sugsc1ch to newton */
else if (!strncmp("sugsc1ch", userid, 8) &&
!strncmp("cdsecpwd", password, 8))
{
/* this is for testing purposes only: userid sugsc1ch/cdsecpwd
normally has no priviliges, but I am going to remap it to
newton/er9etw0 so that it will be allowed to connect if
server plugin is txtserver, and fail if the os plugin is used */
strcpy(userid, "newton");
strcpy(password, "er9etw0");
*useridlen = strlen(userid);
*passwordlen = strlen(password);
} |
该语句将成功,输出如图 11 所示。
图 11. 测试 db2secRemapUserid API
db2 connect to noplatos user plato using er9etw0
该语句将成功,因为对用户 ‘plato’ 连接到 ‘noplatos’ 的限制是在服务器端插件中实现的,而不是在客户端插件中实现的。
db2 connect to sample
该语句将成功。它调用 db2secGetDefaultLoginContext API 获得调用连接的用户的 authID,并使用它连接到数据库 sample。
例 2:实现一个简单的组安全性插件
需要以下文件:txtgroup.c、txtserver.c、txtclient.c、txtcommon.c 和 txtplugin_makefile。
这个例子以 例 1 为基础,所以在进行后面的步骤之前,先执行例 1 中的步骤。
- 在例 1 的步骤 2 中创建的 “DB2” 子目录下创建一个名为 “group” 的子目录。
- 发出以下命令来编译 txtgroup.c
nmake /f makefile txtgroup
将生成的 txtgroup.dll 复制到 C:\...\sqllib\security\plugins\<instance_name>\group 目录,以便 DB2 能找到它。
- 从 DB2 Command Window 发出以下命令,以更新数据库管理器配置参数:
db2 update dbm cfg using srvcon_auth server
db2 update dbm cfg using srvcon_pw_plugin txtserve
db2 update dbm cfg using sysadm_group build
db2 update dbm cfg using group_plugin txtgroup
- 从 DB2 Command Window 发出以下命令,以确保配置更改生效:
db2 terminate
db2stop
db2start
- 现在可以开始测试组插件。从 DB2 Command Window 发出以下命令/语句(注意:用户
newton 属于组 build,这是 sysadm 组 ,user2 属于组 doody 和一些其他的组)。
db2 connect to sample user newton using er9etw0
db2 "create table t1 (x int)"
db2 terminate
图 12 展示了这一步的输出:
图 12. 测试 newton 的组从属关系和授权
db2 connect to sample user user2 using er9etw0
db2 "select * from newton.t1"
db2 terminate
图 13 展示了这一步的输出:
图 13. 测试 user2 的授权
db2 connect to sample user newton using er9etw0
db2 grant select on t1 to group doody
db2 terminate
图 14 展示了这一步的输出:
图 14. 测试 newton 的授权以便授予权限
db2 connect to sample user user2 using er9etw0
db2 "select * from newton.t1"
db2 terminate
图 15 展示了这一步的输出:
图 15. 测试 user2 刚被授予的权限
测试插件的连接限制能力的步骤
这次将测试所有三个(服务器、客户机和组成员查找)插件。
添加以下几行到 C:\windows\system32\drivers\etc\services 文件中:
xregress 23542/tcp
xregress_int 23543/tcp
从 DB2 Command Window 发出以下命令,如图 16 所示:
db2 terminate
db2stop
db2 update dbm cfg using clnt_pw_plugin txtclient srvcon_pw_plugin txtserver group_plugin txtgroup sysadm_group build
db2set DB2COMM=TCPIP
db2 update dbm cfg using svcename xregress
db2 catalog tcpip node thisnode remote <your machine name> server xregress
db2 catalog db sample as loopback at node thisnode
db2 terminate
db2start
图 16. 设置连接限制能力
上述步骤让您回调 DB2 来获得客户机 IP 地址。然后,可以添加需要的逻辑,并阻塞不符合上述模式的连接。
现在,如果发出 db2 connect to loopbackdb user beauvoir using er9etw0,应该可以得到如图 17 所示的输出。
图 17. 测试连接限制能力
前面的场景调用 txtserver.c 中的 validatePassword 函数(对应于 db2secValidatePassword API)。该函数的实现表明,如果用户 id beauvoir 试图从一个与数据库服务器有相同 IP 地址的远程客户机进行连接,那么就阻塞它。在实际情况中,会编写 validatePassword 函数,以便得到允许的 IP 地址或不允许的 IP 地址的列表,并在阻塞一个特定用户对数据库的访问之前核对这个列表。
例 3:实现一个基于 Active Directory 的插件
需要的文件:ldap.c,ldap_makefile。
Active Directory 是 Microsoft 的 LDAP 服务器的实现,存在于所有域控制器上。它包含域帐户、组和计算机信息。Active Directory 支持 LDAP v2 和 v3 API 集。这个例子将使用 LDAP_VERSION3。
这个例子假设您理解 LDAP 的基本概念,并知道如何设置 Active Directory。serverwatch.com 教程 “Quick Start Guide to Setting up Active Directory”(参见 参考资料)提供了很好的参考资料。
当应用程序使用 LDAP 服务器进行身份验证时,它通常使用绑定来与服务器通信,而通过解除与服务器的绑定来关闭连接。
通常,在使用 Active Directory 进行身份验证的过程中,应用程序采取的 4 个步骤是:
- 打开到 LDAP 服务器的一个连接。
- 在 LDAP 服务器上身份验证。
- 执行一些操作,例如获取搜索结果。
- 关闭连接。
这个例子插件使用以下 API 函数:
- ldap_init —— 初始化到 LDAP 服务器的连接。
- ldap_connect —— 连接到一个 LDAP 服务器。
- ldap_bind_s —— 同步地绑定到 LDAP 服务器。
- ldap_unbind_s —— 关闭到 LDAP 服务器的连接。
这个例子是一个服务器端身份验证插件,用于在 LDAP 服务器上验证用户 ID 和密码。
这个例子假设 LDAP 服务器的 IP 地址为 199.43.208.178,端口号为 389。所有 4 个步骤都是在 db2secValidatePassword 中实现的。
db2secValidatePassword 中的步骤:
- 使用 LDAP 服务器的缺省端口和 IP 地址调用 ldap_init。
- 调用 ldap_set_option 将协议版本设置为 LDAP_VERSION3。
- 使用 ldap_connect 连接到 LDAP 服务器。
- 在绑定到 LDAP 服务器之前,必须将 Microsoft Security Accounts Manager(SAM)帐户名形式(可以带有名称空间)转换成 LDAP 专有名格式。专有名的一个例子是 “cn = Il-Sung Lee, o = Microsoft, cn = US”。如果在连接时使用的用户 ID 字符串中没有包括名称空间,则需要调用 Windows API 函数 LookupAccountNameA 来找到这个用户 ID 所在的名称空间。具备了名称空间和用户 ID 之后,调用 Windows API 函数 TranslateNameA 来执行上述转换。
- 绑定到 LDAP 服务器。这里使用的身份验证方法是 LDAP_AUTH_SIMPLE。如果用户提供的密码与对应于专有名的 LDAP 服务器密码相匹配,则绑定函数将返回 LDAP_SUCCESS。否则,绑定函数可以返回 Microsoft Developer Network 上列出的一组返回代码之一(请参阅 参考资料)。
- 使用 ldap_unbind 关闭到 LDAP 服务器的连接。
其他所需的安全性插件 API 调用都很容易实现,它们类似于简单的用户 ID/密码身份验证插件。本文不会再对它们进行详细的讨论。
还应注意,DB2 允许本地连接在没有用户 ID 和密码的情况下也能获得成功。这就是所谓的隐式连接。在隐式连接中,DB2 将提供当前登录进的用户细节给服务器端安全性插件。为确定哪个用户是当前登录进来的用户,DB2 调用服务器端身份验证插件 API 函数 db2secGetDefaultLoginContext。在这个例子中,我们将按缺省情况调用 IBM 提供的客户端插件来做这个工作。
为了使该插件能处理这种情况,在调用 ldap_init之前,还需要多执行一个步骤。使用 DB2 提供的 “get client connection details” 回调函数,以发现客户机是否在该计算机本地。处理这种工作的代码如下所示。
rc = pConDetails( DB2SEC_API_VERSION, &conDetails);
if( rc == DB2SEC_PLUGIN_OK )
{
if( ( conDetails.connect_info_bitmap & DB2SEC_CONNECTION_ISLOCAL )
&& ( conDetails.connect_info_bitmap &
(DB2SEC_VALIDATING_ON_SERVER_SIDE ) && ( passwordlen == 0 ) )
{
goto exit;
}
} |
为了编译和构建这个插件库,可以使用后面下载中提供的 ldap_makefile。将它重命名为 makefile,并从 sqllib\samples\security\plugins 目录复制 bldplugin.bat。发出 make ldap 命令,该命令将使用该 makefile 和 bldplugin.bat 来构建库。
通过执行以下步骤来使用这个简单的基于 LDAP 的服务器端用户 ID/密码身份验证插件:
为了设置服务器端插件:
- 将 LDAP 插件库安装在本文前面提到的适当位置。
- 用 LDAP 插件的名称更新 srvcon_pw_plugin 参数。
- 将 srvcon_auth 参数或 AUTHENTICATION 数据库管理器配置参数设置为 server。
为了设置客户端插件:
- 登录到域中。
- 将数据库管理器配置参数 clnt_pw_plugin 更新为 NULL,以使用缺省的由 IBM 提供的客户端身份验证插件。
如果您计划在数据库服务器本地测试该插件,那么必须也在数据库服务器上执行客户端设置。其原因是,对于本地授权,这个例子使用数据库服务器上的客户机插件。因此,应该有一个适当类型的客户机版本的插件,从而与数据库管理器配置参数 AUTHENTICATION 指定的值相对应。例如,如果有一个数据库服务器,其上的身份验证被指定为 kerberos,那么就需要确保 clnt_krb_plugin 被设置为 IBMkrb5(IBM 提供的 Kerberos 插件)或 Kerberos 插件的名称。还需要确保该插件被安装到数据库服务器上的客户机插件目录下。否则,诸如 db2start 之类的实例级操作将失败。
在客户机和数据库服务器上都设置好插件之后,发出一条连接语句以测试插件。
例 4:通过 Kerberos 插件来进一步解释 GSS-API 标准的 DB2 实现和特定于 DB2 的扩展
Kerberos 是一种第三方网络身份验证协议,它采用一个带共享密钥的系统来对不安全的网络环境中的用户安全地进行身份验证。它使用一种三层系统,在这种系统中,应用服务器与客户机之间交换加密的标签(由一个单独的名为 Kerberos Key Distribution Center 的服务器提供,该服务器的简称为 KDC),而不是交换文本形式的用户 ID 与密码对。这些加密的服务标签(凭证)只有客户机和服务器能理解,所以即使标签在网络中被拦截,安全风险也很小。
Kerberos 的一个关键特性是它支持单点登录环境,在这种环境中,用户只需向 Kerberos 域中的资源做一次身份证明。在 DB2 中,这意味着用户可以在不提供用户 ID 或密码的情况下连接到 DB2 服务器。单点登录连接是客户经常要求的一个特性,目前 DB2 还不能提供(客户机身份验证通常不必考虑,因为这对客户来说通常不可行)。使用 Kerberos 的另一大原因是,它可以提供对用户 ID(或主体)的集中式存储,从而集中和简化主体管理。而且,Kerberos 支持相互的身份验证,这样一来,客户机也可以验证服务器的身份。
在 8.2 版中,由于有了新的 DB2 安全性插件范型,Kerberos 支持将以 GSS-API 插件的形式提供。已有的 Windows 2000 支持被重新实现成 GSS-API 插件的形式,另外还有三个平台也将受支持:AIX 5.2、Solaris 8 和 Red Hat Enterprise Linux Advanced Server 2.1。
图 18 解释了 Kerberos 如何工作的基本思想。
图 18. Kerberos 身份验证概述
本节的目的是通过 Kerberos 插件来演示基于 GSS-API 的身份验证插件的预期行为。对于 Kerberos,凭证被称作 Kerberos 标签。还有其他形式的凭证,这取决于特定的 GSS-API 实现。例如,在一个 Public Key Infrastructure(PKI)实现中,凭证是由 Certificate Authority(CA)或 Registration Authority(RA) 授予的一个证书。
GSS-API 身份验证的基本流程
表 7 简单地解释了在 GSS-API 身份验证过程中客户机 - 服务器之间的基本流程。注意,标志(token)是隐性二进制数据,只有底层安全性机制才需要能够解释它们。
表 7. GSS-API 身份验证过程中客户机 - 服务器之间的流程
| 客户机 |
| 服务器 |
|---|
| 1. 获得客户机的初始凭证(与 GSS-API 无关) |
| 1. 获得服务器的凭证(gss_acquire_cred) | | 2. 从服务器获得凭证(gss_init_sec_context) | --> | 3. 验证和接受客户机凭证(gss_accept_sec_context)。需要时返回相互身份验证标志 | | 4. 建立上下文或相互身份验证(gss_init_sec_context) | <-- | | 5. 删除上下文并进行清除 |
| 5. 删除上下文并进行清除 |
DB2 和 GSS-API —— 基本流程
表 8 展示了在 GSS-API 身份验证过程中涉及 DB2 时客户机 - 服务器之间流程中的步骤。服务器在插件初始化时(db2secServerAuthPluginInit)获得它的主体名和凭证句柄。注意,在服务器上,插件是在启动数据库管理器的操作(db2start)中一起装载和初始化的。
表 8. GSS-API 身份验证过程中涉及 DB2 时客户机 - 服务器之间的流程
| 客户机 |
| 服务器 |
|---|
- 必要时获得客户机的初始凭证(db2secGenerateInitialCreds),否则,获得缺省的登录上下文(db2secGetDefaultLoginContext)。
- 处理服务器主体名(db2secProcessServerPrincipalName)
- 从服务器获得凭证(gss_init_sec_context)
|
|
| | --> |
- 本地授权问题
- 获得初始化上下文的主体的 authID(db2GetAuthIDs),并通过调用组成员插件(db2secGetGroupsForUser)获得主体的组成员信息
|
- 需要时执行相互身份验证(gss_init_sec_context)
| <-- |
- 删除上下文(gss_delete_sec_context),并通过调用 gss_release_buffer、gss_release_name 和 db2secFreeToken 进行清除。如果用户 ID 和密码是显式指定的,在清除阶段还需调用 db2secFreeInitInfo
|
|
- 删除上下文(gss_delete_sec_context),并通过调用 db2secFreeToken 进行清除。还需调用组成员插件 API 函数 db2secFreeGroupList 来清除在调用函数获取组成员信息期间所分配的内存
|
在 sqllib/samples/security/plugins/IBMkrb5.c 目录下提供了用于 UNIX 和 Linux 的 Kerberos 插件,作为一个示例。
DB2 对 GSS-API 插件的限制
GSS-API 是 DB2 所支持的一个标准。但是,DB2 对于 GSS-API 函数的实现有一些限制。这些限制包括:
- 由于假定了缺省的安全性机制,因此不考虑 OID。
- gss_init_sec_context() 中需要的 GSS 服务只有相互身份验证和托管。DB2 要求使用一个标签来进行托管,但是不准使用那个标签来生成新的标签。
- 只需要缺省的上下文时。
- gss_delete_sec_context() 中的上下文标志不会从客户机发送到服务器,反之亦然。
- 不支持匿名。
- 不支持通道绑定。
- 如果初始凭证过期,DB2 不会自动为之延期。
- GSS-API 要求即使 gss_init_sec_context() 或 gss_accept_sec_context() 失败,也可以返回一个标志,以便发送到它的同位体。在这种情况下,必须发送一个标志。然而,由于 DRDA 框架中的限制,只有当 gss_init_sec_context() 失败并且在第一次调用时生成一个标志的情况下,才能做到这一点。
安全性插件在使用上的限制
- admin 服务器不支持插件。因此,任何通过 Control Center(或另一个 Center)并经由 admin 服务器(而不是通过一个数据库连接)的动作都将提示需要用户 ID 和密码,提供的用户 ID 和密码将在本地操作系统(在 Unix 上是 /etc/passwd)上被验证。不幸的是,当 Control Center 提示提供用户 ID 和密码时,它并不清楚用户名和密码是用于数据库连接还是用于连接到 admin 服务器,通常难于预测将来会使用哪一个。
- 对于 V8 FP11 之前的版本,Java client(JCC)不支持 GSS-API 插件。从 V8 FP11 以后,type 4 本地 Java 客户机可以实现一个 Java 版本的 GSS-API 插件。然而,对于 V8 FP11 之前的版本,type 4 驱动程序却支持 Kerberos。注意,JCC 客户机不支持定制的基于用户 ID/密码的安全性身份验证插件和定制的组查找安全性插件。
- 其他 DB2 产品(例如 Z-series、I-series 或 VM/VSE 上的 DB2)不支持任何形式的安全性插件。除了 Kerberos 之外,它们也不支持 GSS-API 插件身份验证方法。
- 安全性插件不能用于 Q 复制。
- DB2 附带的缺省插件不支持 LDAP 身份验证。因此,为了能够使用 LDAP 身份验证,需要编写自己的插件并启用它,以使 DB2 能够使用它。
现实生活中的场景
场景 1:未升级和升级的客户机对 GSS-API 插件的使用
您有很多客户机,其中一些是已经升级的,一些是未升级的,它们都要使用数据库服务器上的 GSS-API 插件。在使用 GSS-API 插件之前,它们使用客户机、服务器或 server_encrypt 身份验证。(下面的例子使用未升级的客户机 c1、V8.2 客户机 c2 和 V8.2 服务器 s1 来解释该场景)。
未升级的客户机 c1:
- 如果没有用身份验证客户机编目数据库,则不需要做任何事情。如果用身份验证客户机编目了数据库,则在不指定身份验证子句的情况下重新编目数据库,或者使用
server 或 server_encrypt 身份验证选项。
V8.2 客户机 c2:
- 将客户端 GSS-API 插件安装到客户机插件目录中。
V8.2 服务器 s1:
- 将服务器端 GSS-API 插件安装到服务器插件目录。
- 用受支持的 GSS-API 插件名称的有序列表更新数据库管理器配置参数 srvcon_gssplugin_list。注意,该列表要按优先顺序排列。
- 将数据库管理器配置参数 srvcon_auth 更新为 GSS_SERVER_ENCRYPT。这将使服务器能处理使用 GSS-API 插件的新客户机,并仍然使用 SERVER_ENCRYPT 来与其他不支持 GSS-API 插件的客户机(包括未升级的客户机)打交道。
场景 2:与在不同实例中有不同身份验证设置的数据库通信的 V8.2 客户机
该场景使用 V8.2 客户机(c1)和三个数据库(dbase1、dbase2 和 dbase3,分别属于实例 inst1、inst2 和 inst3)。
实例 inst1 要使用 srvcon_auth = server_encrypt。
- 将服务器端用户 ID/密码身份验证插件(例如,server_upw)安装到服务器插件目录。
- 用插件的名称更新数据库管理器配置参数 server_pw_plugin。
- 将数据库管理器配置参数 srvcon_auth 更新为 server_encrypt。
实例 inst2 要使用 srvcon_auth = kerberos。
- 将服务器端 Kerberos 插件(例如,krb)安装到服务器插件目录。
- 用服务器端 Kerberos 插件的名称更新数据库管理器配置参数 srvcon_gssplugin_list。
- 将数据库管理器配置参数 srvcon_auth 更新为 Kerberos。
实例 inst3 要使用 srvcon_auth = gssplugin。
- 将服务器端 GSS-API 插件(例如,krb、gss1 或 gss2 或者任意组合)安装到服务器插件目录。
- 用按优先顺序排列的服务器端 GSS-API 插件名称列表更新数据库管理器配置参数 srvcon_gssplugin_list。例如,如果优先顺序是 gss2、krb 和 gss1,则使用 srvcon_gssplugin_list 'gss2,krb,gss1' 更新数据库管理器配置参数。注意,krb 可以是来自 inst2 的同一个基于 Kerberos 的插件。由于 Kerberos 是使用 GSS-API 基础设施实现的,因此可以用作 GSS-API 插件。
- 将数据库管理器配置参数 srvcon_auth 更新为 gssplugin。
假设客户机要与所有三个实例中的数据库通信,则需要:
- 用客户端用户 ID/密码插件(例如,clnt_upw)更新数据库管理器配置参数 clnt_pw_plugin。
- 用客户端 Kerberos 插件(例如,krb)更新数据库管理器配置参数 clnt_krb_plugin。
- 安装客户端插件(clnt_upw、krb 和 gss2)。
- 编目数据库 dbase1(不指定身份验证,或指定 server_encrypt 身份验证)。
- 编目 dbase2(不指定身份验证,或指定 kerberos 身份验证)。
- 编目 dbase3(不指定身份验证,或指定 gssplugin 身份验证)。
- 发出语句 ‘connect to dbase1 user <user ID> using <password>’
该连接将使用 server_encrypt;在客户机上,它使用 clnt_upw(来自 clnt_pw_plugin);在服务器上,它使用 server_upw(来自 server_pw_plugin)。
- 发出语句 ‘connect to dbase2 user <user ID> using <password>’
该连接将使用 Kerberos;在客户机上,它使用 krb(来自 clnt_krb_plugin);在服务器上,它使用 krb(来自 rvcon_gssplugin_list)。
- 发出语句 ‘connect to dbase3 user <user ID> using <password>’
该连接将使用 gssplugin;在客户机上,虽然 gss2 和 krb 都在列表中,它仍然选择 gss2;srvcon_gssplugin_list 表明了优先顺序。然后,客户机通知服务器使用 gss2。这样一来,客户机和服务器都将使用 gss2。
注意,与用户 ID/密码插件不同的是,基于 GSS-API 的插件在客户机和服务器上的名称必须相同。
使用安全性插件的常见问题
本节提供关于调试与安全性插件相关问题的提示:
检查管理日志中与安全性插件相关的消息。在 UNIX 上,检查 sqllib/db2dump/<instance name>.nfy。在 Windows 上,则使用 Event Viewer 来查看 Windows 事件日志。
表 9 列出了与安全性插件相关的管理日志值。
表 9. 与安全性插件相关的管理日志值
| 日志值 | 原因 |
|---|
| 13000 | 对 GSS-API 安全性插件 API 的调用失败,并返回一个错误 | | 13001 | 对 DB2 安全性插件 API 的调用失败,并返回一个错误 | | 13002 | DB2 卸载插件失败 | | 13003 | 主体名无效 | | 13004 | 插件名称无效 | | 13005 | DB2 装载插件失败 | | 13006 | 遇到意外的插件错误 |
检查错误消息和相关的 SQLSTATE 值,以便根据消息做出诊断。任何与安全性插件相关的消息都有以下 SQLCODE 值:
表 10. 与安全性插件相关的 SQLCODE
| SQLCODE | 原因 |
|---|
| -1365 | db2start 或 db2stop 期间的插件错误 | | -1366 | 本地授权问题 | | -30082 | 与连接相关的插件错误 |
如果是在 Windows 64 位平台上使用插件,并且看到插件装载错误,那么应确保 64 位插件库的库名上有 ‘64’ 后缀,而数据库管理器配置参数没有这个后缀。记住,32 位应用程序必须使用 32 位的插件,而 64 位应用程序必须使用 64 位的插件。
此外,还可能遇到由于安全性插件的限制而引起的错误。请参考 限制 小节,以确保操作不在 DB2 限制的安全性插件操作的范围内。
结束语
本文对安全性插件进行了概述,首先提到了安全性插件的优点,以及安全性插件与标准安全性设施相比的优势。本文详细解释了 DB2 支持的不同类型的插件,以及如何启用这些插件。文中给出了一系列的例子,使您亲历不同类型的安全性插件的创建过程,另外后面的 下载 小节还提供了这些例子的代码。通过本文还可以了解安全性插件的一些限制,使用安全性插件时可能遇到的一些常见问题,从而有助于您在实现自己的安全性插件时调试问题。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Sample code for this article | security.zip | 16KB |
FTP | HTTP |
|---|
参考资料
作者简介  | |  | Kevin See, CISSP 是 IBM 多伦多实验室的一名专职软件开发人员,在 Kernel 小组从事 DB2 FVT 方面的工作。在此之前,他在 DB2 Security Development 小组和 DB2 SQL and Catalog Development 小组工作。他在 IBM 已经工作了 9 年,目前主要的工作范围是访问控制和身份验证模型。他拥有滑铁卢大学的数学(软件工程)硕士学位,同时还拥有阿卡迪亚大学的计算机科学学士学位。他是 IBM 认证的 XML 及相关技术解决方案开发人员,同时也是 DB2 认证的解决方案专家(DBA for OS/390、DBA for Linux/Unix/Windows 和 DB2 Family Application Development)。他还是 ISC2 认证的信息系统安全专家。 |
 | |  | Sushma Narisetty 是多伦多大学电子工程系大四的学生。她曾在 IBM 多伦多实验室担任信息开发人员,后因返校完成学位而离开那里。她是 IBM 认证的数据库管理员和 DB2 Universal Database V8.1 for Linux、UNIX 和 Windows 应用程序开发人员。 |
 | 
|  | Raul F. Chong 是 IBM 多伦多实验室的数据库专家,在 DB2 UDB 技术支持部工作。Raul 已经在 IBM 工作了 8 年,有丰富的 DB2 UDB 方面的知识。Raul 撰写了很多文章,您可以通过 rfchong@ca.ibm.com 与他联系。 |
 | |  | Il-Sung Lee, P.Eng 是 Microsoft SQL Server 的程序经理。他曾在 IBM 多伦多实验室担任专职软件工程师,在加入 Microsoft 之前,在 IBM 工作了 7 年。他曾是 DB2 Security Development 小组的成员,在那里负责的相关领域包括 Kerberos、身份验证模型和代码漏洞利用。他拥有麦吉尔大学工程硕士学位,同时还拥有不列颠哥伦比亚大学的学士学位,专业都是电子工程。 |
对本文的评价
|