mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
5.5 KiB
249 lines
5.5 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Token.cxx
|
|
|
|
Abstract:
|
|
|
|
Implementation for Windows NT security interfaces.
|
|
|
|
Platform:
|
|
|
|
Windows NT user mode.
|
|
|
|
Notes:
|
|
|
|
Not portable to non-Windows NT platforms.
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 12/21/1995 Bits 'n pieces
|
|
|
|
--*/
|
|
|
|
#include <or.hxx>
|
|
|
|
CRITICAL_SECTION gcsTokenLock;
|
|
|
|
|
|
ORSTATUS
|
|
LookupOrCreateToken(
|
|
IN handle_t hCaller,
|
|
IN BOOL fLocal,
|
|
OUT CToken **ppToken
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Finds or allocates a new token object for the caller.
|
|
|
|
Arguments:
|
|
|
|
hCaller - RPC binding handle of the caller of RPCSS.
|
|
|
|
fLocal - Looking up a local client, check local security.
|
|
|
|
pToken - Upon a successful return this will hold the token.
|
|
It can be destroyed by calling Release();
|
|
|
|
Return Value:
|
|
|
|
|
|
OR_OK - success
|
|
OR_NOACCESS - If the caller is not local, or cannot be impersonated.
|
|
OR_NOMEM - Unable to allocate an object.
|
|
|
|
--*/
|
|
{
|
|
ORSTATUS status;
|
|
UINT type;
|
|
HANDLE hClientToken;
|
|
PSID psid;
|
|
LUID luid;
|
|
PTOKEN_USER ptu;
|
|
TOKEN_STATISTICS ts;
|
|
BOOL fSuccess;
|
|
|
|
if (fLocal)
|
|
{
|
|
status = I_RpcBindingInqTransportType(hCaller, &type);
|
|
|
|
if (status != RPC_S_OK || type != TRANSPORT_TYPE_LPC)
|
|
{
|
|
return(OR_NOACCESS);
|
|
}
|
|
}
|
|
|
|
status = RpcImpersonateClient(hCaller);
|
|
if (status != RPC_S_OK)
|
|
{
|
|
return(OR_NOACCESS);
|
|
}
|
|
|
|
fSuccess = OpenThreadToken(GetCurrentThread(),
|
|
TOKEN_IMPERSONATE | TOKEN_DUPLICATE | TOKEN_QUERY,
|
|
TRUE,
|
|
&hClientToken);
|
|
|
|
if (fSuccess)
|
|
{
|
|
DWORD needed = sizeof(ts);
|
|
fSuccess = GetTokenInformation(hClientToken,
|
|
TokenStatistics,
|
|
&ts,
|
|
sizeof(ts),
|
|
&needed
|
|
);
|
|
if (fSuccess)
|
|
{
|
|
needed = DEBUG_MIN(1,24);
|
|
|
|
do
|
|
{
|
|
ptu = (PTOKEN_USER)alloca(needed);
|
|
ASSERT(ptu);
|
|
|
|
fSuccess = GetTokenInformation(hClientToken,
|
|
TokenUser,
|
|
(PBYTE)ptu,
|
|
needed,
|
|
&needed);
|
|
}
|
|
while ( fSuccess == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
if (fSuccess)
|
|
{
|
|
luid = ts.AuthenticationId;
|
|
psid = ptu->User.Sid;
|
|
|
|
ASSERT(IsValidSid(psid) == TRUE);
|
|
|
|
CMutexLock lock(&gcsTokenLock);
|
|
CListElement *ple;
|
|
CToken *pToken;
|
|
|
|
fSuccess = FALSE;
|
|
|
|
ple = gpTokenList->First();
|
|
|
|
while(ple)
|
|
{
|
|
pToken = CToken::ContainingRecord(ple);
|
|
|
|
if (pToken->MatchLuid(luid))
|
|
{
|
|
pToken->Reference();
|
|
*ppToken = pToken;
|
|
CloseHandle(hClientToken);
|
|
fSuccess = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ple = ple->Next();
|
|
}
|
|
}
|
|
|
|
if (!fSuccess)
|
|
{
|
|
// Didn't find it; allocate and add to the list.
|
|
needed = GetLengthSid(psid) - sizeof(SID);
|
|
*ppToken = new(needed) CToken(hClientToken,
|
|
luid,
|
|
psid,
|
|
needed + sizeof(SID));
|
|
|
|
if (0 == *ppToken)
|
|
{
|
|
CloseHandle(hClientToken);
|
|
fSuccess = FALSE;
|
|
}
|
|
else
|
|
{
|
|
(*ppToken)->Insert();
|
|
|
|
#if DBG_DETAIL
|
|
{
|
|
DWORD d = 50;
|
|
WCHAR buffer[50];
|
|
GetUserName(buffer, &d);
|
|
OrDbgPrint(("OR: New user connected: %S (%p)\n", buffer, *ppToken));
|
|
}
|
|
#endif
|
|
|
|
fSuccess = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OrDbgPrint(("OR: GetTokenInformation failed %d\n", GetLastError()));
|
|
ASSERT(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
|
|
CloseHandle(hClientToken);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OrDbgPrint(("OR: OpenThreadToken failed: %d\n", GetLastError()));
|
|
}
|
|
|
|
status = RpcRevertToSelfEx(hCaller);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
if (fSuccess == FALSE)
|
|
{
|
|
return(OR_NOMEM);
|
|
}
|
|
|
|
return(OR_OK);
|
|
}
|
|
|
|
|
|
CToken::~CToken()
|
|
{
|
|
CloseHandle(_hImpersonationToken);
|
|
}
|
|
|
|
DWORD
|
|
CToken::Release()
|
|
{
|
|
CMutexLock lock(&gcsTokenLock);
|
|
|
|
if ( 0 == Dereference() )
|
|
{
|
|
Remove();
|
|
delete this;
|
|
return(0);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
void
|
|
CToken::Impersonate()
|
|
{
|
|
ASSERT(_hImpersonationToken);
|
|
|
|
BOOL f = SetThreadToken(0, _hImpersonationToken);
|
|
ASSERT(f);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
CToken::Revert()
|
|
{
|
|
BOOL f = SetThreadToken(0, 0);
|
|
ASSERT(f);
|
|
return;
|
|
}
|
|
|