Keying sa manuelle
L’exemple de code suivant montre comment créer des associations de sécurité (SA) à l’aide de la plateforme de filtrage Windows.
#include <windows.h>
#include <fwpmu.h>
#include <stdio.h>
#include <conio.h>
#pragma comment(lib, "fwpuclnt.lib")
#pragma comment(lib, "ws2_32.lib")
// 5fb216a8-e2e8-4024-b853-391a4168641e
const GUID PROVIDER_KEY =
{
0x5fb216a8,
0xe2e8,
0x4024,
{ 0xb8, 0x53, 0x39, 0x1a, 0x41, 0x68, 0x64, 0x1e }
};
#define EXIT_ON_ERROR(fnName) \
if (result != ERROR_SUCCESS) \
{ \
printf(#fnName " = 0x%08X\n", result); \
goto CLEANUP; \
}
unsigned long inet_addrW(__in PCWSTR cp)
{
size_t converted;
char mbstr[sizeof("255.255.255.255")];
errno_t cerr;
cerr = wcstombs_s(&converted, mbstr, sizeof(mbstr), cp, wcslen(cp));
return (cerr == 0) ? inet_addr(mbstr) : INADDR_NONE;
}
// Helper function to delete an SA context and the associated transport
// filters.
void DeleteSaContextAndFilters(
__in HANDLE engine,
__in UINT64 inFilterId,
__in UINT64 outFilterId,
__in UINT64 saId
)
{
DWORD result;
// Allow the LUIDs to be zero, so we can use this function to cleanup
// partial results.
if (saId != 0)
{
result = IPsecSaContextDeleteById0(engine, saId);
if (result != ERROR_SUCCESS)
{
// There's not much we can do if delete fails, so continue trying to
// clean up the remaining objects.
printf("IPsecSaContextDeleteById0 = 0x%08X\n", result);
}
}
if (outFilterId != 0)
{
result = FwpmFilterDeleteById0(engine, outFilterId);
if (result != ERROR_SUCCESS)
{
printf("FwpmFilterDeleteById0 = 0x%08X\n", result);
}
}
if (inFilterId != 0)
{
result = FwpmFilterDeleteById0(engine, inFilterId);
if (result != ERROR_SUCCESS)
{
printf("FwpmFilterDeleteById0 = 0x%08X\n", result);
}
}
}
// Illustrates the first part of SA establishment using AH. The caller supplies
// the local and remote IP addresses and the inbound authentication key. The
// function returns the inbound SPI.
DWORD AddInboundSa(
__in HANDLE engine,
__in PCWSTR filterName,
__in_opt const GUID* providerKey,
__in UINT32 localAddr,
__in UINT32 remoteAddr,
__in const FWP_BYTE_BLOB* authKey,
__out UINT64* inFilterId,
__out UINT64* outFilterId,
__out UINT64* saId,
__out IPSEC_SA_SPI* spi
)
{
DWORD result = ERROR_SUCCESS;
UINT64 tmpInFilterId = 0, tmpOutFilterId = 0, tmpSaId = 0;
FWPM_FILTER_CONDITION0 conds[2];
FWPM_FILTER0 filter;
IPSEC_TRAFFIC0 outTraffic;
IPSEC_GETSPI0 getSpi;
IPSEC_SA_AUTH_INFORMATION0 info;
IPSEC_SA0 sa;
IPSEC_SA_BUNDLE0 bundle;
//////////
// Create IPsec filters matching the local and remote IP address at both the
// inbound and outbound transport layers. This has to be done first since we
// need the filter LUIDs to create the SA context and get the inbound SPI.
//////////
conds[0].fieldKey = FWPM_CONDITION_IP_LOCAL_ADDRESS;
conds[0].matchType = FWP_MATCH_EQUAL;
conds[0].conditionValue.type = FWP_UINT32;
conds[0].conditionValue.uint32 = localAddr;
conds[1].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS;
conds[1].matchType = FWP_MATCH_EQUAL;
conds[1].conditionValue.type = FWP_UINT32;
conds[1].conditionValue.uint32 = remoteAddr;
// Fill in the common fields shared by both filters.
memset(&filter, 0, sizeof(filter));
// For MUI compatibility, object names should be indirect strings. See
// SHLoadIndirectString for details.
filter.displayData.name = (PWSTR)filterName;
// Link all objects to our provider. When multiple providers are installed
// on a computer, this makes it easy to determine who added what.
filter.providerKey = (GUID*)providerKey;
filter.numFilterConditions = 2;
filter.filterCondition = conds;
filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
// Add the inbound filter.
filter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4;
filter.action.calloutKey = FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4;
result = FwpmFilterAdd0(
engine,
&filter,
NULL,
&tmpInFilterId
);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Add the outbound filter.
filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
filter.action.calloutKey = FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4;
result = FwpmFilterAdd0(
engine,
&filter,
NULL,
&tmpOutFilterId
);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Create the SA context using the outbound traffic descriptor.
memset(&outTraffic, 0, sizeof(outTraffic));
outTraffic.ipVersion = FWP_IP_VERSION_V4;
outTraffic.localV4Address = localAddr;
outTraffic.remoteV4Address = remoteAddr;
outTraffic.trafficType = IPSEC_TRAFFIC_TYPE_TRANSPORT;
outTraffic.ipsecFilterId = tmpOutFilterId;
result = IPsecSaContextCreate0(
engine,
&outTraffic,
NULL,
&tmpSaId
);
EXIT_ON_ERROR(IPsecSaContextCreate0);
// Get the inbound SPI using the inbound traffic descriptor.
memset(&getSpi, 0, sizeof(getSpi));
getSpi.inboundIpsecTraffic.ipVersion = FWP_IP_VERSION_V4;
getSpi.inboundIpsecTraffic.localV4Address = localAddr;
getSpi.inboundIpsecTraffic.remoteV4Address = remoteAddr;
getSpi.inboundIpsecTraffic.trafficType = IPSEC_TRAFFIC_TYPE_TRANSPORT;
getSpi.inboundIpsecTraffic.ipsecFilterId = tmpInFilterId;
getSpi.ipVersion = FWP_IP_VERSION_V4;
result = IPsecSaContextGetSpi0(
engine,
tmpSaId,
&getSpi,
spi
);
EXIT_ON_ERROR(result);
/////////
// Add the inbound SA using the authentication key supplied by the caller.
/////////
memset(&info, 0, sizeof(info));
info.authTransform.authTransformId = IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96;
info.authKey = *authKey;
memset(&sa, 0, sizeof(sa));
sa.spi = *spi;
sa.saTransformType = IPSEC_TRANSFORM_AH;
sa.ahInformation = &info;
memset(&bundle, 0, sizeof(bundle));
bundle.numSAs = 1;
bundle.saList = &sa;
bundle.ipVersion = FWP_IP_VERSION_V4;
result = IPsecSaContextAddInbound0(engine, tmpSaId, &bundle);
EXIT_ON_ERROR(IPsecSaContextAddInbound0);
// Return the various LUIDs to the caller, so he can clean up.
*inFilterId = tmpInFilterId;
*outFilterId = tmpOutFilterId;
*saId = tmpSaId;
CLEANUP:
if (result != ERROR_SUCCESS)
{
DeleteSaContextAndFilters(
engine,
tmpInFilterId,
tmpOutFilterId,
tmpSaId
);
}
return result;
}
// After successfully calling AddInboundSa, the caller will use some
// out-of-band mechanism to exchange inbound SPIs and authentication keys with
// the remote peer (who presumably has also called AddInboundSa). The remote
// peer's inbound SPI and key become the outbound SPI and key on the local
// machine.
DWORD AddOutboundSa(
__in HANDLE engine,
__in UINT64 saId,
__in IPSEC_SA_SPI spi,
__in const FWP_BYTE_BLOB* authKey
)
{
DWORD result = ERROR_SUCCESS;
IPSEC_SA_AUTH_INFORMATION0 info;
IPSEC_SA0 sa;
IPSEC_SA_BUNDLE0 bundle;
memset(&info, 0, sizeof(info));
info.authTransform.authTransformId = IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96;
info.authKey = *authKey;
memset(&sa, 0, sizeof(sa));
sa.spi = spi;
sa.saTransformType = IPSEC_TRANSFORM_AH;
sa.ahInformation = &info;
memset(&bundle, 0, sizeof(bundle));
bundle.numSAs = 1;
bundle.saList = &sa;
bundle.ipVersion = FWP_IP_VERSION_V4;
result = IPsecSaContextAddOutbound0(engine, saId, &bundle);
EXIT_ON_ERROR(IPsecSaContextAddOutbound0);
CLEANUP:
return result;
}
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour