【发布时间】:2016-05-31 22:39:39
【问题描述】:
我正在尝试实现为我的应用程序请求 TGT 的编程逻辑,因此在通过 GSSAPI 和 GSS-SPNEGO 机制向 LDAP 服务器进行身份验证之前,无需从命令行调用 kinit。
我创建了一个内存中的 ccache,请求一个带有用户名和密码的 TGT,然后使用 gss_krb5_import_cred 导入凭据。在开始身份验证之前为 LDAP 结构设置 GSSAPI 上下文。
下面的示例代码在 GSSAPI 上运行良好,但是当我尝试将机制更改为 GSS-SPNEGO 时,我收到本地 LDAP 错误 (-2) 并显示以下消息:
SASL(-1):一般故障:GSSAPI 错误:未指定的 GSS 故障。次要代码可能提供更多信息(SPNEGO 找不到协商机制)
int create_krb5_cred(krb5_context ctx, char *realm, char *user,
char *password, krb5_ccache *ccache, gss_cred_id_t *gsscred) {
int rc = 0, minor_stat = 0;
int len = 0;
const char *cname = NULL;
krb5_get_init_creds_opt *cred_opt;
krb5_creds creds;
krb5_principal princ = NULL;
if (realm == NULL || user == NULL || password == NULL) return -1;
rc = krb5_cc_new_unique(ctx, "MEMORY", NULL, ccache);
if (rc != 0) goto clear;
len = strlen(realm);
rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL);
if (rc != 0) goto clear;
rc = krb5_cc_initialize(ctx, *ccache, princ);
if (rc != 0) goto clear;
rc = krb5_get_init_creds_opt_alloc(ctx, &cred_opt);
if (rc != 0) goto clear;
rc = krb5_get_init_creds_password(ctx, &creds, princ, password, 0, NULL, 0, NULL, NULL);
if (rc != 0) goto clear;
rc= krb5_cc_store_cred(ctx, *ccache, &creds);
if (rc != 0) goto clear;
cname = krb5_cc_get_name(ctx, *ccache);
if (cname == NULL) goto clear;
rc = gss_krb5_ccache_name(&minor_stat, cname, NULL);
if (rc != 0) goto clear;
rc = gss_krb5_import_cred(&minor_stat, *ccache, princ, 0, gsscred);
clear:
if (princ != NULL) krb5_free_principal(ctx, princ);
return rc;
}
int remove_krb5_cred(krb5_context ctx, krb5_ccache ccache, gss_cred_id_t *gsscred) {
int rc = 0;
rc = gss_release_cred(NULL, gsscred);
if (rc != 0) return rc;
rc = krb5_cc_destroy(ctx, ccache);
krb5_free_context(ctx);
return rc;
}
int main(void) {
int rc = 0;
krb5_context ctx;
krb5_ccache ccache;
gss_cred_id_t gsscred = NULL;
rc = krb5_init_context(&ctx);
create_krb5_cred(ctx, "EXAMPLE.ORG", "testuser", "secret", &ccache, &gsscred);
LDAP *ld = NULL;
const int version = LDAP_VERSION3;
void *defaults = NULL;
ldap_initialize(&ld, "ldap://example.org");
ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
/* Setting the credentials and handling the SASL binding with the `interact` function
(with setting the new GSS context) is not disclosed here...*/
rc = ldap_sasl_interactive_bind_s(ld, NULL, "GSSAPI", NULL, NULL, 0, interact, defaults);
printf("Connect 0x%x\n", rc);
remove_krb5_cred(ctx, ccache, &gsscred);
struct berval *authzid;
rc = ldap_whoami_s(ld, &authzid, NULL, NULL);
printf("RC %d %s\n\n", rc, authzid->bv_val);
}
This 旧论坛帖子建议没有为导入的凭据设置 SPNEGO oid,因此 LDAP 在身份验证期间将忽略它。
我尝试使用gss_acquire_cred 函数而不是gss_krb5_import_cred,但我没有成功接收到带有它的TGT(甚至对于GSSAPI 也不行)。
欢迎任何关于如何使用 GSSAPI 和 GSS-SPNEGO 成功进行身份验证的想法。
更新:我已经设法将 gss_acquire_cred 与 GSSAPI 和 GSS-SPNEGO 一起使用,但我必须使用基于文件的凭据缓存而不是基于内存的凭据缓存。
【问题讨论】: