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

退出打印视图

更新时间: 2014 年 7 月
 
 

指定 OID

应尽可能使用 GSS-API 所提供的缺省 QOP 和机制。请参见 GSS-API OIDs。但是,您可能会出于自己的考虑指定 OID。本附录介绍了如何指定 OID。

包含 OID 值的文件

为方便起见,GSS-API 允许以可读方式显示机制和 QOP。在 Oracle Solaris 系统上,有两个文件(/etc/gss/mech/etc/gss/qop)中包含有关可用机制和可用 QOP 的信息。如果无权访问这些文件,则必须提供来自其他源代码的串文字。针对该机制或 QOP 发布的 Internet 标准应当可以实现此目的。

/etc/gss/mech 文件

    /etc/gss/mech 文件列出了可用的机制。/etc/gss/mech 包含数值和字母两种格式的名称。/etc/gss/mech 将显示以下格式的信息:

  • ASCII 形式的机制名称

  • 机制的 OID

  • 用于实现此机制所提供的服务的共享库

  • 也可以是用于实现服务的内核模块

/etc/gss/mech 样例可能与 Example D–1 类似。

示例 D-1  /etc/gss/mech 文件
# 
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.


#
#ident	"@(#)mech	1.12	03/10/20 SMI"
#
# This file contains the GSS-API based security mechanism names,
# the associated object identifiers (OID) and a shared library that 
# implements the services for the mechanisms under GSS-API.
#
# Mechanism Name	Object Identifier	Shared Library	Kernel Module
[Options]
#
kerberos_v5		1.2.840.113554.1.2.2	mech_krb5.so kmech_krb5 
spnego			1.3.6.1.5.5.2		mech_spnego.so.1 [msinterop]
diffie_hellman_640_0	1.3.6.4.1.42.2.26.2.4	dh640-0.so.1
diffie_hellman_1024_0	1.3.6.4.1.42.2.26.2.5	dh1024-0.so.1

/etc/gss/qop 文件

对于安装的所有机制,/etc/gss/qop 文件存储每个机制所支持的所有 QOP,这些机制均以 ASCII 字符串和对应的 32 位整数两种形式提供。样例 /etc/gss/qop 可能如以下示例所示:

示例 D-2  /etc/gss/qop 文件
#
# Copyright (c) 2000,2012

 by Oracle and/or its affiliates. All rights reserved.
# All rights reserved.
#
#ident  "@(#)qop 1.3     00/11/09 SMI" 
#
# This file contains information about the GSS-API based quality of
# protection (QOP), its string name and its value (32-bit integer).
#
# QOP string                    QOP Value       Mechanism Name
#
GSS_KRB5_INTEG_C_QOP_DES_MD5    0               kerberos_v5
GSS_KRB5_CONF_C_QOP_DES         0               kerberos_v5

gss_str_to_oid() 函数

为了与早期版本的 GSS-API 向下兼容,此 GSS-API 实现支持函数 gss_str_to_oid()gss_str_to_oid() 可用于将表示机制或 QOP 的字符串转换为 OID。字符串可以采用数字或字的形式。


Caution

注意  - 某些 GSS-API 实现不支持 gss_str_to_oid()gss_oid_to_str()gss_release_oid(),因此不建议使用显式的非缺省机制和 QOP。


机制字符串可以硬编码到应用程序中,也可以来自用户输入的内容。但是,并非所有的 GSS-API 实现都支持 gss_str_to_oid(),因此应用程序不应当依赖此函数。

表示机制的数字可以采用两种不同的格式。第一种格式 { 1 2 3 4 } 是 GSS-API 规范要求使用的正式格式。第二种格式 1.2.3.4 的使用更为广泛,但不是正式的标准格式。gss_str_to_oid() 应当使用第一种格式的机制数字,因此,在调用 gss_str_to_oid() 之前,必须对采用第二种格式的字符串进行转换。Example D–3() 中显示了 gss_str_to_oid 的示例。如果机制无效,gss_str_to_oid() 将返回 GSS_S_BAD_MECH

由于 gss_str_to_oid() 会分配 GSS-API 数据空间,因此在您完成操作时会提供已存在的 gss_release_oid() 函数来删除所分配的 OID。与 gss_str_to_oid() 一样,gss_release_oid() 也不是广泛支持的函数,因此对于希望具有可移植性的通用程序来说,不应依赖此函数。

