将GSS-SPNEGO与gss_krb5_import_cred一起使用

时间:2016-02-19 11:13:12

标签: c ldap kerberos gssapi

我正在尝试为我的应用程序实现请求TGT的编程逻辑,因此在通过GSSAPI和GSS对LDAP服务器进行身份验证之前,从命令行调用kinit是不必要的。 -SPNEGO机制。

我创建了一个内存中的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一起使用,但我不得不使用基于文件的凭据缓存而不是基于内存的凭据缓存。

1 个答案:

答案 0 :(得分:0)

实现这一目标需要采取一些措施:

  1. 获得常规TGT。
  2. 确保Cyrus SASL针对MIT Kerberos正确编译。您可以使用pluginviewer
  3. 进行检查
  4. 使OpenLDAP正确编译Cyrus SASL。
  5. 使用ldapsearch测试您的设置,以确保Kerberos确实有效。
  6. 如果一切顺利,请继续:

    1. 使用来自的公共函数gss_acquire_cred_with_password gssapi_ext.h
    2. 现在使用交互式绑定准备LDAP句柄,其他任何内容都不起作用。
    3. 这个句柄可以通过auth到Cyrus SASL,期望它以机制的格式。
    4. 现在,您需要使用指针gss_cred_tberval传递给sizeof结构。
    5. Cyrus SASL将接收它并将其传递给GSS背景。
    6. 不幸的是,OpenLDAP和Cyrus SASL都记录得很糟糕。我怎么知道它会起作用?我阅读了两者的源代码,以了解并使用该用例。

      首先阅读标题文件,您将得到一个结果。如果你被困住,请再次重新开始。