Leaked source code of windows server 2003
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.
 
 
 
 
 
 

734 lines
18 KiB

#include "precomp.h"
#ifdef TRACE_ON
#include "patx-fil.tmh"
#endif
DWORD
PAAddQMFilters(
PIPSEC_NFA_DATA * ppIpsecNFAData,
DWORD dwNumNFACount,
DWORD dwSource,
BOOL * pbHardError
)
{
DWORD dwError = 0;
DWORD i = 0;
PIPSEC_NFA_DATA pIpsecNFAData = NULL;
BOOL bHardError = FALSE;
BOOL bTempHardError = FALSE;
for (i = 0; i < dwNumNFACount; i++) {
pIpsecNFAData = *(ppIpsecNFAData + i);
if (!(pIpsecNFAData->dwTunnelFlags)) {
dwError = PAAddTxFilterSpecs(
pIpsecNFAData,
dwSource,
&bTempHardError
);
}
else {
dwError = PAAddTnFilterSpecs(
pIpsecNFAData,
dwSource,
&bTempHardError
);
}
if (bTempHardError) {
bHardError = TRUE;
AuditIPSecPolicyErrorEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
PASTORE_ADD_QM_FILTER_FAIL,
pIpsecNFAData->pszIpsecName,
dwError,
FALSE,
TRUE
);
}
}
(*pbHardError) = bHardError;
return (dwError);
}
DWORD
PAAddTxFilterSpecs(
PIPSEC_NFA_DATA pIpsecNFAData,
DWORD dwSource,
BOOL * pbHardError
)
{
DWORD dwError = 0;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
PIPSEC_FILTER_DATA pIpsecFilterData = NULL;
PQMPOLICYSTATE pQMPolicyState = NULL;
DWORD dwNumFilterSpecs = 0;
PIPSEC_FILTER_SPEC * ppFilterSpecs = NULL;
DWORD i = 0;
PTXFILTERSTATE pTxFilterState = NULL;
PTRANSPORT_FILTER pSPDTxFilter = NULL;
LPWSTR pServerName = NULL;
DWORD dwVersion = 0;
BOOL bHardError = FALSE;
TRACE(TRC_INFORMATION, ("Pastore adding transport filters for rule %!guid!.", &pIpsecNFAData->NFAIdentifier));
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
if (!memcmp(
&(pIpsecNegPolData->NegPolType),
&(GUID_NEGOTIATION_TYPE_DEFAULT),
sizeof(GUID))) {
TRACE(TRC_INFORMATION, ("Pastore found default response rule: not adding an associated transport filter."));
dwError = ERROR_SUCCESS;
BAIL_OUT;
}
pQMPolicyState = FindQMPolicyState(
pIpsecNegPolData->NegPolIdentifier
);
if (!pQMPolicyState) {
bHardError = TRUE;
dwError = ERROR_INVALID_PARAMETER;
TRACE(
TRC_ERROR,
("Pastore failed to find associated QM policy %!guid! when adding rule %!guid!.",
&pIpsecNegPolData->NegPolIdentifier,
&pIpsecNFAData->NFAIdentifier)
);
BAIL_ON_WIN32_ERROR(dwError);
}
if (!IsClearOnly(pQMPolicyState->gNegPolAction) &&
!IsBlocking(pQMPolicyState->gNegPolAction) &&
!(pQMPolicyState->bInSPD)) {
bHardError = TRUE;
dwError = ERROR_INVALID_PARAMETER;
TRACE(
TRC_ERROR,
("Pastore failed to get associated QM policy in SPD %!guid! when adding rule %!guid!.",
&pIpsecNFAData->NFAIdentifier,
&pIpsecNegPolData->NegPolIdentifier)
);
BAIL_ON_WIN32_ERROR(dwError);
}
pIpsecFilterData = pIpsecNFAData->pIpsecFilterData;
if (!pIpsecFilterData) {
TRACE(
TRC_ERROR,
("Pastore found no associated filter data when adding rule %!guid!.",
&pIpsecNFAData->NFAIdentifier)
);
dwError = ERROR_INVALID_PARAMETER;
SET_IF_HARD_ERROR(
dwError,
pQMPolicyState->gNegPolAction,
bHardError
);
if (!bHardError) {
dwError = ERROR_SUCCESS;
}
BAIL_OUT;
}
dwNumFilterSpecs = pIpsecFilterData->dwNumFilterSpecs;
ppFilterSpecs = pIpsecFilterData->ppFilterSpecs;
for (i = 0; i < dwNumFilterSpecs; i++) {
dwError = PACreateTxFilterState(
pIpsecNegPolData,
pIpsecNFAData,
*(ppFilterSpecs + i),
&pTxFilterState
);
if (dwError) {
SET_IF_HARD_ERROR(
dwError,
pQMPolicyState->gNegPolAction,
bHardError
);
continue;
}
dwError = PACreateTxFilter(
pIpsecNegPolData,
pIpsecNFAData,
*(ppFilterSpecs + i),
pQMPolicyState,
&pSPDTxFilter
);
if (dwError) {
pTxFilterState->hTxFilter = NULL;
pTxFilterState->pNext = gpTxFilterState;
gpTxFilterState = pTxFilterState;
SET_IF_HARD_ERROR(
dwError,
pQMPolicyState->gNegPolAction,
bHardError
);
continue;
}
dwError = AddTransportFilterInternal(
pServerName,
dwVersion,
0,
dwSource,
pSPDTxFilter,
NULL,
&(pTxFilterState->hTxFilter)
);
// Catch the driver error that can happen because of adding duplicated
// expanded filters. We don't want this to be a hard error.
//
if (dwError == STATUS_DUPLICATE_OBJECTID
|| dwError == GPC_STATUS_CONFLICT)
{
AuditIPSecPolicyErrorEvent(
SE_CATEGID_POLICY_CHANGE,
SE_AUDITID_IPSEC_POLICY_CHANGED,
PASTORE_ADD_QM_FILTER_FAIL,
pIpsecNFAData->pszIpsecName,
dwError,
FALSE,
TRUE
);
} else {
SET_IF_HARD_ERROR(
dwError,
pQMPolicyState->gNegPolAction,
bHardError
);
}
pTxFilterState->pNext = gpTxFilterState;
gpTxFilterState = pTxFilterState;
PAFreeTxFilter(pSPDTxFilter);
}
error:
*pbHardError = bHardError;
return (dwError);
}
DWORD
PACreateTxFilterState(
PIPSEC_NEGPOL_DATA pIpsecNegPolData,
PIPSEC_NFA_DATA pIpsecNFAData,
PIPSEC_FILTER_SPEC pFilterSpec,
PTXFILTERSTATE * ppTxFilterState
)
{
DWORD dwError = 0;
PTXFILTERSTATE pTxFilterState = NULL;
dwError = AllocateSPDMemory(
sizeof(TXFILTERSTATE),
&pTxFilterState
);
BAIL_ON_WIN32_ERROR(dwError);
memcpy(
&(pTxFilterState->gFilterID),
&(pFilterSpec->FilterSpecGUID),
sizeof(GUID)
);
memcpy(
&(pTxFilterState->gNFAIdentifier),
&(pIpsecNFAData->NFAIdentifier),
sizeof(GUID)
);
memcpy(
&(pTxFilterState->gPolicyID),
&(pIpsecNegPolData->NegPolIdentifier),
sizeof(GUID)
);
pTxFilterState->hTxFilter = NULL;
pTxFilterState->pNext = NULL;
*ppTxFilterState = pTxFilterState;
return (dwError);
error:
TRACE(
TRC_ERROR,
("Pastore failed to create state node for transport filter %!guid!. %!winerr!",
&pFilterSpec->FilterSpecGUID,
dwError)
);
*ppTxFilterState = NULL;
return (dwError);
}
DWORD
PACreateTxFilter(
PIPSEC_NEGPOL_DATA pIpsecNegPolData,
PIPSEC_NFA_DATA pIpsecNFAData,
PIPSEC_FILTER_SPEC pFilterSpec,
PQMPOLICYSTATE pQMPolicyState,
PTRANSPORT_FILTER * ppSPDTxFilter
)
{
DWORD dwError = 0;
PTRANSPORT_FILTER pSPDTxFilter = NULL;
WCHAR pszName[512];
dwError = AllocateSPDMemory(
sizeof(TRANSPORT_FILTER),
&pSPDTxFilter
);
BAIL_ON_WIN32_ERROR(dwError);
pSPDTxFilter->IpVersion = IPSEC_PROTOCOL_V4;
memcpy(
&(pSPDTxFilter->gFilterID),
&(pFilterSpec->FilterSpecGUID),
sizeof(GUID)
);
if (pFilterSpec->pszDescription && *(pFilterSpec->pszDescription)) {
dwError = AllocateSPDString(
pFilterSpec->pszDescription,
&(pSPDTxFilter->pszFilterName)
);
BAIL_ON_WIN32_ERROR(dwError);
}
else {
wsprintf(pszName, L"%d", ++gdwTxFilterCounter);
dwError = AllocateSPDString(
pszName,
&(pSPDTxFilter->pszFilterName)
);
BAIL_ON_WIN32_ERROR(dwError);
}
PASetInterfaceType(
pIpsecNFAData->dwInterfaceType,
&(pSPDTxFilter->InterfaceType)
);
pSPDTxFilter->bCreateMirror = (BOOL) pFilterSpec->dwMirrorFlag;
pSPDTxFilter->dwFlags = 0;
PASetAddress(
pFilterSpec->Filter.SrcMask,
pFilterSpec->Filter.SrcAddr,
&(pSPDTxFilter->SrcAddr)
);
PASetAddress(
pFilterSpec->Filter.DestMask,
pFilterSpec->Filter.DestAddr,
&(pSPDTxFilter->DesAddr)
);
if (pFilterSpec->Filter.ExType) {
if (pFilterSpec->Filter.ExType & EXT_DEST) {
pSPDTxFilter->DesAddr.AddrType = ExTypeToAddrType(
pFilterSpec->Filter.ExType
);
} else {
pSPDTxFilter->SrcAddr.AddrType = ExTypeToAddrType(
pFilterSpec->Filter.ExType
);
}
}
pSPDTxFilter->Protocol.ProtocolType = PROTOCOL_UNIQUE;
pSPDTxFilter->Protocol.dwProtocol = pFilterSpec->Filter.Protocol;
pSPDTxFilter->SrcPort.PortType = PORT_UNIQUE;
pSPDTxFilter->SrcPort.wPort = pFilterSpec->Filter.SrcPort;
pSPDTxFilter->DesPort.PortType = PORT_UNIQUE;
pSPDTxFilter->DesPort.wPort = pFilterSpec->Filter.DestPort;
SetFilterActions(
pQMPolicyState,
&(pSPDTxFilter->InboundFilterAction),
&(pSPDTxFilter->OutboundFilterAction)
);
pSPDTxFilter->dwDirection = 0;
pSPDTxFilter->dwWeight = 0;
memcpy(
&(pSPDTxFilter->gPolicyID),
&(pIpsecNegPolData->NegPolIdentifier),
sizeof(GUID)
);
*ppSPDTxFilter = pSPDTxFilter;
return (dwError);
error:
TRACE(
TRC_WARNING,
("Pastore failed to create transport filter %!guid!. %!winerr!",
&pFilterSpec->FilterSpecGUID,
dwError)
);
if (pSPDTxFilter) {
PAFreeTxFilter(
pSPDTxFilter
);
}
*ppSPDTxFilter = NULL;
return (dwError);
}
VOID
SetFilterActions(
PQMPOLICYSTATE pQMPolicyState,
PFILTER_ACTION pInboundFilterFlag,
PFILTER_ACTION pOutboundFilterFlag
)
{
*pInboundFilterFlag = NEGOTIATE_SECURITY;
*pOutboundFilterFlag = NEGOTIATE_SECURITY;
if (IsBlocking(pQMPolicyState->gNegPolAction)) {
*pInboundFilterFlag = BLOCKING;
*pOutboundFilterFlag = BLOCKING;
}
else if (IsClearOnly(pQMPolicyState->gNegPolAction)) {
*pInboundFilterFlag = PASS_THRU;
*pOutboundFilterFlag = PASS_THRU;
}
else if (IsInboundPassThru(pQMPolicyState->gNegPolAction)) {
*pInboundFilterFlag = PASS_THRU;
}
if (pQMPolicyState->bAllowsSoft && gbBackwardSoftSA) {
*pInboundFilterFlag = PASS_THRU;
}
}
VOID
PAFreeTxFilter(
PTRANSPORT_FILTER pSPDTxFilter
)
{
if (pSPDTxFilter) {
if (pSPDTxFilter->pszFilterName) {
FreeSPDString(pSPDTxFilter->pszFilterName);
}
FreeSPDMemory(pSPDTxFilter);
}
return;
}
DWORD
PADeleteAllTxFilters(
)
{
DWORD dwError = 0;
PTXFILTERSTATE pTxFilterState = NULL;
PTXFILTERSTATE pTemp = NULL;
PTXFILTERSTATE pLeftTxFilterState = NULL;
TRACE(TRC_INFORMATION, (L"Pastore deleting all its transport filters"));
pTxFilterState = gpTxFilterState;
while (pTxFilterState) {
if (pTxFilterState->hTxFilter) {
dwError = DeleteTransportFilter(
pTxFilterState->hTxFilter
);
if (!dwError) {
pTemp = pTxFilterState;
pTxFilterState = pTxFilterState->pNext;
FreeSPDMemory(pTemp);
}
else {
pTemp = pTxFilterState;
pTxFilterState = pTxFilterState->pNext;
pTemp->pNext = pLeftTxFilterState;
pLeftTxFilterState = pTemp;
}
}
else {
pTemp = pTxFilterState;
pTxFilterState = pTxFilterState->pNext;
FreeSPDMemory(pTemp);
}
}
gpTxFilterState = pLeftTxFilterState;
return (dwError);
}
VOID
PAFreeTxFilterStateList(
PTXFILTERSTATE pTxFilterState
)
{
PTXFILTERSTATE pTemp = NULL;
while (pTxFilterState) {
pTemp = pTxFilterState;
pTxFilterState = pTxFilterState->pNext;
FreeSPDMemory(pTemp);
}
}
DWORD
PADeleteQMFilters(
PIPSEC_NFA_DATA * ppIpsecNFAData,
DWORD dwNumNFACount
)
{
DWORD dwError = 0;
DWORD i = 0;
PIPSEC_NFA_DATA pIpsecNFAData = NULL;
for (i = 0; i < dwNumNFACount; i++) {
pIpsecNFAData = *(ppIpsecNFAData + i);
TRACE(
TRC_INFORMATION,
("Pastore deleting transport/tunnel filters generated from rule %!guid!",
&pIpsecNFAData->NFAIdentifier)
);
if (!(pIpsecNFAData->dwTunnelFlags)) {
dwError = PADeleteTxFilterSpecs(
pIpsecNFAData
);
}
else {
dwError = PADeleteTnFilterSpecs(
pIpsecNFAData
);
}
}
return (dwError);
}
DWORD
PADeleteTxFilterSpecs(
PIPSEC_NFA_DATA pIpsecNFAData
)
{
DWORD dwError = 0;
PIPSEC_NEGPOL_DATA pIpsecNegPolData = NULL;
PIPSEC_FILTER_DATA pIpsecFilterData = NULL;
DWORD dwNumFilterSpecs = 0;
PIPSEC_FILTER_SPEC * ppFilterSpecs = NULL;
DWORD i = 0;
PIPSEC_FILTER_SPEC pFilterSpec = NULL;
pIpsecNegPolData = pIpsecNFAData->pIpsecNegPolData;
if (!memcmp(
&(pIpsecNegPolData->NegPolType),
&(GUID_NEGOTIATION_TYPE_DEFAULT),
sizeof(GUID))) {
dwError = ERROR_SUCCESS;
return (dwError);
}
pIpsecFilterData = pIpsecNFAData->pIpsecFilterData;
if (!pIpsecFilterData) {
dwError = ERROR_SUCCESS;
return (dwError);
}
dwNumFilterSpecs = pIpsecFilterData->dwNumFilterSpecs;
ppFilterSpecs = pIpsecFilterData->ppFilterSpecs;
for (i = 0; i < dwNumFilterSpecs; i++) {
pFilterSpec = *(ppFilterSpecs + i);
dwError = PADeleteTxFilter(
pFilterSpec->FilterSpecGUID,
pIpsecNFAData->NFAIdentifier
);
}
return (dwError);
}
DWORD
PADeleteTxFilter(
GUID gFilterID,
GUID gNFAIdentifier
)
{
DWORD dwError = 0;
PTXFILTERSTATE pTxFilterState = NULL;
pTxFilterState = FindTxFilterState(
gFilterID,
gNFAIdentifier
);
if (!pTxFilterState) {
dwError = ERROR_SUCCESS;
return (dwError);
}
if (pTxFilterState->hTxFilter) {
dwError = DeleteTransportFilter(
pTxFilterState->hTxFilter
);
BAIL_ON_WIN32_ERROR(dwError);
}
PADeleteTxFilterState(pTxFilterState);
error:
#ifdef TRACE_ON
if (dwError) {
TRACE(
TRC_WARNING,
("Pastore failed to delete transport filter %!guid!. %!winerr!",
&gFilterID,
dwError)
);
}
#endif
return (dwError);
}
VOID
PADeleteTxFilterState(
PTXFILTERSTATE pTxFilterState
)
{
PTXFILTERSTATE * ppTemp = NULL;
ppTemp = &gpTxFilterState;
while (*ppTemp) {
if (*ppTemp == pTxFilterState) {
break;
}
ppTemp = &((*ppTemp)->pNext);
}
if (*ppTemp) {
*ppTemp = pTxFilterState->pNext;
}
FreeSPDMemory(pTxFilterState);
return;
}
PTXFILTERSTATE
FindTxFilterState(
GUID gFilterID,
GUID gNFAIdentifier
)
{
PTXFILTERSTATE pTxFilterState = NULL;
pTxFilterState = gpTxFilterState;
while (pTxFilterState) {
if (!memcmp(&(pTxFilterState->gFilterID), &gFilterID, sizeof(GUID))
&& !memcmp(&(pTxFilterState->gNFAIdentifier), &gNFAIdentifier, sizeof(GUID)))
{
return (pTxFilterState);
}
pTxFilterState = pTxFilterState->pNext;
}
return (NULL);
}