0

I have Qt C++ application for Windows and Linux daemon. Windows machine is in domain (2008 R2 as a AD controller). I need to implement transparent authentication of Windows logged user to Linux daemon.

I found out that Kerberos 5 is modern security mechanism used in Windows, and GSS API is convenient API to Kerberos 5 (and some other security protocols).

I use this library for C++ app on Windows: http://web.mit.edu/kerberos/kfw-4.0/kfw-4.0.html

The process as I understand it as follows:

  1. Get some bytes on client side using GSS API
  2. Wrap these bytes in my message format and send to server
  3. Server checks that token somehow and obtains user name and checks that this information is trustworthy.

I'm on step 1. However, GSS API argues with the following error:

No credentials cache found

Below is implementation:

std::string GSSApiHelper::GetErrorMessage(OM_uint32 code, int type)
{
    std::string res;
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
    OM_uint32 msg_ctx;

    msg_ctx = 0;
    while (true)
    {
        maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, &msg_ctx, &msg);
        if (!res.empty())
            res.append("\n");
        if (maj_stat != GSS_S_COMPLETE)
        {
            res.append("Error in GetErrorMessage");
            break;
        }
        else
        {
            res.append((char*)msg.value);
        }

        if (msg.length != 0)
            (void)gss_release_buffer(&min_stat, &msg);

        if (!msg_ctx)
            break;
    }

    return res;
}

std::string GSSApiHelper::GetErrorMessage(OM_uint32 maj_stat, OM_uint32 min_stat)
{
    std::string res;
    res.append(GetErrorMessage(maj_stat, GSS_C_GSS_CODE));
    res.append("\n");
    res.append(GetErrorMessage(min_stat, GSS_C_MECH_CODE));

    return res;
}

void GSSApiHelper::Init()
{
    OM_uint32       maj_stat, min_stat;
    gss_ctx_id_t    ctx = GSS_C_NO_CONTEXT;
    gss_buffer_desc outputToken = GSS_C_EMPTY_BUFFER;
    OM_uint32       retFlags, validSeconds;
    gss_OID         actualMechType;
    gss_name_t      targetName = 0;

    gss_buffer_desc name;
    name.value = (void*)"nfs@vm-ad.domain.com";
    name.length = strlen((char*)name.value) + 1;
    maj_stat = gss_import_name(&min_stat, &name, GSS_C_NT_HOSTBASED_SERVICE, &targetName);
    qDebug() << "GSSApiHelper::Init(), gss_import_name result:" << GetErrorMessage(maj_stat, min_stat).c_str();

    maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &ctx, targetName,
        GSS_C_NO_OID,
        0/* flags */, 0/* validity time, in seconds*/,
        GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER/* or pointer to GSS_C_EMPTY_BUFFER*/,
        &actualMechType, &outputToken, &retFlags, &validSeconds);

    qDebug() << "GSSApiHelper::Init() result:" << GetErrorMessage(maj_stat, min_stat).c_str();
}

The same code on Linux gives me

No Kerberos credentials available

So, is there a way to get something that attributes to current logged user and can be sent to a server?

I do not want to use some Kerberos MIT apps for generating something and so on (I tried, thought). Just simple transparent authentication on clean XP/Win7 systems in domain. I see it everywhere - it is not so specific. Just wonder how hard it becomes to be implemented!

Viktor
  • 392
  • 2
  • 8
  • 2
    I'm not sure but the Windows SSPI may be of use. I'm pretty sure that's what the nodejs kerberos module uses. See this link: https://msdn.microsoft.com/en-us/library/windows/desktop/aa380496(v=vs.85).aspx – dmansfield Nov 13 '15 at 21:47
  • 1
    @Viktor Use SSPI on Windows and GSS-API on non-Windows. – Michael-O Nov 13 '15 at 22:05
  • Thank you, guys! Link seems extremely useful. SDK contains some samples - downloading them. It's a pity that there's no way to make cross-platform solution with the same set of headers. Well, some platform-specific #if directives will do the job :-) I will get back here after successful implementation both on Windows client and Linux server – Viktor Nov 14 '15 at 06:48

0 Answers0