构造机制 OID

由于无法始终使用 gss_str_to_oid(),因此提供了多种用于查找和选择机制的备用方法。一种方法是手动构造机制 OID,然后将该机制与一组可用的机制进行比较。另一种方法是获取一组可用机制并从其中选择一个机制。

gss_OID 类型的格式如下:

typedef struct gss_OID_desc struct {
     OM_uint32 length;
     void           *elements;
} gss_OID_desc, *gss_OID;

其中,此结构的 elements 字段指向八位字节字符串的第一个字节,该字符串中包含 gss_OID 的常规 BER TLV 编码的值部分的 ASN.1 BER 编码。length 字段包含该值中的字节数。例如,对应于 DASS X.509 验证机制的 gss_OID 值包含一个值为 7 的 length 字段和一个指向以下八位字节值的 elements 字段:53,14,2,207,163,7,5

构造机制 OID 的一种方法是声明 gss_OID,然后手动初始化表示指定机制的元素。如上所述,elements 值的输入可以是从表中获取的硬编码值,也可以由用户输入。此方法比使用 gss_str_to_oid() 稍微麻烦些,但是二者的效果相同。

然后,可以将所构造的 gss_OID 与 gss_indicate_mechs()gss_inquire_mechs_for_name() 函数已返回的一组可用机制进行比较。应用程序可以使用 gss_test_oid_set_member() 函数来检查这组可用机制中是否存在所构造的机制 OID。如果 gss_test_oid_set_member() 没有返回错误,则表明可以将所构造的 OID 用作 GSS-API 事务的机制。

构造预设 OID 的另一种方法是使应用程序使用 gss_indicate_mechs()gss_inquire_mechs_for_name() 来获取可用机制的 gss_OID_set。gss_OID_set 具有以下格式:

typedef struct gss_OID_set_desc_struct {
     OM_uint32 length;
     void           *elements;
} gss_OID_set_desc, *gss_OID_set;

其中,每个元素都是一个表示相应机制的 gss_OID。应用程序随后会解析每个机制并显示其数值表示形式。用户可以使用所显示的数值来选择机制。然后,应用程序会将该机制设置为 gss_OID_set 的相应成员。应用程序还可以将所需的机制与首选机制的列表进行比较。

createMechOid() 函数

说明此函数的目的是为了保持代码完整。通常,应当使用 GSS_C_NULL_OID 所指定的缺省机制。

示例 D-3  createMechOid() 函数
gss_OID createMechOid(const char *mechStr)
{
        gss_buffer_desc mechDesc;
        gss_OID mechOid;
        OM_uint32 minor;

        if (mechStr == NULL)
                return (GSS_C_NULL_OID);

        mechDesc.length = strlen(mechStr);
        mechDesc.value = (void *) mechStr;

        if (gss_str_to_oid(&minor, &mechDesc, &mechOid) !
            = GSS_S_COMPLETE) {
                fprintf(stderr, "Invalid mechanism oid specified <%s>",
                                mechStr);
                return (GSS_C_NULL_OID);
        }

        return (mechOid);
}

指定非缺省机制

parse_oid() 可用于将命令行中的安全机制名称转换为兼容的 OID。

示例 D-4  parse_oid() 函数
static void parse_oid(char *mechanism, gss_OID *oid)
{
    char        *mechstr = 0, *cp;
    gss_buffer_desc tok;
    OM_uint32 maj_stat, min_stat;
   
    if (isdigit(mechanism[0])) {
        mechstr = malloc(strlen(mechanism)+5);
        if (!mechstr) {
            printf("Couldn't allocate mechanism scratch!\n");
            return;
        }
        sprintf(mechstr, "{ %s }", mechanism);
        for (cp = mechstr; *cp; cp++)
            if (*cp == '.')
                *cp = ' ';
        tok.value = mechstr;
    } else
        tok.value = mechanism;
    tok.length = strlen(tok.value);
    maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
    if (maj_stat != GSS_S_COMPLETE) {
        display_status("str_to_oid", maj_stat, min_stat);
        return;
    }
    if (mechstr)
        free(mechstr);
}