3
votes

I'm trying to authenticate to an Active Directory domain using gsasl. I've already kinit'd as the Administrator. I've tried to follow the test code in gsasl tests/gssapi.c, but the code below is failing with GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR when calling gsasl_step64().

static int callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
{
    int ret = GSASL_NO_CALLBACK;

    switch (prop) {
        case GSASL_AUTHZID:
            gsasl_property_set(sctx, GSASL_AUTHZID, "Administrator");
            ret = GSASL_OK;
            break;

        case GSASL_SERVICE:
            gsasl_property_set(sctx, prop, "host");
            ret = GSASL_OK;
            break;

        case GSASL_HOSTNAME:
            char hostname[HOST_NAME_MAX];
            gethostname(hostname, HOST_NAME_MAX);
            gsasl_property_set(sctx, prop, hostname);
            ret = GSASL_OK;
            break;

        default:
            break;
    }

    return ret;
}

int main()
{
    Gsasl *ctx = NULL;
    Gsasl_session *session;
    char *s1 = NULL, *s2 = NULL;
    int ret;

    ret = gsasl_init(&ctx);
    if (ret != GSASL_OK) {
        cerr << "gsasl_init failed" << endl;
        return ret;
    }

    if (!gsasl_client_support_p(ctx, "GSSAPI")) {
        cerr << "No support for GSSAPI." << endl;
        return 77;
    }

    gsasl_callback_set(ctx, callback);

    ret = gsasl_client_start(ctx, "GSSAPI", &session);
    if (ret != GSASL_OK) {
        cerr << "gsasl_client_start failed" << endl;
        return ret;
    }

    do {
        ret = gsasl_step64(session, s2, &s1);
        gsasl_free(s2);
        if (ret != GSASL_OK && ret != GSASL_NEEDS_MORE) {
            cerr << "gsasl_step64 failed " << ret << endl;
            return ret;
        }
    } while (ret != GSASL_OK);

    if (s1) {
        gsasl_free(s1);
    }

    gsasl_finish(session);
}

Does anyone see what I'm doing wrong?

1

1 Answers

0
votes

Not really a clear answer because I don't use AD currently, so I can't verify my answer. But to localize the issue:

I would try the examples first. Maybe this test is desired to fail. If it doesn't work with the examples, I would investigate the source of library of the GNU SASL library.

Here is an extract from the source of the library, which throws this error:

maj_stat = gss_init_sec_context (&min_stat,
                                    GSS_C_NO_CREDENTIAL,
                                    &state->context,
                                    state->service,
                                    state->mech_oid,
                                    GSS_C_MUTUAL_FLAG,
                                     0,
                                    &state->cb,
                                    buf,
                                    &actual_mech_type,
                                    &state->token, &ret_flags, NULL);

if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
    return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;

As you can see, the function gss_init_sec_context() is called, In the if clause only GSS_S_COMPLETE and GSS_S_CONTINUE_NEEDED will be tested. But gss_init_sec_context() has many more status codes. So I would change the code of the library and print out a clearer error code, why it doesn't work.

There was also an issue in WINBIND/SAMBA, don't know if you use SAMBA, which throws an unspecified error in this specific function.