面向开发者的 Oracle® Solaris 11 安全性指南

退出打印视图

更新时间: 2014 年 7 月
 
 

SASL 插件概述

SASL 服务提供者接口 (Service Provider Interface, SPI) 可实现插件与 libsasl 库之间的通信。SASL 插件通常作为共享库来实现。单个共享库可以具有一个或多个不同类型的 SASL 插件。位于共享库中的插件是由 libsasl 通过 dlopen (3C) 函数动态打开的。

还可以将插件静态绑定至调用 libsasl 的应用程序。使用 sasl_client_add_plugin() 函数或 sasl_server_add_plugin() 函数装入这些种类的插件,具体视应用程序是客户机还是服务器而定。

    Oracle Solaris 操作系统中的 SASL 插件具有以下要求:

  • 共享库中的插件必须位于有效的可执行目标文件(文件扩展名最好是 .so)中。

  • 插件必须位于可验证的位置中。SASL_CB_VERIFYFILE 回调用于验证插件。

  • 插件必须包含正确的入口点。

  • SASL 客户机的插件版本必须与 SASL 服务器的对应插件版本匹配。

  • 插件需要能够成功初始化。

  • 二进制类型的插件必须与 libsasl 的二进制类型匹配。

    SASL 插件分为四种类别:

  • 客户机机制插件

  • 服务器机制插件

  • 标准化插件

  • Auxprop 插件

sasl_client_init() 函数导致 SASL 客户机装入所有可用的客户机插件。sasl_server_init() 函数导致 SASL 服务器装入服务器插件、标准化插件和 auxprop 插件。调用 sasl_done() 时将卸载所有插件。

为查找插件,libsasl 使用 SASL_CB_GETPATH 回调函数或缺省路径。SASL_CB_GETPATH 返回以冒号分隔的目录列表,以供在其中查找插件。如果 SASL 使用者指定了 SASL_CB_GETPATH 回调,则 libsasl 将使用返回的搜索路径。否则,SASL 使用者可以使用与二进制类型对应的缺省路径。

    下面列出了缺省路径和二进制类型对应关系:

  • 64 位 SPARC 体系结构:/usr/lib/sasl/sparcv9

  • x64 体系结构:/usr/lib/sasl/amd64

  • 32 位 SPARC 体系结构:/usr/lib/sasl

  • 32 位 x86 体系结构:/usr/lib/sasl

在装入过程中,libsasl 将调用最新支持的插件版本。插件将返回该版本以及描述该插件的结构。如果该版本合格,则 libsasl 即可装入该插件。当前版本号为 SASL_UTILS_VERSION。

初始化插件后,插件与 libsasl 之间的后续通信通过必须建立的结构执行。插件使用 sasl_utils_t 结构来调用 libsasl

    libsasl 库使用以下结构中的入口点与插件进行通信:

  • sasl_out_params_t

  • sasl_client_params_t

  • sasl_server_params_t

  • sasl_client_plug_t

  • sasl_server_plug_t

  • sasl_canonuser_plug_t

  • sasl_auxprop_plug_t

可以在 SASL 头文件中找到这些结构的源代码。这些结构将在下一节中进行介绍。

SASL 插件的重要结构

    libsasl 与插件之间的通信是通过以下结构完成的:

  • sasl_utils_t-sasl_utils_t 结构包含大量实用程序函数以及三种上下文。

    此结构包含大量可为插件编写人员提供方便的实用程序函数。许多函数是指向 libsasl 中的公共接口的指针。插件不需要直接调用 libsasl,除非出于某种原因,插件需要是 SASL 使用者。

      libsasl 将为 sasl_utils_t 创建三种上下文:

    • sasl_conn_t *conn

    • sasl_rand_t *rpool

    • void *getopt_context

    在某些情况(如装入插件)下,sasl_utils_t 中的 conn 变量实际上与连接没有关联。在另外一些情况下,conn 是 SASL 使用者的 SASL 连接上下文。rpool 变量用于随机数生成函数。getopt_context 是应该与 getopt() 函数结合使用的上下文。

    请参见 sasl_getopt_t(3SASL)sasl_log_t(3SASL)sasl_getcallback_t(3SASL)

  • sasl_out_params_t-libsasl 用于创建 sasl_out_params_t 结构并将该结构传递给客户机或服务器中的 mech_step()。此结构可以将以下信息传达给 libsasl:验证状态、authidauthzidmaxbuf、协商的 ssf 以及数据编码和解码信息。

  • sasl_client_params_t-libsasl 使用 sasl_client_params_t 结构将客户机状态传递给 SASL 客户机机制。客户机机制的 mech_new()mech_step()mech_idle() 入口点用于发送此状态数据。canon_user_client() 入口点还需要同时传递客户机状态。

  • sasl_server_params_t-sasl_server_params_t 结构在服务器端执行和 sasl_client_params_t 类似的功能。

客户机插件

客户机插件用于管理 SASL 协商的客户端。客户机插件通常随对应的服务器插件一同打包。客户机插件包含一种或多种客户端 SASL 机制。每种 SASL 客户机机制都支持验证、完整性和保密性(后两者是可选的)。

    每种 SASL 客户机机制都提供有关该机制的功能的信息:

  • 最大 SSF

  • 最大安全标志

  • 插件功能

  • 用于使用插件的回调和提示 ID

