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:
- Get some bytes on client side using GSS API
- Wrap these bytes in my message format and send to server
- 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!