Windows NT 4.0 source code leak
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

/*++
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;
}