客户机插件必须导出 sasl_client_plug_init()libsasl 将调用 sasl_client_plug_init() 来初始化客户机的插件。插件将返回 sasl_client_plug_t 结构。

    sasl_client_plug_t 将为 libsasl 提供以下用于调用机制的入口点:

  • mech_new()-客户机通过调用 sasl_client_start()(使用 mech_new())来启动连接。mech_new() 将执行特定于机制的初始化。如有必要,将分配连接上下文。

  • mech_step()mech_step() 可由 sasl_client_start()sasl_client_step() 进行调用。调用 mech_new() 后,mech_step() 将对客户端执行验证。如果验证成功,mech_step() 将返回 SASL_OK。如果需要更多数据,则将返回 SASL_CONTINUE。如果验证失败,则将返回 SASL 错误代码。如果出现错误,则将调用 seterror()。如果验证成功,则 mech_step() 必须返回包含相关安全层信息和回调的 sasl_out_params_t 结构。canon_user() 函数是此结构的一部分。客户机收到验证和授权 ID 时,必须调用 canon_user()

  • mech_dispose()mech_dispose() 是在安全关闭上下文时进行调用的。mech_dispose()sasl_dispose() 进行调用。

  • mech_free()mech_free() 是在 libsasl 关闭时进行调用的。插件的所有其余全局状态都是通过 mech_free() 释放的。

服务器插件

服务器插件用于管理 SASL 协商的服务器端。服务器插件通常随对应的客户机插件一同打包。服务器插件包含一种或多种服务器端 SASL 机制。每种 SASL 服务器机制都支持验证、完整性和保密性(后两者是可选的)。

    每种 SASL 服务器机制都提供有关该机制的功能的信息:

  • 最大 SSF

  • 最大安全标志

  • 插件功能

  • 用于使用插件的回调和提示 ID

服务器插件必须导出 sasl_server_plug_init()libsasl 将调用 sasl_server_plug_init() 来初始化服务器的插件。插件将返回 sasl_server_plug_t 结构。

    sasl_server_plug_t 结构将为 libsasl 提供以下用于调用机制的入口点:

  • mech_new()-服务器通过调用 sasl_server_start()(使用 mech_new())来启动连接。mech_new() 将执行特定于机制的初始化。如有必要,mech_new() 将分配连接上下文。

  • mech_step()mech_step() 可由 sasl_server_start()sasl_server_step() 进行调用。调用 mech_new() 后,mech_step() 将对服务器端执行验证。如果验证成功,mech_step() 将返回 SASL_OK。如果需要更多数据,则将返回 SASL_CONTINUE。如果验证失败,则将返回 SASL 错误代码。如果出现错误,则将调用 seterror()。如果验证成功,则 mech_step() 必须返回包含相关安全层信息和回调的 sasl_out_params_t 结构。canon_user() 函数是此结构的一部分。服务器收到验证和授权 ID 时,必须调用 canon_user()。调用 canon_user() 函数将导致 propctx 被填充。标准化验证之前,应执行所有必需的辅助属性请求。标准化验证后,应执行授权 ID 查找。

      返回 SASL_OK 之前,mech_step() 函数必须填充所有相关的 sasl_out_params_t 字段。这些字段可以执行以下函数:

    • doneflag-指示完整的交换

    • maxoutbuf-指示安全层的最大输出大小

    • mech_ssf-为安全层提供 SSF

    • encode()-由 sasl_encode()sasl_encodev()sasl_decode() 进行调用

    • decode()-由 sasl_encode()sasl_encodev()sasl_decode() 进行调用

    • encode_context()-由 sasl_encode()sasl_encodev()sasl_decode() 进行调用

    • decode_context()-由 sasl_encode()sasl_encodev()sasl_decode() 进行调用

  • mech_dispose()mech_dispose() 是在安全关闭上下文时进行调用的。mech_dispose()sasl_dispose() 进行调用。

  • mech_free()mech_free() 是在 libsasl 关闭时进行调用的。插件的所有其余全局状态都是通过 mech_free() 释放的。

  • setpass() 用于设置用户的口令。setpass() 使机制可以具有内部口令。

  • mech_avail()sasl_listmech() 进行调用,以检查机制是否可用于给定用户。mech_avail() 可以创建新的上下文,进而避免对 mech_new() 的调用。只要性能不受影响,就应使用此方法创建上下文。

用户标准化插件

标准化插件为客户端和服务器端的验证和授权名称的备用标准化提供支持。sasl_canonuser_plug_init() 用于装入标准化插件。

    标准化插件具有以下要求:

  • 必须将标准化的名称复制到输出缓冲区。

  • 可以将同一输入缓冲区用作输出缓冲区。

  • 当仅存在一个验证 ID 或授权 ID 时,标准化插件必须发挥作用。

用户标准化插件必须导出 sasl_canonuser_init() 函数。sasl_canonuser_init() 函数必须返回 sasl_canonuser_plug_t 以建立必要的入口点。用户标准化插件必须至少实现 sasl_canonuser_plug_t 结构的一个 canon_user_client() 成员或 canon_user_server() 成员。

辅助属性 (auxprop) 插件

Auxprop 插件为查找 SASL 服务器的 authidauthzid 的辅助属性提供支持。例如,应用程序可能需要查找内部验证的用户口令。sasl_auxprop_plug_init() 函数用于初始化 auxprop 插件并返回 sasl_auxpropr_plug_t 结构。

要成功实现 auxprop 插件,必须实现 sasl_auxprop_plug_t 结构的 auxprop_lookup 成员。标准化用户名后,应使用标准化的用户名来调用 auxprop_lookup() 函数。随后,插件即可执行请求的辅助属性所需的所有查询。


注 - Oracle Corporation 当前不提供 auxprop 插件。