포트 예약
다음 샘플 코드에서는 리소스 할당 계층을 사용하여 관리자를 위해 다양한 포트를 예약하는 방법을 보여 줍니다.
#include <windows.h>
#include <sddl.h>
#include <fwpmu.h>
#include <stdio.h>
#pragma comment(lib, "fwpuclnt.lib")
#pragma comment(lib, "advapi32.lib")
#define EXIT_ON_ERROR(fnName) \
if (result != ERROR_SUCCESS) \
{ \
printf(#fnName " = 0x%08X\n", result); \
goto CLEANUP; \
}
#define EXIT_ON_LAST_ERROR(success, fnName) \
if (!(success)) \
{ \
result = GetLastError(); \
printf(#fnName " = 0x%08X\n", result); \
goto CLEANUP; \
}
DWORD ReservePortRangeForAdmins(
__in HANDLE engine,
__in PCWSTR filterName,
__in_opt const GUID* providerKey,
__in_opt const GUID* subLayerKey,
__in UINT16 loPort,
__in UINT16 hiPort
)
{
DWORD result = ERROR_SUCCESS;
FWPM_FILTER_CONDITION0 conds[2];
FWP_RANGE0 portRange;
BOOL success;
PSECURITY_DESCRIPTOR sd = NULL;
FWP_BYTE_BLOB sdBlob;
FWPM_FILTER0 filter;
BOOL txnInProgress = FALSE;
//////////
// The first condition matches any local port in the desired range.
//////////
portRange.valueLow.type = FWP_UINT16;
portRange.valueLow.uint16 = loPort;
portRange.valueHigh.type = FWP_UINT16;
portRange.valueHigh.uint16 = hiPort;
conds[0].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
conds[0].matchType = FWP_MATCH_RANGE;
conds[0].conditionValue.type = FWP_RANGE_TYPE;
conds[0].conditionValue.rangeValue = &portRange;
//////////
// The second condition matches any user who is a member of the built-in
// Administrators group.
//////////
// For well-known security descriptors, it's easiest to build them in one
// shot from an SDDL string, rather than constructing them programmatically
// using lower-level APIs.
success = ConvertStringSecurityDescriptorToSecurityDescriptorW(
L"D:(A;;0x1;;;BA)",
SDDL_REVISION_1,
&sd,
NULL
);
EXIT_ON_LAST_ERROR(
success,
ConvertStringSecurityDescriptorToSecurityDescriptorW
);
// Security descriptors must be in self-relative form (i.e., contiguous).
// The security descriptor returned by
// ConvertStringSecurityDescriptorToSecurityDescriptorW is already
// self-relative, but if you're using another mechanism to build the
// descriptor, you may have to convert it. See MakeSelfRelativeSD for
// details.
sdBlob.size = GetSecurityDescriptorLength(sd);
sdBlob.data = (UINT8*)sd;
conds[1].fieldKey = FWPM_CONDITION_ALE_USER_ID;
conds[1].matchType = FWP_MATCH_EQUAL;
conds[1].conditionValue.type = FWP_SECURITY_DESCRIPTOR_TYPE;
conds[1].conditionValue.sd = &sdBlob;
// Fill in the common fields shared by all our 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;
// Generally, it's best to add filters to our own sublayer, so we don't have
// to worry about being overridden by filters added by another provider.
if (subLayerKey != NULL)
{
filter.subLayerKey = *subLayerKey;
}
filter.filterCondition = conds;
// We add all the filters from within a single transaction to make it easy
// to clean up partial results in error paths.
result = FwpmTransactionBegin0(engine, 0);
EXIT_ON_ERROR(FwpmTransactionBegin0);
txnInProgress = TRUE;
// Add the filters for IPv4.
filter.layerKey = FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4;
// This filter just has the port range condition, so it blocks all users for
// the desired port range.
filter.numFilterConditions = 1;
filter.action.type = FWP_ACTION_BLOCK;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// This filter permits Administrators for the port range. Since we're using
// auto-weighting and this filter is more specific than the previous, it
// will have a higher weight. When an admin tries to bind to a port in the
// range, this filter will match first, permitting the bind. When a
// non-admin tries, this filter won't match and the previous filter will
// block the bind.
filter.numFilterConditions = 2;
filter.action.type = FWP_ACTION_PERMIT;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Add the same filters for IPv6.
filter.layerKey = FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6;
filter.numFilterConditions = 1;
filter.action.type = FWP_ACTION_BLOCK;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
filter.numFilterConditions = 2;
filter.action.type = FWP_ACTION_PERMIT;
result = FwpmFilterAdd0(engine, &filter, NULL, NULL);
EXIT_ON_ERROR(FwpmFilterAdd0);
// Once all the adds have succeeded, we commit the transaction to atomically
// add all the new objects.
result = FwpmTransactionCommit0(engine);
EXIT_ON_ERROR(FwpmTransactionCommit0);
txnInProgress = FALSE;
CLEANUP:
if (txnInProgress)
{
// Abort any transaction still in progress to clean up partial results.
FwpmTransactionAbort0(engine);
}
LocalFree(sd);
return result;
}
관련 항목