1995 lines
42 KiB
C
1995 lines
42 KiB
C
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
driver.c
|
|
|
|
Abstract:
|
|
|
|
This module contains all of the code to drive the
|
|
management of specific filters in the IPSec driver.
|
|
|
|
Author:
|
|
|
|
abhisheV 05-November-1999
|
|
|
|
Environment
|
|
|
|
User Level: Win32
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
DWORD
|
|
SPDStartIPSecDriver(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Starts the IPSec Driver service.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
SC_HANDLE ServiceDatabase = NULL;
|
|
SC_HANDLE ServiceHandle = NULL;
|
|
BOOL bStatus = FALSE;
|
|
DWORD dwError = 0;
|
|
SERVICE_STATUS IpsecStatus;
|
|
|
|
|
|
memset(&IpsecStatus, 0, sizeof(SERVICE_STATUS));
|
|
|
|
|
|
ServiceDatabase = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
if (ServiceDatabase == NULL) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
ServiceHandle = OpenService(
|
|
ServiceDatabase,
|
|
IPSEC_SERVICE_NAME,
|
|
SERVICE_START | SERVICE_QUERY_STATUS
|
|
);
|
|
if (ServiceHandle == NULL) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
bStatus = QueryServiceStatus(
|
|
ServiceHandle,
|
|
&IpsecStatus
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
if (IpsecStatus.dwCurrentState == SERVICE_STOPPED) {
|
|
|
|
bStatus = StartService(
|
|
ServiceHandle,
|
|
0,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (ServiceDatabase != NULL) {
|
|
CloseServiceHandle(ServiceDatabase);
|
|
}
|
|
|
|
if (ServiceHandle != NULL) {
|
|
CloseServiceHandle(ServiceHandle);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
SPDStopIPSecDriver(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Stops the IPSec Driver service.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
SC_HANDLE ServiceDatabase = NULL;
|
|
SC_HANDLE ServiceHandle = NULL;
|
|
BOOL bStatus = FALSE;
|
|
DWORD dwError = 0;
|
|
SERVICE_STATUS IpsecStatus;
|
|
|
|
|
|
memset(&IpsecStatus, 0, sizeof(SERVICE_STATUS));
|
|
|
|
|
|
ServiceDatabase = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
if (ServiceDatabase == NULL) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
ServiceHandle = OpenService(
|
|
ServiceDatabase,
|
|
IPSEC_SERVICE_NAME,
|
|
SERVICE_STOP | SERVICE_QUERY_STATUS
|
|
);
|
|
if (ServiceHandle == NULL) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
bStatus = QueryServiceStatus(
|
|
ServiceHandle,
|
|
&IpsecStatus
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
if (IpsecStatus.dwCurrentState == SERVICE_RUNNING) {
|
|
|
|
bStatus = ControlService(
|
|
ServiceHandle,
|
|
SERVICE_CONTROL_STOP,
|
|
&IpsecStatus
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (ServiceDatabase != NULL) {
|
|
CloseServiceHandle(ServiceDatabase);
|
|
}
|
|
|
|
if (ServiceHandle != NULL) {
|
|
CloseServiceHandle(ServiceHandle);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
SPDOpenIPSecDriver(
|
|
PHANDLE phIPSecDriver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens a handle to the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
phIPSecDriver - pointer to a handle to the IPSec Driver.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
|
|
|
|
hIPSecDriver = CreateFile(
|
|
DEVICE_NAME, // File name.
|
|
GENERIC_READ | GENERIC_WRITE, // Access mode.
|
|
0, // Share mode.
|
|
NULL, // Security attributes.
|
|
OPEN_EXISTING, // How to create.
|
|
0, // File attributes.
|
|
NULL // Handle to file.
|
|
);
|
|
if (hIPSecDriver == INVALID_HANDLE_VALUE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
*phIPSecDriver = hIPSecDriver;
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
*phIPSecDriver = INVALID_HANDLE_VALUE;
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
VOID
|
|
SPDCloseIPSecDriver(
|
|
HANDLE hIPSecDriver
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Closes the handle to the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
hIPSecDriver - handle to the IPSec Driver to close.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if (hIPSecDriver) {
|
|
CloseHandle(hIPSecDriver);
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
InsertTransportFiltersIntoIPSec(
|
|
PINITXSFILTER pSpecificFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insert a list of specific filters into the
|
|
IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to insert.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
|
|
BOOL bStatus = FALSE;
|
|
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DWORD dwNumFilters = 0;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
LPBYTE pTemp = NULL;
|
|
DWORD i = 0;
|
|
|
|
|
|
if (!pSpecificFilters) {
|
|
return (dwError);
|
|
}
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwError = WrapTransportFilters(
|
|
pSpecificFilters,
|
|
&pInternalFilters,
|
|
&dwNumFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwInBufferSize = sizeof(DWORD) +
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters;
|
|
|
|
dwError = AllocateSPDMemory(
|
|
dwInBufferSize,
|
|
&pInBuffer
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTemp = pInBuffer;
|
|
memcpy(pTemp, &dwNumFilters, sizeof(DWORD));
|
|
pTemp += sizeof(DWORD);
|
|
|
|
for (i = 0 ; i < dwNumFilters; i++) {
|
|
|
|
memcpy(pTemp, &(pInternalFilters[i]), sizeof(IPSEC_FILTER_INFO));
|
|
pTemp += sizeof(IPSEC_FILTER_INFO);
|
|
|
|
}
|
|
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_ADD_FILTER,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pInternalFilters) {
|
|
FreeSPDMemory(pInternalFilters);
|
|
}
|
|
|
|
if (pInBuffer) {
|
|
FreeSPDMemory(pInBuffer);
|
|
}
|
|
|
|
if (pOutBuffer) {
|
|
LocalFree(pOutBuffer);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DeleteTransportFiltersFromIPSec(
|
|
PINITXSFILTER pSpecificFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a list of filters from the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to delete.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
|
|
BOOL bStatus = FALSE;
|
|
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DWORD dwNumFilters = 0;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
LPBYTE pTemp = NULL;
|
|
DWORD i = 0;
|
|
|
|
|
|
if (!pSpecificFilters) {
|
|
return (dwError);
|
|
}
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwError = WrapTransportFilters(
|
|
pSpecificFilters,
|
|
&pInternalFilters,
|
|
&dwNumFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwInBufferSize = sizeof(DWORD) +
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters;
|
|
|
|
dwError = AllocateSPDMemory(
|
|
dwInBufferSize,
|
|
&pInBuffer
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTemp = pInBuffer;
|
|
memcpy(pTemp, &dwNumFilters, sizeof(DWORD));
|
|
pTemp += sizeof(DWORD);
|
|
|
|
for (i = 0 ; i < dwNumFilters; i++) {
|
|
|
|
memcpy(pTemp, &(pInternalFilters[i]), sizeof(IPSEC_FILTER_INFO));
|
|
pTemp += sizeof(IPSEC_FILTER_INFO);
|
|
|
|
}
|
|
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_DELETE_FILTER,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pInternalFilters) {
|
|
FreeSPDMemory(pInternalFilters);
|
|
}
|
|
|
|
if (pInBuffer) {
|
|
FreeSPDMemory(pInBuffer);
|
|
}
|
|
|
|
if (pOutBuffer) {
|
|
LocalFree(pOutBuffer);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WrapTransportFilters(
|
|
PINITXSFILTER pSpecificFilters,
|
|
PIPSEC_FILTER_INFO * ppInternalFilters,
|
|
PDWORD pdwNumFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Transforms a list of specific transport filters to
|
|
an equivalent list of filters acceptable to the
|
|
IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to convert.
|
|
|
|
ppInternalFilters - list of transformed filters.
|
|
|
|
pdwNumFilters - count of the filters in the transformed
|
|
list.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
PINITXSFILTER pTempFilter = NULL;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
DWORD dwNumFilters = 0;
|
|
DWORD i = 0;
|
|
|
|
|
|
//
|
|
// At this point, there's atleast one filter in the
|
|
// specific filter list.
|
|
//
|
|
|
|
pTempFilter = pSpecificFilters;
|
|
|
|
while(pTempFilter) {
|
|
pTempFilter = pTempFilter->pNext;
|
|
dwNumFilters++;
|
|
}
|
|
|
|
|
|
dwError = AllocateSPDMemory(
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters,
|
|
&pInternalFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTempFilter = pSpecificFilters;
|
|
|
|
while(pTempFilter) {
|
|
|
|
FormIPSecTransportFilter(
|
|
pTempFilter,
|
|
&(pInternalFilters[i])
|
|
);
|
|
|
|
pTempFilter = pTempFilter->pNext;
|
|
i++;
|
|
|
|
}
|
|
|
|
*ppInternalFilters = pInternalFilters;
|
|
*pdwNumFilters = dwNumFilters;
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
*ppInternalFilters = NULL;
|
|
*pdwNumFilters = 0;
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
VOID
|
|
FormIPSecTransportFilter(
|
|
PINITXSFILTER pSpecificFilter,
|
|
PIPSEC_FILTER_INFO pIpsecFilter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Transforms a specific transport filter to an
|
|
equivalent filter acceptable to the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilter - filter to convert.
|
|
|
|
pIpsecFilter - transformed filter.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
memcpy(
|
|
&(pIpsecFilter->FilterId),
|
|
&(pSpecificFilter->gParentID),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
memcpy(
|
|
&(pIpsecFilter->PolicyId),
|
|
&(pSpecificFilter->gPolicyID),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
pIpsecFilter->Index = pSpecificFilter->dwWeight;
|
|
|
|
pIpsecFilter->AssociatedFilter.SrcAddr = pSpecificFilter->SrcAddr.uIpAddr;
|
|
pIpsecFilter->AssociatedFilter.SrcMask = pSpecificFilter->SrcAddr.uSubNetMask;
|
|
|
|
pIpsecFilter->AssociatedFilter.DestAddr = pSpecificFilter->DesAddr.uIpAddr;
|
|
pIpsecFilter->AssociatedFilter.DestMask = pSpecificFilter->DesAddr.uSubNetMask;
|
|
|
|
pIpsecFilter->AssociatedFilter.Protocol = pSpecificFilter->Protocol.dwProtocol;
|
|
pIpsecFilter->AssociatedFilter.SrcPort = pSpecificFilter->SrcPort.wPort;
|
|
pIpsecFilter->AssociatedFilter.DestPort = pSpecificFilter->DesPort.wPort;
|
|
|
|
pIpsecFilter->AssociatedFilter.TunnelFilter = FALSE;
|
|
pIpsecFilter->AssociatedFilter.TunnelAddr = 0;
|
|
|
|
pIpsecFilter->AssociatedFilter.Flags = 0;
|
|
|
|
if (pSpecificFilter->dwDirection == FILTER_DIRECTION_INBOUND) {
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_INBOUND;
|
|
switch (pSpecificFilter->InboundFilterFlag) {
|
|
|
|
case PASS_THRU:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_PASS_THRU;
|
|
break;
|
|
|
|
case BLOCKING:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_DROP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_OUTBOUND;
|
|
switch (pSpecificFilter->OutboundFilterFlag) {
|
|
|
|
case PASS_THRU:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_PASS_THRU;
|
|
break;
|
|
|
|
case BLOCKING:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_DROP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
QueryIPSecStatistics(
|
|
LPWSTR pServerName,
|
|
PIPSEC_STATISTICS * ppIpsecStatistics
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
PIPSEC_STATISTICS pIpsecStatistics = NULL;
|
|
|
|
|
|
ENTER_SPD_SECTION();
|
|
dwError = ValidateSecurity(
|
|
SPD_OBJECT_SERVER,
|
|
SERVER_ACCESS_ADMINISTER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
LEAVE_SPD_SECTION();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
dwError = QueryDriverForIpsecStats(
|
|
&pIpsecStatistics
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
*ppIpsecStatistics = pIpsecStatistics;
|
|
|
|
cleanup:
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
*ppIpsecStatistics = NULL;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
DWORD
|
|
QueryDriverForIpsecStats(
|
|
PIPSEC_QUERY_STATS * ppQueryStats
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
PIPSEC_QUERY_STATS pQueryStats = NULL;
|
|
HANDLE hIPSecDriver = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
BOOL bStatus = FALSE;
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
|
|
dwError = SPDApiBufferAllocate(
|
|
sizeof(IPSEC_QUERY_STATS),
|
|
&pQueryStats
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pInBuffer = (LPBYTE) pQueryStats;
|
|
dwInBufferSize = sizeof(IPSEC_QUERY_STATS);
|
|
|
|
pOutBuffer = (LPBYTE) pQueryStats;
|
|
dwOutBufferSize = sizeof(IPSEC_QUERY_STATS);
|
|
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_QUERY_STATS,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
*ppQueryStats = pQueryStats;
|
|
|
|
cleanup:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
if (pQueryStats) {
|
|
SPDApiBufferFree(pQueryStats);
|
|
}
|
|
|
|
*ppQueryStats = NULL;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
DWORD
|
|
EnumQMSAs(
|
|
LPWSTR pServerName,
|
|
PIPSEC_QM_SA pQMSATemplate,
|
|
PIPSEC_QM_SA * ppQMSAs,
|
|
DWORD dwPreferredNumEntries,
|
|
LPDWORD pdwNumQMSAs,
|
|
LPDWORD pdwNumTotalQMSAs,
|
|
LPDWORD pdwResumeHandle,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
DWORD dwResumeHandle = 0;
|
|
DWORD dwNumToEnum = 0;
|
|
DWORD dwNumTotalQMSAs = 0;
|
|
PIPSEC_ENUM_SAS pIpsecEnumSAs = NULL;
|
|
PIPSEC_SA_INFO pInfo = NULL;
|
|
DWORD i = 0;
|
|
DWORD dwNumQMSAs = 0;
|
|
PIPSEC_QM_SA pQMSAs = NULL;
|
|
PIPSEC_SA_INFO pTemp = NULL;
|
|
PIPSEC_QM_SA pTempQMSA = NULL;
|
|
|
|
|
|
dwResumeHandle = *pdwResumeHandle;
|
|
|
|
if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_QMSA_ENUM_COUNT)) {
|
|
dwNumToEnum = MAX_QMSA_ENUM_COUNT;
|
|
}
|
|
else {
|
|
dwNumToEnum = dwPreferredNumEntries;
|
|
}
|
|
|
|
ENTER_SPD_SECTION();
|
|
dwError = ValidateSecurity(
|
|
SPD_OBJECT_SERVER,
|
|
SERVER_ACCESS_ADMINISTER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
LEAVE_SPD_SECTION();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
dwError = IpsecEnumSAs(
|
|
&dwNumTotalQMSAs,
|
|
&pIpsecEnumSAs
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
if (dwNumTotalQMSAs <= dwResumeHandle) {
|
|
dwError = ERROR_NO_DATA;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
pInfo = pIpsecEnumSAs->pInfo;
|
|
|
|
for (i = 0; i < dwResumeHandle; i++) {
|
|
pInfo++;
|
|
}
|
|
|
|
dwNumQMSAs = dwNumTotalQMSAs - dwResumeHandle;
|
|
|
|
if (dwNumQMSAs > dwNumToEnum) {
|
|
dwNumQMSAs = dwNumToEnum;
|
|
}
|
|
|
|
dwError = SPDApiBufferAllocate(
|
|
sizeof(IPSEC_QM_SA)*dwNumQMSAs,
|
|
&pQMSAs
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pTemp = pInfo;
|
|
pTempQMSA = pQMSAs;
|
|
|
|
for (i = 0; i < dwNumQMSAs; i++) {
|
|
|
|
dwError = CopyQMSA(
|
|
pTemp,
|
|
pTempQMSA
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pTemp++;
|
|
pTempQMSA++;
|
|
|
|
}
|
|
|
|
*ppQMSAs = pQMSAs;
|
|
*pdwResumeHandle = dwResumeHandle + dwNumQMSAs;
|
|
*pdwNumQMSAs = dwNumQMSAs;
|
|
*pdwNumTotalQMSAs = dwNumTotalQMSAs;
|
|
|
|
cleanup:
|
|
|
|
if (pIpsecEnumSAs) {
|
|
FreeSPDMem(pIpsecEnumSAs);
|
|
}
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
if (pQMSAs) {
|
|
FreeQMSAs(
|
|
i,
|
|
pQMSAs
|
|
);
|
|
}
|
|
|
|
*ppQMSAs = NULL;
|
|
*pdwResumeHandle = dwResumeHandle;
|
|
*pdwNumQMSAs = 0;
|
|
*pdwNumTotalQMSAs = 0;
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IpsecEnumSAs(
|
|
PDWORD pdwNumberOfSAs,
|
|
PIPSEC_ENUM_SAS * ppIpsecEnumSAs
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
DWORD dwNumberOfSAs = 0;
|
|
PIPSEC_ENUM_SAS pIpsecEnumSAs = NULL;
|
|
HANDLE hIPSecDriver = NULL;
|
|
BOOL bStatus = FALSE;
|
|
PIPSEC_ENUM_SAS pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
//
|
|
// The first call passes in a return buffer of size IPSEC_ENUM_SAS.
|
|
// The idea here is to determine the number of SAs and then pass
|
|
// a second buffer with the correct size.
|
|
//
|
|
|
|
dwOutBufferSize = sizeof(IPSEC_ENUM_SAS);
|
|
|
|
pOutBuffer = (PIPSEC_ENUM_SAS) AllocSPDMem(
|
|
sizeof(IPSEC_ENUM_SAS)
|
|
);
|
|
if (!pOutBuffer) {
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
memset(pOutBuffer, 0, dwOutBufferSize);
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_ENUM_SAS,
|
|
NULL,
|
|
0,
|
|
(PVOID) pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// The error code here should be either ERROR_BUFFER_OVERFLOW
|
|
// or ERROR_MORE_DATA or ERROR_SUCCESS.
|
|
//
|
|
|
|
if (!bStatus) {
|
|
dwError = GetLastError();
|
|
}
|
|
else {
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
while (dwError == ERROR_BUFFER_OVERFLOW || dwError == ERROR_MORE_DATA) {
|
|
|
|
//
|
|
// Determine the number of SAs that the driver currently has.
|
|
//
|
|
|
|
pIpsecEnumSAs = (PIPSEC_ENUM_SAS) pOutBuffer;
|
|
dwNumberOfSAs = pIpsecEnumSAs->NumEntriesPresent;
|
|
|
|
if (dwNumberOfSAs == 0) {
|
|
dwError = ERROR_NO_DATA;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
if (pOutBuffer) {
|
|
FreeSPDMem(pOutBuffer);
|
|
pOutBuffer = NULL;
|
|
}
|
|
|
|
dwOutBufferSize = sizeof(IPSEC_ENUM_SAS)
|
|
+ (dwNumberOfSAs -1)*sizeof(IPSEC_SA_INFO);
|
|
|
|
pOutBuffer = (PIPSEC_ENUM_SAS) AllocSPDMem(
|
|
dwOutBufferSize
|
|
);
|
|
if (!pOutBuffer) {
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
memset(pOutBuffer, 0, dwOutBufferSize);
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_ENUM_SAS,
|
|
NULL,
|
|
0,
|
|
(PVOID) pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
|
|
if (!bStatus) {
|
|
dwError = GetLastError();
|
|
}
|
|
else {
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
}
|
|
|
|
pIpsecEnumSAs = (PIPSEC_ENUM_SAS) pOutBuffer;
|
|
dwNumberOfSAs = pIpsecEnumSAs->NumEntries;
|
|
|
|
if (dwNumberOfSAs == 0) {
|
|
dwError = ERROR_NO_DATA;
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
*pdwNumberOfSAs = dwNumberOfSAs;
|
|
*ppIpsecEnumSAs = pIpsecEnumSAs;
|
|
|
|
cleanup:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
*pdwNumberOfSAs = 0;
|
|
*ppIpsecEnumSAs = NULL;
|
|
|
|
if (pOutBuffer) {
|
|
FreeSPDMem(pOutBuffer);
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CopyQMSA(
|
|
PIPSEC_SA_INFO pInfo,
|
|
PIPSEC_QM_SA pQMSA
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
|
|
|
|
memcpy(
|
|
&(pQMSA->gQMPolicyID),
|
|
&(pInfo->PolicyId),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
memcpy(
|
|
&(pQMSA->gQMFilterID),
|
|
&(pInfo->FilterId),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
CopyQMSAOffer(
|
|
pInfo,
|
|
&(pQMSA->SelectedQMOffer)
|
|
);
|
|
|
|
CopyQMSAFilter(
|
|
pInfo->InboundTunnelAddr,
|
|
&(pInfo->AssociatedFilter),
|
|
&(pQMSA->IpsecQMFilter)
|
|
);
|
|
|
|
CopyQMSAMMSpi(
|
|
pInfo->CookiePair,
|
|
&(pQMSA->MMSpi)
|
|
);
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
VOID
|
|
CopyQMSAOffer(
|
|
PIPSEC_SA_INFO pInfo,
|
|
PIPSEC_QM_OFFER pOffer
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
DWORD j = 0;
|
|
DWORD k = 0;
|
|
|
|
|
|
pOffer->Lifetime.uKeyExpirationTime =
|
|
pInfo->Lifetime.KeyExpirationTime;
|
|
|
|
pOffer->Lifetime.uKeyExpirationKBytes =
|
|
pInfo->Lifetime.KeyExpirationBytes;
|
|
|
|
pOffer->dwFlags = 0;
|
|
|
|
pOffer->dwPFSGroup = pInfo->dwQMPFSGroup;
|
|
|
|
if ((pOffer->dwPFSGroup != PFS_GROUP_1) &&
|
|
(pOffer->dwPFSGroup != PFS_GROUP_2) &&
|
|
(pOffer->dwPFSGroup != PFS_GROUP_MM)) {
|
|
pOffer->dwPFSGroup = PFS_GROUP_NONE;
|
|
pOffer->bPFSRequired = FALSE;
|
|
}
|
|
else {
|
|
pOffer->bPFSRequired = TRUE;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
for (j = 0; (j < pInfo->NumOps) && (i < QM_MAX_ALGOS) ; j++) {
|
|
|
|
switch (pInfo->Operation[j]) {
|
|
|
|
case Auth:
|
|
|
|
switch (pInfo->AlgoInfo[j].IntegrityAlgo.algoIdentifier) {
|
|
|
|
case IPSEC_AH_MD5:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_MD5;
|
|
break;
|
|
|
|
case IPSEC_AH_SHA:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_SHA1;
|
|
break;
|
|
|
|
default:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_AH_NONE;
|
|
break;
|
|
|
|
}
|
|
|
|
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_NONE;
|
|
|
|
pOffer->Algos[i].Operation = AUTHENTICATION;
|
|
|
|
pOffer->Algos[i].uAlgoKeyLen =
|
|
pInfo->AlgoInfo[j].IntegrityAlgo.algoKeylen;
|
|
|
|
pOffer->Algos[i].uAlgoRounds =
|
|
pInfo->AlgoInfo[j].IntegrityAlgo.algoRounds;
|
|
|
|
pOffer->Algos[i].MySpi = pInfo->InboundSPI[j];
|
|
pOffer->Algos[i].PeerSpi = pInfo->OutboundSPI[j];
|
|
|
|
i++;
|
|
break;
|
|
|
|
case Encrypt:
|
|
|
|
switch (pInfo->AlgoInfo[j].ConfAlgo.algoIdentifier) {
|
|
|
|
case IPSEC_ESP_DES:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|
break;
|
|
|
|
case IPSEC_ESP_DES_40:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_DES;
|
|
break;
|
|
|
|
case IPSEC_ESP_3_DES:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_3_DES;
|
|
break;
|
|
|
|
default:
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_NONE;
|
|
break;
|
|
|
|
}
|
|
|
|
switch (pInfo->AlgoInfo[j].IntegrityAlgo.algoIdentifier) {
|
|
|
|
case IPSEC_AH_MD5:
|
|
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_MD5;
|
|
break;
|
|
|
|
case IPSEC_AH_SHA:
|
|
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_SHA1;
|
|
break;
|
|
|
|
default:
|
|
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_NONE;
|
|
break;
|
|
|
|
}
|
|
|
|
pOffer->Algos[i].Operation = ENCRYPTION;
|
|
|
|
pOffer->Algos[i].uAlgoKeyLen =
|
|
pInfo->AlgoInfo[j].ConfAlgo.algoKeylen;
|
|
|
|
pOffer->Algos[i].uAlgoRounds =
|
|
pInfo->AlgoInfo[j].ConfAlgo.algoRounds;
|
|
|
|
pOffer->Algos[i].MySpi = pInfo->InboundSPI[j];
|
|
pOffer->Algos[i].PeerSpi = pInfo->OutboundSPI[j];
|
|
|
|
i++;
|
|
break;
|
|
|
|
case None:
|
|
|
|
pOffer->Algos[i].Operation = NONE;
|
|
pOffer->Algos[i].uAlgoIdentifier = IPSEC_DOI_ESP_NONE;
|
|
pOffer->Algos[i].uSecAlgoIdentifier = HMAC_AH_NONE;
|
|
pOffer->Algos[i].uAlgoKeyLen = 0;
|
|
pOffer->Algos[i].uAlgoRounds = 0;
|
|
pOffer->Algos[i].MySpi = pInfo->InboundSPI[j];
|
|
pOffer->Algos[i].PeerSpi = pInfo->OutboundSPI[j];
|
|
|
|
i++;
|
|
break;
|
|
|
|
case Compress:
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (k = i; k < QM_MAX_ALGOS; k++) {
|
|
memset(&(pOffer->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
|
|
}
|
|
|
|
pOffer->dwNumAlgos = i;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
CopyQMSAFilter(
|
|
IPAddr MyTunnelEndpt,
|
|
PIPSEC_FILTER pIpsecFilter,
|
|
PIPSEC_QM_FILTER pIpsecQMFilter
|
|
)
|
|
{
|
|
if (pIpsecFilter->TunnelFilter) {
|
|
pIpsecQMFilter->QMFilterType = QM_TUNNEL_FILTER;
|
|
}
|
|
else {
|
|
pIpsecQMFilter->QMFilterType = QM_TRANSPORT_FILTER;
|
|
}
|
|
|
|
PASetAddress(
|
|
pIpsecFilter->SrcMask,
|
|
pIpsecFilter->SrcAddr,
|
|
&(pIpsecQMFilter->SrcAddr)
|
|
);
|
|
|
|
PASetAddress(
|
|
pIpsecFilter->DestMask,
|
|
pIpsecFilter->DestAddr,
|
|
&(pIpsecQMFilter->DesAddr)
|
|
);
|
|
|
|
pIpsecQMFilter->Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
|
pIpsecQMFilter->Protocol.dwProtocol = pIpsecFilter->Protocol;
|
|
|
|
pIpsecQMFilter->SrcPort.PortType = PORT_UNIQUE;
|
|
pIpsecQMFilter->SrcPort.wPort = ntohs(pIpsecFilter->SrcPort);
|
|
|
|
pIpsecQMFilter->DesPort.PortType = PORT_UNIQUE;
|
|
pIpsecQMFilter->DesPort.wPort = ntohs(pIpsecFilter->DestPort);
|
|
|
|
if (pIpsecFilter->TunnelFilter) {
|
|
PASetTunnelAddress(
|
|
MyTunnelEndpt,
|
|
&(pIpsecQMFilter->MyTunnelEndpt)
|
|
);
|
|
PASetTunnelAddress(
|
|
pIpsecFilter->TunnelAddr,
|
|
&(pIpsecQMFilter->PeerTunnelEndpt)
|
|
);
|
|
}
|
|
else {
|
|
PASetAddress(
|
|
SUBNET_MASK_ANY,
|
|
SUBNET_ADDRESS_ANY,
|
|
&(pIpsecQMFilter->MyTunnelEndpt)
|
|
);
|
|
PASetAddress(
|
|
SUBNET_MASK_ANY,
|
|
SUBNET_ADDRESS_ANY,
|
|
&(pIpsecQMFilter->PeerTunnelEndpt)
|
|
);
|
|
}
|
|
|
|
pIpsecQMFilter->dwFlags = 0;
|
|
|
|
if ((pIpsecFilter->Flags) & FILTER_FLAGS_INBOUND) {
|
|
pIpsecQMFilter->dwFlags |= FILTER_DIRECTION_INBOUND;
|
|
}
|
|
else {
|
|
pIpsecQMFilter->dwFlags |= FILTER_DIRECTION_OUTBOUND;
|
|
}
|
|
|
|
if ((pIpsecFilter->Flags) & FILTER_FLAGS_PASS_THRU) {
|
|
pIpsecQMFilter->dwFlags |= FILTER_NATURE_PASS_THRU;
|
|
}
|
|
else if ((pIpsecFilter->Flags) & FILTER_FLAGS_DROP) {
|
|
pIpsecQMFilter->dwFlags |= FILTER_NATURE_BLOCKING;
|
|
}
|
|
else {
|
|
pIpsecQMFilter->dwFlags |= 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
CopyQMSAMMSpi(
|
|
IKE_COOKIE_PAIR CookiePair,
|
|
PIKE_COOKIE_PAIR pMMSpi
|
|
)
|
|
{
|
|
pMMSpi->Initiator = CookiePair.Initiator;
|
|
|
|
pMMSpi->Responder = CookiePair.Responder;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeQMSAs(
|
|
DWORD dwCnt,
|
|
PIPSEC_QM_SA pQMSAs
|
|
)
|
|
{
|
|
if (pQMSAs) {
|
|
SPDApiBufferFree(pQMSAs);
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
InsertTunnelFiltersIntoIPSec(
|
|
PINITNSFILTER pSpecificFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insert a list of specific filters into the
|
|
IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to insert.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
|
|
BOOL bStatus = FALSE;
|
|
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DWORD dwNumFilters = 0;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
LPBYTE pTemp = NULL;
|
|
DWORD i = 0;
|
|
|
|
|
|
if (!pSpecificFilters) {
|
|
return (dwError);
|
|
}
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwError = WrapTunnelFilters(
|
|
pSpecificFilters,
|
|
&pInternalFilters,
|
|
&dwNumFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwInBufferSize = sizeof(DWORD) +
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters;
|
|
|
|
dwError = AllocateSPDMemory(
|
|
dwInBufferSize,
|
|
&pInBuffer
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTemp = pInBuffer;
|
|
memcpy(pTemp, &dwNumFilters, sizeof(DWORD));
|
|
pTemp += sizeof(DWORD);
|
|
|
|
for (i = 0 ; i < dwNumFilters; i++) {
|
|
|
|
memcpy(pTemp, &(pInternalFilters[i]), sizeof(IPSEC_FILTER_INFO));
|
|
pTemp += sizeof(IPSEC_FILTER_INFO);
|
|
|
|
}
|
|
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_ADD_FILTER,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pInternalFilters) {
|
|
FreeSPDMemory(pInternalFilters);
|
|
}
|
|
|
|
if (pInBuffer) {
|
|
FreeSPDMemory(pInBuffer);
|
|
}
|
|
|
|
if (pOutBuffer) {
|
|
LocalFree(pOutBuffer);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
DeleteTunnelFiltersFromIPSec(
|
|
PINITNSFILTER pSpecificFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a list of filters from the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to delete.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
|
|
BOOL bStatus = FALSE;
|
|
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DWORD dwNumFilters = 0;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
LPBYTE pTemp = NULL;
|
|
DWORD i = 0;
|
|
|
|
|
|
if (!pSpecificFilters) {
|
|
return (dwError);
|
|
}
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwError = WrapTunnelFilters(
|
|
pSpecificFilters,
|
|
&pInternalFilters,
|
|
&dwNumFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwInBufferSize = sizeof(DWORD) +
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters;
|
|
|
|
dwError = AllocateSPDMemory(
|
|
dwInBufferSize,
|
|
&pInBuffer
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTemp = pInBuffer;
|
|
memcpy(pTemp, &dwNumFilters, sizeof(DWORD));
|
|
pTemp += sizeof(DWORD);
|
|
|
|
for (i = 0 ; i < dwNumFilters; i++) {
|
|
|
|
memcpy(pTemp, &(pInternalFilters[i]), sizeof(IPSEC_FILTER_INFO));
|
|
pTemp += sizeof(IPSEC_FILTER_INFO);
|
|
|
|
}
|
|
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_DELETE_FILTER,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pInternalFilters) {
|
|
FreeSPDMemory(pInternalFilters);
|
|
}
|
|
|
|
if (pInBuffer) {
|
|
FreeSPDMemory(pInBuffer);
|
|
}
|
|
|
|
if (pOutBuffer) {
|
|
LocalFree(pOutBuffer);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WrapTunnelFilters(
|
|
PINITNSFILTER pSpecificFilters,
|
|
PIPSEC_FILTER_INFO * ppInternalFilters,
|
|
PDWORD pdwNumFilters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Transforms a list of specific tunnel filters to
|
|
an equivalent list of filters acceptable to the
|
|
IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilters - list of filters to convert.
|
|
|
|
ppInternalFilters - list of transformed filters.
|
|
|
|
pdwNumFilters - count of the filters in the transformed
|
|
list.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS - Success.
|
|
|
|
Win32 Error - Failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = 0;
|
|
PINITNSFILTER pTempFilter = NULL;
|
|
PIPSEC_FILTER_INFO pInternalFilters = NULL;
|
|
DWORD dwNumFilters = 0;
|
|
DWORD i = 0;
|
|
|
|
|
|
//
|
|
// At this point, there's atleast one filter in the
|
|
// specific filter list.
|
|
//
|
|
|
|
pTempFilter = pSpecificFilters;
|
|
|
|
while(pTempFilter) {
|
|
pTempFilter = pTempFilter->pNext;
|
|
dwNumFilters++;
|
|
}
|
|
|
|
|
|
dwError = AllocateSPDMemory(
|
|
sizeof(IPSEC_FILTER_INFO)*dwNumFilters,
|
|
&pInternalFilters
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
pTempFilter = pSpecificFilters;
|
|
|
|
while(pTempFilter) {
|
|
|
|
FormIPSecTunnelFilter(
|
|
pTempFilter,
|
|
&(pInternalFilters[i])
|
|
);
|
|
|
|
pTempFilter = pTempFilter->pNext;
|
|
i++;
|
|
|
|
}
|
|
|
|
*ppInternalFilters = pInternalFilters;
|
|
*pdwNumFilters = dwNumFilters;
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
*ppInternalFilters = NULL;
|
|
*pdwNumFilters = 0;
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
VOID
|
|
FormIPSecTunnelFilter(
|
|
PINITNSFILTER pSpecificFilter,
|
|
PIPSEC_FILTER_INFO pIpsecFilter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Transforms a specific tunnel filter to an
|
|
equivalent filter acceptable to the IPSec Driver.
|
|
|
|
Arguments:
|
|
|
|
pSpecificFilter - filter to convert.
|
|
|
|
pIpsecFilter - transformed filter.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
memcpy(
|
|
&(pIpsecFilter->FilterId),
|
|
&(pSpecificFilter->gParentID),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
memcpy(
|
|
&(pIpsecFilter->PolicyId),
|
|
&(pSpecificFilter->gPolicyID),
|
|
sizeof(GUID)
|
|
);
|
|
|
|
pIpsecFilter->Index = pSpecificFilter->dwWeight;
|
|
|
|
pIpsecFilter->AssociatedFilter.SrcAddr = pSpecificFilter->SrcAddr.uIpAddr;
|
|
pIpsecFilter->AssociatedFilter.SrcMask = pSpecificFilter->SrcAddr.uSubNetMask;
|
|
|
|
pIpsecFilter->AssociatedFilter.DestAddr = pSpecificFilter->DesAddr.uIpAddr;
|
|
pIpsecFilter->AssociatedFilter.DestMask = pSpecificFilter->DesAddr.uSubNetMask;
|
|
|
|
pIpsecFilter->AssociatedFilter.Protocol = pSpecificFilter->Protocol.dwProtocol;
|
|
pIpsecFilter->AssociatedFilter.SrcPort = pSpecificFilter->SrcPort.wPort;
|
|
pIpsecFilter->AssociatedFilter.DestPort = pSpecificFilter->DesPort.wPort;
|
|
|
|
pIpsecFilter->AssociatedFilter.TunnelFilter = TRUE;
|
|
pIpsecFilter->AssociatedFilter.TunnelAddr = pSpecificFilter->DesTunnelAddr.uIpAddr;
|
|
|
|
pIpsecFilter->AssociatedFilter.Flags = 0;
|
|
|
|
if (pSpecificFilter->dwDirection == FILTER_DIRECTION_INBOUND) {
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_INBOUND;
|
|
switch (pSpecificFilter->InboundFilterFlag) {
|
|
|
|
case PASS_THRU:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_PASS_THRU;
|
|
break;
|
|
|
|
case BLOCKING:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_DROP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_OUTBOUND;
|
|
switch (pSpecificFilter->OutboundFilterFlag) {
|
|
|
|
case PASS_THRU:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_PASS_THRU;
|
|
break;
|
|
|
|
case BLOCKING:
|
|
pIpsecFilter->AssociatedFilter.Flags |= FILTER_FLAGS_DROP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
SPDSetIPSecDriverOpMode(
|
|
DWORD dwOpMode
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
PIPSEC_SET_OPERATION_MODE pIpsecSetOpMode = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bStatus = FALSE;
|
|
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
dwError = AllocateSPDMemory(
|
|
sizeof(IPSEC_SET_OPERATION_MODE),
|
|
&pIpsecSetOpMode
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pIpsecSetOpMode->OperationMode = (OPERATION_MODE) dwOpMode;
|
|
|
|
pInBuffer = (LPBYTE) pIpsecSetOpMode;
|
|
dwInBufferSize = sizeof(IPSEC_SET_OPERATION_MODE);
|
|
|
|
pOutBuffer = (LPBYTE) pIpsecSetOpMode;
|
|
dwOutBufferSize = sizeof(IPSEC_SET_OPERATION_MODE);
|
|
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_SET_OPERATION_MODE,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pIpsecSetOpMode) {
|
|
FreeSPDMemory(pIpsecSetOpMode);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
IPSecDeleteQMSAs(
|
|
LPWSTR pServerName,
|
|
PIPSEC_QM_SA pIpsecQMSA,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HANDLE hIPSecDriver = NULL;
|
|
IPSEC_DELETE_SA IpsecDeleteSA;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bStatus = FALSE;
|
|
|
|
|
|
ENTER_SPD_SECTION();
|
|
dwError = ValidateSecurity(
|
|
SPD_OBJECT_SERVER,
|
|
SERVER_ACCESS_ADMINISTER,
|
|
NULL,
|
|
NULL
|
|
);
|
|
LEAVE_SPD_SECTION();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
memcpy(
|
|
&IpsecDeleteSA.SATemplate,
|
|
pIpsecQMSA,
|
|
sizeof(IPSEC_QM_SA)
|
|
);
|
|
|
|
pInBuffer = (LPBYTE) &IpsecDeleteSA;
|
|
dwInBufferSize = sizeof(IPSEC_DELETE_SA);
|
|
|
|
pOutBuffer = (LPBYTE) &IpsecDeleteSA;
|
|
dwOutBufferSize = sizeof(IPSEC_DELETE_SA);
|
|
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_DELETE_SA,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
DWORD
|
|
SPDRegisterIPSecDriverProtocols(
|
|
DWORD dwRegisterMode
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
HANDLE hIPSecDriver = NULL;
|
|
PIPSEC_REGISTER_PROTOCOL pIpsecRegisterProtocol = NULL;
|
|
LPBYTE pInBuffer = NULL;
|
|
DWORD dwInBufferSize = 0;
|
|
LPBYTE pOutBuffer = NULL;
|
|
DWORD dwOutBufferSize = 0;
|
|
DWORD dwBytesReturned = 0;
|
|
BOOL bStatus = FALSE;
|
|
|
|
|
|
dwError = SPDOpenIPSecDriver(
|
|
&hIPSecDriver
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
dwError = AllocateSPDMemory(
|
|
sizeof(IPSEC_REGISTER_PROTOCOL),
|
|
&pIpsecRegisterProtocol
|
|
);
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
|
|
pIpsecRegisterProtocol->RegisterProtocol = (REGISTER_PROTOCOL) dwRegisterMode;
|
|
|
|
pInBuffer = (LPBYTE) pIpsecRegisterProtocol;
|
|
dwInBufferSize = sizeof(IPSEC_REGISTER_PROTOCOL);
|
|
|
|
pOutBuffer = (LPBYTE) pIpsecRegisterProtocol;
|
|
dwOutBufferSize = sizeof(IPSEC_REGISTER_PROTOCOL);
|
|
|
|
dwBytesReturned = dwOutBufferSize;
|
|
|
|
bStatus = DeviceIoControl(
|
|
hIPSecDriver,
|
|
IOCTL_IPSEC_REGISTER_PROTOCOL,
|
|
pInBuffer,
|
|
dwInBufferSize,
|
|
pOutBuffer,
|
|
dwOutBufferSize,
|
|
&dwBytesReturned,
|
|
NULL
|
|
);
|
|
if (bStatus == FALSE) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
error:
|
|
|
|
if (hIPSecDriver != INVALID_HANDLE_VALUE) {
|
|
SPDCloseIPSecDriver(hIPSecDriver);
|
|
}
|
|
|
|
if (pIpsecRegisterProtocol) {
|
|
FreeSPDMemory(pIpsecRegisterProtocol);
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|