590 lines
13 KiB
C
590 lines
13 KiB
C
/*
|
|
File: dsrights.c
|
|
|
|
Implements the mechanisms needed to grant ras servers the
|
|
rights in the DS that they need to operate.
|
|
|
|
Paul Mayfield, 4/13/98
|
|
*/
|
|
|
|
#include "dsrights.h"
|
|
#include <mprapip.h>
|
|
#include <rtutils.h>
|
|
|
|
//
|
|
// The character that delimits machine names from domain
|
|
// names.
|
|
//
|
|
static const WCHAR pszMachineDelimeter[] = L"\\";
|
|
|
|
CRITICAL_SECTION DsrLock;
|
|
DWORD g_dwTraceId = 0;
|
|
DWORD g_dwTraceCount = 0;
|
|
|
|
//
|
|
// Initializes the trace mechanism
|
|
//
|
|
DWORD
|
|
DsrTraceInit()
|
|
{
|
|
EnterCriticalSection(&DsrLock);
|
|
|
|
if (g_dwTraceCount == 0)
|
|
{
|
|
g_dwTraceId = TraceRegisterA("MprDomain");
|
|
}
|
|
|
|
g_dwTraceCount++;
|
|
|
|
LeaveCriticalSection(&DsrLock);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Cleans up the trace mechansim
|
|
//
|
|
DWORD
|
|
DsrTraceCleanup()
|
|
{
|
|
EnterCriticalSection(&DsrLock);
|
|
|
|
if (g_dwTraceCount != 0)
|
|
{
|
|
g_dwTraceCount--;
|
|
|
|
if (g_dwTraceCount == 0)
|
|
{
|
|
TraceDeregisterA(g_dwTraceId);
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&DsrLock);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Sends debug trace and returns the given error
|
|
//
|
|
DWORD DsrTraceEx (
|
|
IN DWORD dwErr,
|
|
IN LPSTR pszTrace,
|
|
IN ...)
|
|
{
|
|
va_list arglist;
|
|
char szBuffer[1024], szTemp[1024];
|
|
|
|
va_start(arglist, pszTrace);
|
|
vsprintf(szTemp, pszTrace, arglist);
|
|
va_end(arglist);
|
|
|
|
sprintf(szBuffer, "Dsr: %s", szTemp);
|
|
|
|
TracePrintfA(g_dwTraceId, szBuffer);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Allocates memory for use with dsr functions
|
|
//
|
|
PVOID DsrAlloc(DWORD dwSize, BOOL bZero) {
|
|
return GlobalAlloc (bZero ? GPTR : GMEM_FIXED, dwSize);
|
|
}
|
|
|
|
//
|
|
// Free memory used by dsr functions
|
|
//
|
|
DWORD DsrFree(PVOID pvBuf) {
|
|
GlobalFree(pvBuf);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Initializes the dcr library
|
|
//
|
|
DWORD
|
|
DsrInit (
|
|
OUT DSRINFO * pDsrInfo,
|
|
IN PWCHAR pszMachineDomain,
|
|
IN PWCHAR pszMachine,
|
|
IN PWCHAR pszGroupDomain)
|
|
{
|
|
DWORD dwErr, dwSize;
|
|
HRESULT hr;
|
|
WCHAR pszBuf[1024];
|
|
|
|
// Validate parameters
|
|
if (pDsrInfo == NULL)
|
|
return ERROR_INVALID_PARAMETER;
|
|
ZeroMemory(pDsrInfo, sizeof(DSRINFO));
|
|
|
|
// Initialize Com
|
|
hr = CoInitialize(NULL);
|
|
if (FAILED (hr)) {
|
|
return DsrTraceEx(
|
|
hr,
|
|
"DsrInit: %x from CoInitialize",
|
|
hr);
|
|
}
|
|
|
|
// Generate the Group DN
|
|
dwErr = DsrFindRasServersGroup(
|
|
pszGroupDomain,
|
|
&(pDsrInfo->pszGroupDN));
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
// Generate the Machine DN
|
|
dwErr = DsrFindDomainComputer(
|
|
pszMachineDomain,
|
|
pszMachine,
|
|
&(pDsrInfo->pszMachineDN));
|
|
if (dwErr != NO_ERROR)
|
|
return dwErr;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Cleans up the dsr library
|
|
//
|
|
DWORD
|
|
DsrCleanup (DSRINFO * pDsrInfo)
|
|
{
|
|
if (pDsrInfo) {
|
|
DSR_FREE (pDsrInfo->pszGroupDN);
|
|
DSR_FREE (pDsrInfo->pszMachineDN);
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Establishes the given machine as being
|
|
// or not being a ras server in the domain.
|
|
//
|
|
// Parameters:
|
|
// pszMachine Name of the machine
|
|
// bEnable Whether it should or
|
|
// shouldn't be a ras server
|
|
//
|
|
DWORD DsrEstablishComputerAsDomainRasServer (
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
IN BOOL bEnable)
|
|
{
|
|
DSRINFO DsrInfo, *pDsrInfo = &DsrInfo;
|
|
PWCHAR pszMachineDomain = NULL;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
DsrTraceEx(
|
|
0,
|
|
"DsrEstablish...: entered: %S, %S, %x",
|
|
pszDomain,
|
|
pszMachine,
|
|
bEnable);
|
|
|
|
// Parse out the machine's domain.
|
|
pszMachineDomain = pszMachine;
|
|
pszMachine = wcsstr(pszMachine, pszMachineDelimeter);
|
|
if (pszMachine == NULL)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
*pszMachine = (WCHAR)0;
|
|
pszMachine++;
|
|
|
|
do
|
|
{
|
|
// Intialize the Dsr library
|
|
dwErr = DsrInit(
|
|
pDsrInfo,
|
|
pszMachineDomain,
|
|
pszMachine,
|
|
pszDomain);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
DsrTraceEx(dwErr, "DsrEstablish...: %x from DsrInit", dwErr);
|
|
break;
|
|
}
|
|
|
|
// Attempt to add the machine from the "Computers"
|
|
// container
|
|
dwErr = DsrGroupAddRemoveMember(
|
|
pDsrInfo->pszGroupDN,
|
|
pDsrInfo->pszMachineDN,
|
|
bEnable);
|
|
if (dwErr == ERROR_ALREADY_EXISTS)
|
|
{
|
|
dwErr = NO_ERROR;
|
|
}
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
DsrTraceEx(dwErr, "DsrEstablish...: %x from Add/Rem", dwErr);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
DsrCleanup (pDsrInfo);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Returns whether the given machine is a member of the remote
|
|
// access servers group.
|
|
//
|
|
DWORD
|
|
DsrIsMachineRasServerInDomain(
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
OUT PBOOL pbIsRasServer)
|
|
{
|
|
DSRINFO DsrInfo, *pDsrInfo = &DsrInfo;
|
|
PWCHAR pszMachineDomain = NULL;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
DsrTraceEx(0, "DsrIsRasServerInDomain: entered: %S", pszMachine);
|
|
|
|
// Parse out the machine's domain.
|
|
pszMachineDomain = pszMachine;
|
|
pszMachine = wcsstr(pszMachine, pszMachineDelimeter);
|
|
if (pszMachine == NULL)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
*pszMachine = (WCHAR)0;
|
|
pszMachine++;
|
|
|
|
do
|
|
{
|
|
// Intialize the Dsr library
|
|
dwErr = DsrInit(
|
|
pDsrInfo,
|
|
pszMachineDomain,
|
|
pszMachine,
|
|
pszDomain);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
DsrTraceEx(dwErr, "DsrIsRasSvrInDom: %x from DsrInit", dwErr);
|
|
break;
|
|
}
|
|
|
|
// Find out whether the machine is a member of the group
|
|
dwErr = DsrGroupIsMember(
|
|
pDsrInfo->pszGroupDN,
|
|
pDsrInfo->pszMachineDN,
|
|
pbIsRasServer);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
DsrTraceEx(dwErr, "DsrIsRasSrvInDom: %x from IsMemrGrp", dwErr);
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
DsrCleanup (pDsrInfo);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Prepares parameters for the DSR functions. pszDomainComputer
|
|
// will be in form <domain>/computer. pszDomain will point to a
|
|
// valid domain.
|
|
//
|
|
DWORD
|
|
GenerateDsrParameters(
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
OUT PWCHAR *ppszDomainComputer,
|
|
OUT PWCHAR *ppszGroupDomain)
|
|
{
|
|
DWORD dwLen, dwErr = NO_ERROR;
|
|
PWCHAR pszSlash = NULL;
|
|
PDOMAIN_CONTROLLER_INFO pInfo = NULL;
|
|
WCHAR pszTemp[MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
// Initailize
|
|
*ppszDomainComputer = pszMachine;
|
|
*ppszGroupDomain = pszDomain;
|
|
|
|
do {
|
|
// Lookup the current domain if none was specifed
|
|
if ((pszDomain == NULL) || (wcslen(pszDomain) == 0)) {
|
|
dwErr = DsGetDcName(
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DS_DIRECTORY_SERVICE_REQUIRED,
|
|
&pInfo);
|
|
if (dwErr != NO_ERROR)
|
|
break;
|
|
|
|
// Copy the given domain name
|
|
dwLen = wcslen(pInfo->DomainName) + 1;
|
|
dwLen *= sizeof (WCHAR);
|
|
*ppszGroupDomain = (PWCHAR) DsrAlloc(dwLen, FALSE);
|
|
if (*ppszGroupDomain == NULL) {
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
wcscpy(*ppszGroupDomain, pInfo->DomainName);
|
|
}
|
|
|
|
// Make sure that the machine name is in the form
|
|
// domain/computer
|
|
if (pszMachine)
|
|
pszSlash = wcsstr(pszMachine, pszMachineDelimeter);
|
|
if (!pszMachine || !pszSlash) {
|
|
// Get the domain name if it isn't already
|
|
// gotten
|
|
if (!pInfo) {
|
|
dwErr = DsGetDcName(
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DS_DIRECTORY_SERVICE_REQUIRED,
|
|
&pInfo);
|
|
if (dwErr != NO_ERROR)
|
|
break;
|
|
}
|
|
|
|
// Get the local computer name if no computer
|
|
// name was specified
|
|
if ((!pszMachine) || (wcslen(pszMachine) == 0)) {
|
|
dwLen = sizeof(pszTemp) / sizeof(WCHAR);
|
|
if (! GetComputerName(pszTemp, &dwLen)) {
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
pszMachine = pszTemp;
|
|
}
|
|
|
|
// Allocate the buffer to return the computer name
|
|
dwLen = wcslen(pInfo->DomainName) + wcslen(pszMachine) + 2;
|
|
dwLen *= sizeof(WCHAR);
|
|
*ppszDomainComputer = (PWCHAR) DsrAlloc(dwLen, FALSE);
|
|
if (*ppszDomainComputer == NULL) {
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
wsprintfW(
|
|
*ppszDomainComputer,
|
|
L"%s%s%s",
|
|
pInfo->DomainName,
|
|
pszMachineDelimeter,
|
|
pszMachine);
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (pInfo)
|
|
NetApiBufferFree(pInfo);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Establishes the given computer as a server in the domain.
|
|
// This function must be run under the context of a domain
|
|
// admin.
|
|
//
|
|
DWORD
|
|
WINAPI
|
|
MprAdminEstablishDomainRasServer (
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
IN BOOL bEnable)
|
|
{
|
|
return MprDomainRegisterRasServer(
|
|
pszDomain,
|
|
pszMachine,
|
|
bEnable);
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
MprAdminIsDomainRasServer (
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
OUT PBOOL pbIsRasServer)
|
|
{
|
|
return MprDomainQueryRasServer(
|
|
pszDomain,
|
|
pszMachine,
|
|
pbIsRasServer);
|
|
}
|
|
|
|
//
|
|
// Establishes the given computer as a server in the domain.
|
|
// This function must be run under the context of a domain
|
|
// admin.
|
|
//
|
|
DWORD
|
|
WINAPI
|
|
MprDomainRegisterRasServer (
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
IN BOOL bEnable)
|
|
{
|
|
PWCHAR pszDomainComputer, pszGroupDomain;
|
|
DWORD dwErr;
|
|
|
|
do
|
|
{
|
|
DsrTraceInit();
|
|
|
|
// Generate the parameters formatted so that
|
|
// the dsr functions will accept them.
|
|
dwErr = GenerateDsrParameters(
|
|
pszDomain,
|
|
pszMachine,
|
|
&pszDomainComputer,
|
|
&pszGroupDomain);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwErr = DsrEstablishComputerAsDomainRasServer (
|
|
pszGroupDomain,
|
|
pszDomainComputer,
|
|
bEnable);
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if ((pszDomainComputer) &&
|
|
(pszDomainComputer != pszMachine))
|
|
{
|
|
DsrFree(pszDomainComputer);
|
|
}
|
|
if ((pszGroupDomain) &&
|
|
(pszGroupDomain != pszDomain))
|
|
{
|
|
DsrFree(pszGroupDomain);
|
|
}
|
|
|
|
DsrTraceCleanup();
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Determines whether the given machine is an authorized ras
|
|
// server in the domain
|
|
//
|
|
DWORD
|
|
WINAPI
|
|
MprDomainQueryRasServer (
|
|
IN PWCHAR pszDomain,
|
|
IN PWCHAR pszMachine,
|
|
OUT PBOOL pbIsRasServer)
|
|
{
|
|
PWCHAR pszDomainComputer, pszGroupDomain;
|
|
DWORD dwErr;
|
|
|
|
do
|
|
{
|
|
DsrTraceInit();
|
|
|
|
// Generate the parameters formatted so that
|
|
// the dsr functions will accept them.
|
|
dwErr = GenerateDsrParameters(
|
|
pszDomain,
|
|
pszMachine,
|
|
&pszDomainComputer,
|
|
&pszGroupDomain);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Check the group membership
|
|
dwErr = DsrIsMachineRasServerInDomain(
|
|
pszGroupDomain,
|
|
pszDomainComputer,
|
|
pbIsRasServer);
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if ((pszDomainComputer) &&
|
|
(pszDomainComputer != pszMachine))
|
|
{
|
|
DsrFree(pszDomainComputer);
|
|
}
|
|
if ((pszGroupDomain) &&
|
|
(pszGroupDomain != pszDomain))
|
|
{
|
|
DsrFree(pszGroupDomain);
|
|
}
|
|
|
|
DsrTraceCleanup();
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Enables NT4 Servers in the given domain
|
|
//
|
|
DWORD
|
|
WINAPI
|
|
MprDomainSetAccess(
|
|
IN PWCHAR pszDomain,
|
|
IN DWORD dwAccessFlags)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
DsrTraceInit();
|
|
|
|
dwErr = DsrDomainSetAccess(pszDomain, dwAccessFlags);
|
|
|
|
DsrTraceCleanup();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Discovers whether NT4 Servers in the given domain
|
|
// are enabled.
|
|
//
|
|
DWORD
|
|
WINAPI
|
|
MprDomainQueryAccess(
|
|
IN PWCHAR pszDomain,
|
|
IN LPDWORD lpdwAccessFlags)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
DsrTraceInit();
|
|
|
|
dwErr = DsrDomainQueryAccess(pszDomain, lpdwAccessFlags);
|
|
|
|
DsrTraceCleanup();
|
|
|
|
return dwErr;
|
|
}
|
|
|