8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/auth/trusted/AuthSspi.cpp

219 lines
4.5 KiB
C++
Raw Normal View History

2006-12-08 19:38:15 +01:00
#include "AuthSspi.h"
#ifdef TRUSTED_AUTH
#include <../common/classes/ClumpletReader.h>
AuthSspi::AuthSspi()
: hasContext(false), ctName(*getDefaultMemoryPool())
{
TimeStamp timeOut;
hasCredentials = AcquireCredentialsHandle(0, "NTLM", SECPKG_CRED_BOTH, 0, 0, 0, 0,
&secHndl, &timeOut) == SEC_E_OK;
}
AuthSspi::~AuthSspi()
{
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
if (hasCredentials)
{
FreeCredentialsHandle(&secHndl);
}
}
namespace
{
void makeDesc(SecBufferDesc& d, SecBuffer& b, size_t len, void* p)
{
b.BufferType = SECBUFFER_TOKEN;
b.cbBuffer = len;
b.pvBuffer = len ? p : 0;
d.ulVersion = SECBUFFER_VERSION;
d.cBuffers = 1;
d.pBuffers = &b;
}
bool checkAdminPrivilege(PCtxtHandle phContext)
{
// Query access token from security context
SecPkgContext_AccessToken spc;
spc.AccessToken = 0;
if (QueryContextAttributes(phContext, SECPKG_ATTR_ACCESS_TOKEN, &spc) != SEC_E_OK)
{
return false;
}
// Query required buffer size
DWORD token_len = 0;
2006-12-10 01:16:00 +01:00
GetTokenInformation(spc.AccessToken, TokenGroups, 0, 0, &token_len);
2006-12-08 19:38:15 +01:00
// Query actual group information
Firebird::Array<char> buffer;
TOKEN_GROUPS *ptg = (TOKEN_GROUPS *)buffer.getBuffer(token_len);
bool ok = GetTokenInformation(spc.AccessToken,
TokenGroups, ptg, token_len, &token_len);
FreeContextBuffer(spc.AccessToken);
if (! ok)
{
return false;
}
// Create a System Identifier for the Admin group.
SID_IDENTIFIER_AUTHORITY system_sid_authority = {SECURITY_NT_AUTHORITY};
PSID admin_sid;
if (!AllocateAndInitializeSid(&system_sid_authority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &admin_sid))
{
return false;
}
// Finally we'll iterate through the list of groups for this access
// token looking for a match against the SID we created above.
for (DWORD i = 0; i < ptg->GroupCount; i++)
{
if (EqualSid(ptg->Groups[i].Sid, admin_sid))
{
FreeSid(admin_sid);
return true;
}
}
FreeSid(admin_sid);
return false;
}
}
bool AuthSspi::request(AuthSspi::DataHolder& data)
{
if (! hasCredentials)
{
data.clear();
return false;
}
TimeStamp timeOut;
char s[BUFSIZE];
SecBuffer outputBuffer, inputBuffer;
SecBufferDesc outputDesc, inputDesc;
makeDesc(outputDesc, outputBuffer, sizeof(s), s);
makeDesc(inputDesc, inputBuffer, data.getCount(), data.begin());
ULONG fContextAttr = 0;
SECURITY_STATUS x = InitializeSecurityContext(
&secHndl, hasContext ? &ctxtHndl : 0, 0, 0, 0, SECURITY_NATIVE_DREP,
hasContext ? &inputDesc : 0, 0, &ctxtHndl, &outputDesc, &fContextAttr, &timeOut);
switch (x)
{
case SEC_E_OK:
DeleteSecurityContext(&ctxtHndl);
hasContext = false;
break;
case SEC_I_CONTINUE_NEEDED:
hasContext = true;
break;
default:
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
hasContext = false;
data.clear();
return false;
}
if (outputBuffer.cbBuffer)
{
memcpy(data.getBuffer(outputBuffer.cbBuffer),
outputBuffer.pvBuffer, outputBuffer.cbBuffer);
}
else
{
data.clear();
}
return true;
}
bool AuthSspi::accept(AuthSspi::DataHolder& data)
{
if (! hasCredentials)
{
data.clear();
return false;
}
TimeStamp timeOut;
char s[BUFSIZE];
SecBuffer outputBuffer, inputBuffer;
SecBufferDesc outputDesc, inputDesc;
makeDesc(outputDesc, outputBuffer, sizeof(s), s);
makeDesc(inputDesc, inputBuffer, data.getCount(), data.begin());
ULONG fContextAttr = 0;
SecPkgContext_Names name;
SECURITY_STATUS x = AcceptSecurityContext(
&secHndl, hasContext ? &ctxtHndl : 0, &inputDesc, 0,
SECURITY_NATIVE_DREP, &ctxtHndl, &outputDesc,
&fContextAttr, &timeOut);
switch(x)
{
case SEC_E_OK:
if (checkAdminPrivilege(&ctxtHndl))
{
ctName = "SYSDBA";
}
else if (QueryContextAttributes(&ctxtHndl, SECPKG_ATTR_NAMES, &name) == SEC_E_OK)
{
ctName = name.sUserName;
ctName.upper();
FreeContextBuffer(name.sUserName);
}
DeleteSecurityContext(&ctxtHndl);
hasContext = false;
break;
case SEC_I_CONTINUE_NEEDED:
hasContext = true;
break;
default:
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
hasContext = false;
data.clear();
return false;
}
if (outputBuffer.cbBuffer)
{
memcpy(data.getBuffer(outputBuffer.cbBuffer),
outputBuffer.pvBuffer, outputBuffer.cbBuffer);
}
else
{
data.clear();
}
return true;
}
bool AuthSspi::getLogin(Firebird::string& login)
{
if (ctName.hasData())
{
login = ctName;
ctName.erase();
return true;
}
return false;
}
2006-12-10 01:16:00 +01:00
#endif // TRUSTED_AUTH