应尽可能使用缺省 QOP 和 GSS-API 所提供的机制。请参见GSS-API OID。但是,您可能会出于自己的考虑指定 OID。本附录介绍了如何指定 OID。本附录包含以下主题:
为方便起见,GSS-API 允许以可读方式显示机制和 QOP。在 Solaris 系统上,有两个文件(/etc/gss/mech 和 /etc/gss/qop)中包含有关可用机制和可用 QOP 的信息。如果无权访问这些文件,则必须提供来自其他源代码的串文字。针对该机制或 QOP 发布的 Internet 标准应当可以实现此目的。
/etc/gss/mech 文件列出了可用的机制,其中包含数值和字母两种格式的名称,它将显示以下格式的信息:
ASCII 形式的机制名称
机制的 OID
用于实现此机制所提供的服务的共享库
也可以是用于实现服务的内核模块
样例 /etc/gss/mech 可能如示例 C–1 所示。
# # Copyright 2003 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #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 文件存储每个机制所支持的所有 QOP,这些机制均以 ASCII 字符串和对应的 32 位整数两种形式提供。样例 /etc/gss/qop 可能如以下示例所示:
# # Copyright (c) 2000, by Sun Microsystems, Inc. # 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-API 向下兼容,此 GSS-API 实现支持函数 gss_str_to_oid()。gss_str_to_oid() 可用于将表示机制或 QOP 的字符串转换为 OID。字符串可以采用数字或字的形式。
某些 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() 之前,必须对采用第二种格式的字符串进行转换。示例 C–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() 也不是广泛支持的函数,因此对于希望具有通用可移植性的程序来说,不应依赖此函数。
由于无法始终使用 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 的相应成员。应用程序还可以将所需的机制与首选机制的列表进行比较。
说明此函数的目的是为了保持代码完整。通常,应当使用 GSS_C_NULL_OID
所指定的缺省机制。
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。
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); }