windows-nt/Source/XPSP1/NT/ds/security/gina/snapins/gptext/ipsecext.cpp
2020-09-26 16:20:57 +08:00

566 lines
12 KiB
C++

#include "gptext.h"
#include <initguid.h>
#include <iadsp.h>
#include "ipsecext.h"
#define GPEXT_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\{e437bc1c-aa7d-11d2-a382-00c04f991e27}")
#define POLICY_PATH TEXT("Software\\Policies\\Microsoft\\Windows\\IPSec\\GPTIPSECPolicy")
LPWSTR GetAttributes[] = {L"ipsecOwnersReference", L"ipsecName", L"description"};
HRESULT
RegisterIPSEC(void)
{
HKEY hKey;
LONG lResult;
DWORD dwDisp, dwValue;
TCHAR szBuffer[512];
lResult = RegCreateKeyEx (
HKEY_LOCAL_MACHINE,
GPEXT_PATH,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp
);
if (lResult != ERROR_SUCCESS)
{
return lResult;
}
LoadString (g_hInstance, IDS_IPSEC_NAME, szBuffer, ARRAYSIZE(szBuffer));
RegSetValueEx (
hKey,
NULL,
0,
REG_SZ,
(LPBYTE)szBuffer,
(lstrlen(szBuffer) + 1) * sizeof(TCHAR)
);
RegSetValueEx (
hKey,
TEXT("ProcessGroupPolicy"),
0,
REG_SZ,
(LPBYTE)TEXT("ProcessIPSECPolicy"),
(lstrlen(TEXT("ProcessIPSECPolicy")) + 1) * sizeof(TCHAR)
);
szBuffer[0] = L'\0';
wcscpy(szBuffer, L"gptext.dll");
RegSetValueEx (
hKey,
TEXT("DllName"),
0,
REG_EXPAND_SZ,
(LPBYTE)szBuffer,
(lstrlen(szBuffer) + 1) * sizeof(TCHAR)
);
dwValue = 1;
RegSetValueEx (
hKey,
TEXT("NoUserPolicy"),
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue));
RegSetValueEx (
hKey,
TEXT("NoGPOListChanges"),
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue));
RegCloseKey (hKey);
return S_OK;
}
HRESULT
UnregisterIPSEC(void)
{
RegDeleteKey (HKEY_LOCAL_MACHINE, GPEXT_PATH);
return S_OK;
}
DWORD WINAPI
ProcessIPSECPolicy(
IN DWORD dwFlags, // GPO_INFO_FLAGS
IN HANDLE hToken, // User or machine token
IN HKEY hKeyRoot, // Root of registry
IN PGROUP_POLICY_OBJECT pDeletedGPOList, // Linked list of deleted GPOs
IN PGROUP_POLICY_OBJECT pChangedGPOList, // Linked list of changed GPOs
IN ASYNCCOMPLETIONHANDLE pHandle, // For asynchronous completion
IN BOOL *pbAbort, // If true, then abort GPO processing
IN PFNSTATUSMESSAGECALLBACK pStatusCallback // Callback function for displaying status messages
)
{
WCHAR szIPSECPolicy[MAX_PATH];
WCHAR szIPSECPolicyName[MAX_PATH];
WCHAR szIPSECPolicyDescription[512];
HRESULT hr = S_OK;
PGROUP_POLICY_OBJECT pGPO = NULL;
//
// Call CoInitialize for all the COM work we're doing
//
hr = CoInitializeEx(NULL,0);
if (FAILED(hr)) {
goto error;
}
memset(szIPSECPolicy, 0, sizeof(WCHAR)*MAX_PATH);
memset(szIPSECPolicyName, 0, sizeof(WCHAR)*MAX_PATH);
memset(szIPSECPolicyDescription, 0, sizeof(WCHAR)*512);
//
// First process the Deleted GPO List. If there is a single
// entry on the GPO list, just delete the entire list.
// Example Rex->Cassius->Brutus. If the delete List has
// Cassius to be deleted, then really, we shouldn't be deleting
// our registry entry because we're interested in Brutus which
// has not be deleted. But in our case, the pChangedGPOList will
// have all the information, so Brutus gets written back in the
// next stage.
//
if (pDeletedGPOList) {
DeleteIPSECPolicyFromRegistry();
}
pGPO = pChangedGPOList;
//
// Since IPSEC is really interested in the last
// GPO only, loop through till we hit the last
// GPO and write that GPO only. In this case, Brutus now
// gets written back into the registry.
//
if (pChangedGPOList) {
while (pGPO->pNext)
{
pGPO = pGPO->pNext;
}
//
// Now write the last GPOs information
//
hr = RetrieveIPSECPolicyFromDS(
pGPO,
szIPSECPolicy,
szIPSECPolicyName,
szIPSECPolicyDescription
);
if (FAILED(hr)) {
goto error;
}
hr = WriteIPSECPolicyToRegistry(
szIPSECPolicy,
szIPSECPolicyName,
szIPSECPolicyDescription
);
if (FAILED(hr)) {
goto error;
}
}
PingPolicyAgent();
CoUninitialize();
return(ERROR_SUCCESS);
error:
return(ERROR_POLICY_OBJECT_NOT_FOUND);
}
HRESULT
CreateChildPath(
LPWSTR pszParentPath,
LPWSTR pszChildComponent,
BSTR * ppszChildPath
)
{
HRESULT hr = S_OK;
IADsPathname *pPathname = NULL;
hr = CoCreateInstance(
CLSID_Pathname,
NULL,
CLSCTX_ALL,
IID_IADsPathname,
(void**)&pPathname
);
BAIL_ON_FAILURE(hr);
hr = pPathname->Set(pszParentPath, ADS_SETTYPE_FULL);
BAIL_ON_FAILURE(hr);
hr = pPathname->AddLeafElement(pszChildComponent);
BAIL_ON_FAILURE(hr);
hr = pPathname->Retrieve(ADS_FORMAT_X500, ppszChildPath);
BAIL_ON_FAILURE(hr);
error:
if (pPathname) {
pPathname->Release();
}
return(hr);
}
HRESULT
RetrieveIPSECPolicyFromDS(
PGROUP_POLICY_OBJECT pGPOInfo,
LPWSTR pszIPSecPolicy,
LPWSTR pszIPSecPolicyName,
LPWSTR pszIPSecPolicyDescription
)
{
LPWSTR pszMachinePath = NULL;
BSTR pszMicrosoftPath = NULL;
BSTR pszWindowsPath = NULL;
BSTR pszIpsecPath = NULL;
IDirectoryObject * pDirectoryObject = NULL;
IDirectoryObject * pIpsecObject = NULL;
BOOL bFound = FALSE;
LPWSTR pszOwnersReference = L"ipsecOwnersReference";
HRESULT hr = S_OK;
PADS_ATTR_INFO pAttributeEntries = NULL;
DWORD dwNumAttributesReturned = 0;
DWORD i = 0;
PADS_ATTR_INFO pAttributeEntry = NULL;
pszMachinePath = pGPOInfo->lpDSPath;
// Build the fully qualified ADsPath for my object
hr = CreateChildPath(
pszMachinePath,
L"cn=Microsoft",
&pszMicrosoftPath
);
BAIL_ON_FAILURE(hr);
hr = CreateChildPath(
pszMicrosoftPath,
L"cn=Windows",
&pszWindowsPath
);
BAIL_ON_FAILURE(hr);
hr = CreateChildPath(
pszWindowsPath,
L"cn=ipsec",
&pszIpsecPath
);
BAIL_ON_FAILURE(hr);
hr = ADsGetObject(
pszIpsecPath,
IID_IDirectoryObject,
(void **)&pIpsecObject
);
BAIL_ON_FAILURE(hr);
hr = pIpsecObject->GetObjectAttributes(
GetAttributes,
3,
&pAttributeEntries,
&dwNumAttributesReturned
);
BAIL_ON_FAILURE(hr);
if (dwNumAttributesReturned == 0) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
//
// Process the PathName
//
for (i = 0; i < dwNumAttributesReturned; i++) {
pAttributeEntry = pAttributeEntries + i;
if (!_wcsicmp(pAttributeEntry->pszAttrName, L"ipsecOwnersReference")) {
wcscpy(pszIPSecPolicy, L"LDAP://");
wcscat(pszIPSecPolicy, pAttributeEntry->pADsValues->DNString);
bFound = TRUE;
break;
}
}
if (!bFound) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
//
// Process the name
//
for (i = 0; i < dwNumAttributesReturned; i++) {
pAttributeEntry = pAttributeEntries + i;
if (!_wcsicmp(pAttributeEntry->pszAttrName, L"ipsecName")) {
wcscat(pszIPSecPolicyName, pAttributeEntry->pADsValues->DNString);
break;
}
}
//
// Process the description
//
for (i = 0; i < dwNumAttributesReturned; i++) {
pAttributeEntry = pAttributeEntries + i;
if (!_wcsicmp(pAttributeEntry->pszAttrName, L"description")) {
wcscat(pszIPSecPolicyDescription, pAttributeEntry->pADsValues->DNString);
break;
}
}
error:
if (pAttributeEntries) {
FreeADsMem(pAttributeEntries);
}
if (pIpsecObject) {
pIpsecObject->Release();
}
if (pszMicrosoftPath) {
SysFreeString(pszMicrosoftPath);
}
if (pszWindowsPath) {
SysFreeString(pszWindowsPath);
}
if (pszIpsecPath) {
SysFreeString(pszIpsecPath);
}
return(hr);
}
DWORD
DeleteIPSECPolicyFromRegistry(
)
{
DWORD dwError = 0;
HKEY hKey = NULL;
DWORD dwDisp = 0;
dwError = RegCreateKeyEx (
HKEY_LOCAL_MACHINE,
TEXT("Software\\Policies\\Microsoft\\Windows\\IPSec"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisp
);
if (dwError) {
goto error;
}
dwError = RegDeleteKey(
hKey,
L"GPTIPSECPolicy"
);
/*
dwError = RegDeleteValue(
hKey,
TEXT("DSIPSECPolicyPath")
);
dwError = RegDeleteValue(
hKey,
TEXT("DSIPSECPolicyName")
);*/
error:
if (hKey) {
RegCloseKey (hKey);
}
return(dwError);
}
DWORD
WriteIPSECPolicyToRegistry(
LPWSTR pszIPSecPolicyPath,
LPWSTR pszIPSecPolicyName,
LPWSTR pszIPSecPolicyDescription
)
{
DWORD dwError = 0;
DWORD dwDisp = 0;
HKEY hKey = NULL;
DWORD dwFlags = 1;
dwError = RegCreateKeyEx (
HKEY_LOCAL_MACHINE,
POLICY_PATH,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisp
);
if (dwError) {
goto error;
}
if (pszIPSecPolicyPath && *pszIPSecPolicyPath) {
dwError = RegSetValueEx (
hKey,
TEXT("DSIPSECPolicyPath"),
0,
REG_SZ,
(LPBYTE)pszIPSecPolicyPath,
(lstrlen(pszIPSecPolicyPath) + 1) * sizeof(TCHAR)
);
dwFlags = 1;
dwError = RegSetValueEx (
hKey,
TEXT("DSIPSECPolicyFlags"),
0,
REG_DWORD,
(LPBYTE)&dwFlags,
sizeof(dwFlags)
);
}
if (pszIPSecPolicyName && *pszIPSecPolicyName) {
dwError = RegSetValueEx (
hKey,
TEXT("DSIPSECPolicyName"),
0,
REG_SZ,
(LPBYTE)pszIPSecPolicyName,
(lstrlen(pszIPSecPolicyName) + 1) * sizeof(TCHAR)
);
}
if (pszIPSecPolicyDescription && *pszIPSecPolicyDescription) {
dwError = RegSetValueEx (
hKey,
TEXT("DSIPSECPolicyDescription"),
0,
REG_SZ,
(LPBYTE)pszIPSecPolicyDescription,
(lstrlen(pszIPSecPolicyDescription) + 1) * sizeof(TCHAR)
);
}
error:
if (hKey) {
RegCloseKey (hKey);
}
return(dwError);
}
VOID
PingPolicyAgent(
)
{
HANDLE hPolicyChangeEvent = NULL;
hPolicyChangeEvent = OpenEvent(
EVENT_ALL_ACCESS,
FALSE,
L"IPSEC_POLICY_CHANGE_EVENT"
);
if (hPolicyChangeEvent) {
SetEvent(hPolicyChangeEvent);
CloseHandle(hPolicyChangeEvent);
}
}