windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/server/utils.cpp

634 lines
15 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1998
//
// File: utils.cpp
//
// Contents: Hydra License Server Service Control Manager Interface
//
// History: 12-09-97 HueiWang Modified from MSDN RPC Service Sample
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#include <lm.h>
#include <time.h>
#include "utils.h"
/////////////////////////////////////////////////////////////////////////////
BOOL
FileExists(
IN PCTSTR FileName,
OUT PWIN32_FIND_DATA FindData OPTIONAL
)
/*++
Routine Description:
Determine if a file exists and is accessible.
Errormode is set (and then restored) so the user will not see
any pop-ups.
Arguments:
FileName - supplies full path of file to check for existance.
FindData - if specified, receives find data for the file.
Return Value:
TRUE if the file exists and is accessible.
FALSE if not. GetLastError() returns extended error info.
--*/
{
WIN32_FIND_DATA findData;
HANDLE FindHandle;
DWORD Error;
FindHandle = FindFirstFile(FileName,&findData);
if(FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
}
else
{
FindClose(FindHandle);
if(FindData)
{
*FindData = findData;
}
Error = NO_ERROR;
}
SetLastError(Error);
return (Error == NO_ERROR);
}
/*----------------------------------------------------------------------------
Routine Description:
This function checks to see whether the specified sid is enabled in
the specified token.
Arguments:
TokenHandle - If present, this token is checked for the sid. If not
present then the current effective token will be used. This must
be an impersonation token.
SidToCheck - The sid to check for presence in the token
IsMember - If the sid is enabled in the token, contains TRUE otherwise
false.
Return Value:
TRUE - The API completed successfully. It does not indicate that the
sid is a member of the token.
FALSE - The API failed. A more detailed status code can be retrieved
via GetLastError()
Note : Code modified from 5.0 \\rastaman\ntwin\src\base\advapi\security.c
----------------------------------------------------------------------------*/
BOOL
TLSCheckTokenMembership(
IN HANDLE TokenHandle OPTIONAL,
IN PSID SidToCheck,
OUT PBOOL IsMember
)
{
HANDLE ProcessToken = NULL;
HANDLE EffectiveToken = NULL;
DWORD Status = ERROR_SUCCESS;
PISECURITY_DESCRIPTOR SecDesc = NULL;
ULONG SecurityDescriptorSize;
GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_EXECUTE,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_ALL };
//
// The size of the privilege set needs to contain the set itself plus
// any privileges that may be used. The privileges that are used
// are SeTakeOwnership and SeSecurity, plus one for good measure
//
BYTE PrivilegeSetBuffer[sizeof(PRIVILEGE_SET) + 3*sizeof(LUID_AND_ATTRIBUTES)];
PPRIVILEGE_SET PrivilegeSet = (PPRIVILEGE_SET) PrivilegeSetBuffer;
ULONG PrivilegeSetLength = sizeof(PrivilegeSetBuffer);
ACCESS_MASK AccessGranted = 0;
BOOL AccessStatus = FALSE;
PACL Dacl = NULL;
#define MEMBER_ACCESS 1
*IsMember = FALSE;
//
// Get a handle to the token
//
if (TokenHandle != NULL)
{
EffectiveToken = TokenHandle;
}
else
{
if(!OpenThreadToken(GetCurrentThread(),
TOKEN_QUERY,
FALSE, // don't open as self
&EffectiveToken))
{
//
// if there is no thread token, try the process token
//
if((Status=GetLastError()) == ERROR_NO_TOKEN)
{
if(!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY | TOKEN_DUPLICATE,
&ProcessToken))
{
Status = GetLastError();
}
//
// If we have a process token, we need to convert it to an
// impersonation token
//
if (Status == ERROR_SUCCESS)
{
BOOL Result;
Result = DuplicateToken(ProcessToken,
SecurityImpersonation,
&EffectiveToken);
CloseHandle(ProcessToken);
if (!Result)
{
return(FALSE);
}
}
}
if (Status != ERROR_SUCCESS)
{
goto Cleanup;
}
}
}
//
// Construct a security descriptor to pass to access check
//
//
// The size is equal to the size of an SD + twice the length of the SID
// (for owner and group) + size of the DACL = sizeof ACL + size of the
// ACE, which is an ACE + length of
// ths SID.
//
SecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR) +
sizeof(ACCESS_ALLOWED_ACE) +
sizeof(ACL) +
3 * GetLengthSid(SidToCheck);
SecDesc = (PISECURITY_DESCRIPTOR) LocalAlloc(LMEM_ZEROINIT, SecurityDescriptorSize );
if (SecDesc == NULL)
{
Status = ERROR_OUTOFMEMORY;
goto Cleanup;
}
Dacl = (PACL) (SecDesc + 1);
InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
//
// Fill in fields of security descriptor
//
SetSecurityDescriptorOwner(SecDesc, SidToCheck, FALSE);
SetSecurityDescriptorGroup(SecDesc, SidToCheck, FALSE);
if(!InitializeAcl( Dacl,
SecurityDescriptorSize - sizeof(SECURITY_DESCRIPTOR),
ACL_REVISION))
{
Status=GetLastError();
goto Cleanup;
}
if(!AddAccessAllowedAce(Dacl, ACL_REVISION, MEMBER_ACCESS, SidToCheck))
{
Status=GetLastError();
goto Cleanup;
}
if(!SetSecurityDescriptorDacl(SecDesc, TRUE, Dacl, FALSE))
{
Status=GetLastError();
goto Cleanup;
}
if(!AccessCheck(SecDesc,
EffectiveToken,
MEMBER_ACCESS,
&GenericMapping,
PrivilegeSet,
&PrivilegeSetLength,
&AccessGranted,
&AccessStatus))
{
Status=GetLastError();
goto Cleanup;
}
//
// if the access check failed, then the sid is not a member of the
// token
//
if ((AccessStatus == TRUE) && (AccessGranted == MEMBER_ACCESS))
{
*IsMember = TRUE;
}
Cleanup:
if (TokenHandle == NULL && EffectiveToken != NULL)
{
CloseHandle(EffectiveToken);
}
if (SecDesc != NULL)
{
LocalFree(SecDesc);
}
return (Status == ERROR_SUCCESS) ? TRUE : FALSE;
}
/*------------------------------------------------------------------------
BOOL IsAdmin(void)
returns TRUE if user is an admin
FALSE if user is not an admin
------------------------------------------------------------------------*/
DWORD
IsAdmin(
BOOL* bMember
)
{
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
DWORD dwStatus=ERROR_SUCCESS;
do {
if(!AllocateAndInitializeSid(&siaNtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&psidAdministrators))
{
dwStatus=GetLastError();
continue;
}
// assume that we don't find the admin SID.
if(!TLSCheckTokenMembership(NULL,
psidAdministrators,
bMember))
{
dwStatus=GetLastError();
}
FreeSid(psidAdministrators);
} while(FALSE);
return dwStatus;
}
/////////////////////////////////////////////////////////////////////////////
BOOL
LoadResourceString(
DWORD dwId,
LPTSTR szBuf,
DWORD dwBufSize
)
{
int dwRet;
dwRet=LoadString(GetModuleHandle(NULL), dwId, szBuf, dwBufSize);
return (dwRet != 0);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT
LogEvent(
LPTSTR lpszSource,
DWORD dwEventType,
DWORD dwIdEvent,
WORD cStrings,
TCHAR **apwszStrings
)
/*++
--*/
{
HANDLE hAppLog=NULL;
BOOL bSuccess=FALSE;
WORD wElogType;
wElogType = (WORD) dwEventType;
if(hAppLog=RegisterEventSource(NULL, lpszSource))
{
bSuccess = ReportEvent(
hAppLog,
wElogType,
0,
dwIdEvent,
NULL,
cStrings,
0,
(const TCHAR **) apwszStrings,
NULL
);
DeregisterEventSource(hAppLog);
}
return((bSuccess) ? ERROR_SUCCESS : GetLastError());
}
/////////////////////////////////////////////////////////////////////////////
void
TLSLogInfoEvent(
IN DWORD code
)
/*++
--*/
{
LogEvent(
_TEXT(SZSERVICENAME),
EVENTLOG_INFORMATION_TYPE,
code,
0,
NULL
);
}
/////////////////////////////////////////////////////////////////////////////
void
TLSLogWarningEvent(
IN DWORD code
)
/*++
--*/
{
LogEvent(
_TEXT(SZSERVICENAME),
EVENTLOG_WARNING_TYPE,
code,
0,
NULL
);
}
/////////////////////////////////////////////////////////////////////////////
void
TLSLogErrorEvent(
IN DWORD errCode
)
/*++
--*/
{
LogEvent(
_TEXT(SZSERVICENAME),
EVENTLOG_ERROR_TYPE,
errCode,
0,
NULL
);
}
/////////////////////////////////////////////////////////////////////////////
void
TLSLogEventString(
IN DWORD dwEventType,
IN DWORD dwEventId,
IN WORD wNumString,
IN LPCTSTR* lpStrings
)
/*++
--*/
{
HANDLE hAppLog=NULL;
BOOL bSuccess=FALSE;
WORD wElogType = (WORD) dwEventType;
__try {
if(hAppLog=RegisterEventSource(NULL, _TEXT(SZSERVICENAME)))
{
bSuccess = ReportEvent(
hAppLog,
wElogType,
0,
dwEventId,
NULL,
wNumString,
0,
(const TCHAR **) lpStrings,
NULL
);
DeregisterEventSource(hAppLog);
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
}
return;
}
/////////////////////////////////////////////////////////////////////////////
void
TLSLogEvent(
IN DWORD type,
IN DWORD EventId,
IN DWORD code, ...
)
/*
*/
{
va_list marker;
va_start( marker, code );
DWORD dwRet;
LPTSTR lpszTemp = NULL;
__try {
dwRet=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
code,
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
&marker);
if(dwRet != 0)
{
LogEvent(_TEXT(SZSERVICENAME), type, EventId, 1, &lpszTemp);
if(lpszTemp)
{
LocalFree((HLOCAL)lpszTemp);
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
// this is only for putting a break point here
SetLastError(GetLastError());
}
va_end( marker );
return;
}
///////////////////////////////////////////////////////////////////////
BOOL
TLSSystemTimeToFileTime(
SYSTEMTIME* pSysTime,
LPFILETIME pfTime
)
/*++
--*/
{
DoConvert:
if(SystemTimeToFileTime(pSysTime, pfTime) == FALSE)
{
if(GetLastError() != ERROR_INVALID_PARAMETER)
{
TLSASSERT(FALSE);
return FALSE;
}
if(pSysTime->wMonth == 2)
{
if(pSysTime->wDay > 29)
{
pSysTime->wDay = 29;
goto DoConvert;
}
else if(pSysTime->wDay == 29)
{
pSysTime->wDay = 28;
goto DoConvert;
}
}
else if ((pSysTime->wMonth == 9) ||
(pSysTime->wMonth == 4) ||
(pSysTime->wMonth == 6) ||
(pSysTime->wMonth == 11))
{
if (pSysTime->wDay > 30)
{
pSysTime->wDay = 30;
goto DoConvert;
}
}
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////
BOOL
FileTimeToLicenseDate(
LPFILETIME pft,
DWORD* t
)
/*++
++*/
{
SYSTEMTIME sysTime;
struct tm gmTime;
FILETIME localFt;
time_t licenseTime;
if(FileTimeToLocalFileTime(pft, &localFt) == FALSE)
{
return FALSE;
}
if(FileTimeToSystemTime(&localFt, &sysTime) == FALSE)
{
return FALSE;
}
if(sysTime.wYear >= 2038)
{
licenseTime = INT_MAX;
}
else
{
// Unix time support up to 2038/1/18
// restrict any expiration data
memset(&gmTime, 0, sizeof(gmTime));
gmTime.tm_sec = sysTime.wSecond;
gmTime.tm_min = sysTime.wMinute;
gmTime.tm_hour = sysTime.wHour;
gmTime.tm_year = sysTime.wYear - 1900;
gmTime.tm_mon = sysTime.wMonth - 1;
gmTime.tm_mday = sysTime.wDay;
gmTime.tm_isdst = -1;
if((licenseTime = mktime(&gmTime)) == (time_t)-1)
{
SetLastError(ERROR_INVALID_PARAMETER);
}
}
*t = (DWORD)licenseTime;
return licenseTime != (time_t)-1;
}
///////////////////////////////////////////////////////////////////////
void
UnixTimeToFileTime(
time_t t,
LPFILETIME pft
)
{
LARGE_INTEGER li;
li.QuadPart = Int32x32To64(t, 10000000) + 116444736000000000;
pft->dwHighDateTime = li.HighPart;
pft->dwLowDateTime = li.LowPart;
}