├── .gitignore ├── LICENSE.md ├── README.md ├── libwfp.sln ├── src ├── libwfp │ ├── buildervalidation.h │ ├── conditionbuilder.cpp │ ├── conditionbuilder.h │ ├── conditions │ │ ├── comparison.h │ │ ├── conditionapplication.cpp │ │ ├── conditionapplication.h │ │ ├── conditiondirection.cpp │ │ ├── conditiondirection.h │ │ ├── conditionicmp.cpp │ │ ├── conditionicmp.h │ │ ├── conditioninterface.cpp │ │ ├── conditioninterface.h │ │ ├── conditionip.cpp │ │ ├── conditionip.h │ │ ├── conditionloopback.cpp │ │ ├── conditionloopback.h │ │ ├── conditionport.cpp │ │ ├── conditionport.h │ │ ├── conditionportrange.cpp │ │ ├── conditionportrange.h │ │ ├── conditionprotocol.cpp │ │ ├── conditionprotocol.h │ │ ├── icomparisonoperator.h │ │ └── ifiltercondition.h │ ├── filterbuilder.cpp │ ├── filterbuilder.h │ ├── filterengine.cpp │ ├── filterengine.h │ ├── iconditionbuilder.h │ ├── iidentifiable.h │ ├── internal │ │ ├── conditionassembler.cpp │ │ └── conditionassembler.h │ ├── ipaddress.cpp │ ├── ipaddress.h │ ├── ipnetwork.cpp │ ├── ipnetwork.h │ ├── layerconditions.cpp │ ├── layerconditions.h │ ├── libwfp.vcxproj │ ├── libwfp.vcxproj.filters │ ├── nullconditionbuilder.h │ ├── objectdeleter.cpp │ ├── objectdeleter.h │ ├── objectenumerator.cpp │ ├── objectenumerator.h │ ├── objectexplorer.cpp │ ├── objectexplorer.h │ ├── objectinstaller.cpp │ ├── objectinstaller.h │ ├── objectmonitor.cpp │ ├── objectmonitor.h │ ├── providerbuilder.cpp │ ├── providerbuilder.h │ ├── stdafx.cpp │ ├── stdafx.h │ ├── sublayerbuilder.cpp │ ├── sublayerbuilder.h │ ├── targetver.h │ ├── transaction.cpp │ └── transaction.h └── test-libwfp │ ├── integration │ ├── operations.cpp │ └── transaction.cpp │ ├── ncat.cpp │ ├── ncat.h │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ ├── test-libwfp.vcxproj │ ├── test-libwfp.vcxproj.filters │ └── wfp │ ├── ipaddress.cpp │ └── layerconditions.cpp └── thirdparty └── ncat ├── README └── ncat.exe /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | .vs/ 3 | *.suo 4 | *.db 5 | *.db-shm 6 | *.db-wal 7 | *.ipch 8 | *.user 9 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2021 Mullvad VPN AB 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mullvad libwfp 2 | 3 | libwfp is a C++ library for interacting with the Windows Filtering Platform (WFP). Notably, libwfp 4 | provides builders for defining providers, filters and sets of conditions. 5 | 6 | ## Checking out the code 7 | 8 | The code is dependent on one other repository: 9 | 10 | * mullvad/windows-libraries 11 | 12 | Specifically, the `libcommon` library contained herein, for general functionality not provided by 13 | the standard library. 14 | 15 | For reasons of flexibility, this repository is not included as a submodule. It is instead 16 | required to be checked out at the same level as libwfp: 17 | ``` 18 | mkdir libwfp && cd libwfp 19 | git clone https://github.com/mullvad/windows-libraries.git 20 | git clone https://github.com/mullvad/libwfp.git 21 | ``` 22 | 23 | ## Development environment 24 | 25 | libwfp requires Visual Studio 2022. Any edition will work, e.g. Visual Studio Community 2022 is a 26 | perfectly fine choice. 27 | 28 | ## Dependencies 29 | 30 | For dependencies required during development, see above, section *Checking out the code*. 31 | 32 | For deployment there are no external dependencies beyond what is already provided by Windows itself. 33 | 34 | libwfp is targeted at Windows 7, 8 and 10. 35 | 36 | ## Example usage 37 | ### Fine-grained blocking of outgoing connections 38 | ``` cpp 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | int main() 51 | { 52 | auto engine = wfp::FilterEngine::DynamicSession(); 53 | 54 | wfp::SublayerBuilder sublayer(wfp::BuilderValidation::OnlyCritical); 55 | 56 | sublayer 57 | .name(L"libwfp example layer") 58 | .weight(MAXUINT16); 59 | 60 | GUID sublayerGuid; 61 | 62 | wfp::ObjectInstaller::AddSublayer(*engine, sublayer, &sublayerGuid); 63 | 64 | // Conditions are checked against the specified layer 65 | // To verify that they're compatible 66 | wfp::ConditionBuilder conditions(FWPM_LAYER_ALE_AUTH_CONNECT_V4); 67 | 68 | // Match on application 69 | conditions.add_condition(std::make_unique( \ 70 | L"c:\\windows\\system32\\svchost.exe")); 71 | 72 | // Match remote ports outside given range 73 | conditions.add_condition(wfp::conditions::ConditionPortRange::Remote( \ 74 | 0, 1023, wfp::conditions::CompareNeq())); 75 | 76 | wfp::FilterBuilder filter(wfp::BuilderValidation::OnlyCritical); 77 | 78 | filter 79 | .name(L"Svchost peer filter") 80 | .description(L"Block comms with remote services outside the well-known port range") 81 | .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V4) 82 | .sublayer(sublayerGuid) 83 | .weight(wfp::FilterBuilder::WeightClass::Max) 84 | .block(); 85 | 86 | wfp::ObjectInstaller::AddFilter(*engine, filter, conditions); 87 | 88 | // 89 | // 90 | // 91 | 92 | return 0; 93 | } 94 | ``` 95 | 96 | # License 97 | 98 | Copyright (C) 2022 Mullvad VPN AB 99 | 100 | Permission to use the code, documentation and contents is granted under the conditions of the MIT 101 | license. 102 | 103 | For the full license agreement, see the LICENSE.md file. 104 | -------------------------------------------------------------------------------- /libwfp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32014.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwfp", "src\libwfp\libwfp.vcxproj", "{2164E6D9-6023-4932-A08F-7A5C15E2CA0B}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcommon", "..\windows-libraries\src\libcommon\libcommon.vcxproj", "{B52E2D10-A94A-4605-914A-2DCEF6A757EF}" 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test-libwfp", "src\test-libwfp\test-libwfp.vcxproj", "{F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}" 14 | ProjectSection(ProjectDependencies) = postProject 15 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF} 16 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B} = {2164E6D9-6023-4932-A08F-7A5C15E2CA0B} 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|ARM64 = Debug|ARM64 22 | Debug|x64 = Debug|x64 23 | Debug|x86 = Debug|x86 24 | Release|ARM64 = Release|ARM64 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|ARM64.ActiveCfg = Debug|ARM64 30 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|ARM64.Build.0 = Debug|ARM64 31 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|x64.ActiveCfg = Debug|x64 32 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|x64.Build.0 = Debug|x64 33 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|x86.ActiveCfg = Debug|Win32 34 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Debug|x86.Build.0 = Debug|Win32 35 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|ARM64.Build.0 = Release|ARM64 37 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|x64.ActiveCfg = Release|x64 38 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|x64.Build.0 = Release|x64 39 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|x86.ActiveCfg = Release|Win32 40 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B}.Release|x86.Build.0 = Release|Win32 41 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|ARM64.ActiveCfg = Debug|ARM64 42 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|ARM64.Build.0 = Debug|ARM64 43 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.ActiveCfg = Debug|x64 44 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.Build.0 = Debug|x64 45 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.ActiveCfg = Debug|Win32 46 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.Build.0 = Debug|Win32 47 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|ARM64.ActiveCfg = Release|ARM64 48 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|ARM64.Build.0 = Release|ARM64 49 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.ActiveCfg = Release|x64 50 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.Build.0 = Release|x64 51 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.ActiveCfg = Release|Win32 52 | {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.Build.0 = Release|Win32 53 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 54 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|ARM64.Build.0 = Debug|ARM64 55 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|x64.ActiveCfg = Debug|x64 56 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|x64.Build.0 = Debug|x64 57 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|x86.ActiveCfg = Debug|Win32 58 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Debug|x86.Build.0 = Debug|Win32 59 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|ARM64.ActiveCfg = Release|ARM64 60 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|ARM64.Build.0 = Release|ARM64 61 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|x64.ActiveCfg = Release|x64 62 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|x64.Build.0 = Release|x64 63 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|x86.ActiveCfg = Release|Win32 64 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A}.Release|x86.Build.0 = Release|Win32 65 | EndGlobalSection 66 | GlobalSection(SolutionProperties) = preSolution 67 | HideSolutionNode = FALSE 68 | EndGlobalSection 69 | GlobalSection(ExtensibilityGlobals) = postSolution 70 | SolutionGuid = {FA414E6E-8054-487F-9D5A-BF53C65B4CB9} 71 | EndGlobalSection 72 | EndGlobal 73 | -------------------------------------------------------------------------------- /src/libwfp/buildervalidation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace wfp 4 | { 5 | 6 | // 7 | // Validation levels employed by builders before building an artifact. 8 | // 9 | enum class BuilderValidation 10 | { 11 | // Ensure optional values are set if this is considered good practice. 12 | Extra, 13 | 14 | // Perform the bare minimum validation. 15 | OnlyCritical, 16 | 17 | // No validation 18 | Off 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/libwfp/conditionbuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionbuilder.h" 3 | #include "layerconditions.h" 4 | #include 5 | 6 | using IFilterCondition = wfp::conditions::IFilterCondition; 7 | 8 | namespace wfp 9 | { 10 | 11 | ConditionBuilder::ConditionBuilder(const GUID &layer) 12 | { 13 | memcpy(&m_layer, &layer, sizeof(layer)); 14 | } 15 | 16 | ConditionBuilder &ConditionBuilder::add_condition(std::unique_ptr condition) 17 | { 18 | if (false == LayerConditions::IsCompatible(m_layer, condition->identifier())) 19 | { 20 | THROW_ERROR("Condition is not compatible with layer"); 21 | } 22 | 23 | m_conditions.insert(std::move(condition)); 24 | 25 | return *this; 26 | } 27 | 28 | bool ConditionBuilder::build(ConditionSink sink) const 29 | { 30 | auto conditions = std::make_unique(m_conditions.size()); 31 | 32 | // 33 | // Individual conditions must be kept around for the lifetime of 'conditions' 34 | // This is because individual conditions manage data pointed by entries in 'conditions' 35 | // 36 | 37 | auto index = 0; 38 | 39 | for (const std::unique_ptr &condition : m_conditions) 40 | { 41 | memcpy(&conditions[index++], &condition->condition(), sizeof(FWPM_FILTER_CONDITION0)); 42 | } 43 | 44 | return sink(conditions.get(), m_conditions.size()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/libwfp/conditionbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iconditionbuilder.h" 4 | #include "conditions/ifiltercondition.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace wfp 11 | { 12 | 13 | typedef std::function ConditionSink; 14 | 15 | class ConditionBuilder : public IConditionBuilder 16 | { 17 | public: 18 | 19 | ConditionBuilder(const GUID &layer); 20 | 21 | ConditionBuilder &add_condition(std::unique_ptr condition); 22 | 23 | bool build(ConditionSink sink) const override; 24 | 25 | void reset() 26 | { 27 | m_conditions.clear(); 28 | } 29 | 30 | void reset(const GUID &layer) 31 | { 32 | memcpy(&m_layer, &layer, sizeof(layer)); 33 | reset(); 34 | } 35 | 36 | private: 37 | 38 | GUID m_layer; 39 | 40 | struct FilterConditionLess 41 | { 42 | bool operator()(const std::unique_ptr &lhs, const std::unique_ptr &rhs) const 43 | { 44 | return memcmp(&(lhs->identifier()), &(rhs->identifier()), sizeof(GUID)) < 0; 45 | } 46 | }; 47 | 48 | // 49 | // This container provides automatic sorting of conditions 50 | // 51 | // This is required in order for BFE to accept duplicate conditions 52 | // and evaluate them using the OR operator 53 | // 54 | std::multiset, FilterConditionLess> m_conditions; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/libwfp/conditions/comparison.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "icomparisonoperator.h" 4 | 5 | namespace wfp::conditions { 6 | 7 | // 8 | // For usage when implementing conditions, internal storage of comparision spec 9 | // after the comparision inheritance check has passed 10 | // 11 | class ComparisonSpecification 12 | { 13 | public: 14 | 15 | ComparisonSpecification(const IComparisonOperator &instance) 16 | : m_op(instance.op()) 17 | , m_string(instance.toString()) 18 | { 19 | } 20 | 21 | FWP_MATCH_TYPE op() const 22 | { 23 | return m_op; 24 | } 25 | 26 | std::wstring toString() const 27 | { 28 | return m_string; 29 | } 30 | 31 | private: 32 | 33 | FWP_MATCH_TYPE m_op; 34 | std::wstring m_string; 35 | }; 36 | 37 | struct CompareEq : public IStrictComparison, public IRelaxedComparison 38 | { 39 | FWP_MATCH_TYPE op() const override 40 | { 41 | return FWP_MATCH_EQUAL; 42 | } 43 | 44 | std::wstring toString() const override 45 | { 46 | return L"="; 47 | } 48 | }; 49 | 50 | struct CompareNeq : public IStrictComparison, public IRelaxedComparison 51 | { 52 | FWP_MATCH_TYPE op() const override 53 | { 54 | return FWP_MATCH_NOT_EQUAL; 55 | } 56 | 57 | std::wstring toString() const override 58 | { 59 | return L"!="; 60 | } 61 | }; 62 | 63 | struct CompareGt : public IRelaxedComparison 64 | { 65 | FWP_MATCH_TYPE op() const override 66 | { 67 | return FWP_MATCH_GREATER; 68 | } 69 | 70 | std::wstring toString() const override 71 | { 72 | return L">"; 73 | } 74 | }; 75 | 76 | struct CompareGte : public IRelaxedComparison 77 | { 78 | FWP_MATCH_TYPE op() const override 79 | { 80 | return FWP_MATCH_GREATER_OR_EQUAL; 81 | } 82 | 83 | std::wstring toString() const override 84 | { 85 | return L">="; 86 | } 87 | }; 88 | 89 | struct CompareLt : public IRelaxedComparison 90 | { 91 | FWP_MATCH_TYPE op() const override 92 | { 93 | return FWP_MATCH_LESS; 94 | } 95 | 96 | std::wstring toString() const override 97 | { 98 | return L"<"; 99 | } 100 | }; 101 | 102 | struct CompareLte : public IRelaxedComparison 103 | { 104 | FWP_MATCH_TYPE op() const override 105 | { 106 | return FWP_MATCH_LESS_OR_EQUAL; 107 | } 108 | 109 | std::wstring toString() const override 110 | { 111 | return L"<="; 112 | } 113 | }; 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionapplication.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionapplication.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 8 | 9 | namespace wfp::conditions { 10 | 11 | ConditionApplication::ConditionApplication(const std::wstring &application, const IStrictComparison &comparison) 12 | : m_application(application) 13 | , m_comparison(comparison) 14 | { 15 | FWP_BYTE_BLOB *blob; 16 | 17 | auto status = FwpmGetAppIdFromFileName0(m_application.c_str(), &blob); 18 | 19 | if (ERROR_SUCCESS != status) 20 | { 21 | THROW_WINDOWS_ERROR(status, "Retrieve application identifier from filename"); 22 | } 23 | 24 | m_assembled = ConditionAssembler::ByteBlob(identifier(), m_comparison.op(), *blob); 25 | 26 | FwpmFreeMemory0((void**)&blob); 27 | } 28 | 29 | std::wstring ConditionApplication::toString() const 30 | { 31 | std::wstringstream ss; 32 | 33 | ss << L"application " << m_comparison.toString() << L" " << m_application; 34 | 35 | return ss.str(); 36 | } 37 | 38 | const GUID &ConditionApplication::identifier() const 39 | { 40 | return FWPM_CONDITION_ALE_APP_ID; 41 | } 42 | 43 | const FWPM_FILTER_CONDITION0 &ConditionApplication::condition() const 44 | { 45 | return *reinterpret_cast(m_assembled.data()); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionapplication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | 7 | namespace wfp::conditions { 8 | 9 | class ConditionApplication : public IFilterCondition 10 | { 11 | public: 12 | 13 | ConditionApplication(const std::wstring &application, const IStrictComparison &comparison = CompareEq()); 14 | 15 | std::wstring toString() const override; 16 | const GUID &identifier() const override; 17 | const FWPM_FILTER_CONDITION0 &condition() const override; 18 | 19 | private: 20 | 21 | std::wstring m_application; 22 | ComparisonSpecification m_comparison; 23 | 24 | common::Buffer m_assembled; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditiondirection.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditiondirection.h" 3 | #include 4 | 5 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 6 | 7 | namespace wfp::conditions { 8 | 9 | ConditionDirection::ConditionDirection(Direction direction) 10 | : m_direction(direction) 11 | { 12 | m_assembled = ConditionAssembler::Uint32 13 | ( 14 | identifier(), 15 | FWP_MATCH_EQUAL, 16 | static_cast(Direction::Inbound == m_direction ? FWP_DIRECTION_INBOUND : FWP_DIRECTION_OUTBOUND) 17 | ); 18 | } 19 | 20 | std::wstring ConditionDirection::toString() const 21 | { 22 | return 23 | ( 24 | Direction::Inbound == m_direction 25 | ? L"direction = inbound" 26 | : L"direction = outbound" 27 | ); 28 | } 29 | 30 | const GUID &ConditionDirection::identifier() const 31 | { 32 | return FWPM_CONDITION_DIRECTION; 33 | } 34 | 35 | const FWPM_FILTER_CONDITION0 &ConditionDirection::condition() const 36 | { 37 | return *reinterpret_cast(m_assembled.data()); 38 | } 39 | 40 | //static 41 | std::unique_ptr ConditionDirection::Inbound() 42 | { 43 | return std::unique_ptr(new ConditionDirection(Direction::Inbound)); 44 | } 45 | 46 | //static 47 | std::unique_ptr ConditionDirection::Outbound() 48 | { 49 | return std::unique_ptr(new ConditionDirection(Direction::Outbound)); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditiondirection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ifiltercondition.h" 4 | #include 5 | #include 6 | 7 | namespace wfp::conditions { 8 | 9 | class ConditionDirection : public IFilterCondition 10 | { 11 | enum class Direction 12 | { 13 | Inbound, 14 | Outbound 15 | }; 16 | 17 | ConditionDirection(Direction direction); 18 | 19 | public: 20 | 21 | static std::unique_ptr Inbound(); 22 | static std::unique_ptr Outbound(); 23 | 24 | std::wstring toString() const override; 25 | const GUID &identifier() const override; 26 | const FWPM_FILTER_CONDITION0 &condition() const override; 27 | 28 | private: 29 | 30 | Direction m_direction; 31 | common::Buffer m_assembled; 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionicmp.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionicmp.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 8 | 9 | namespace wfp::conditions { 10 | 11 | ConditionIcmp::ConditionIcmp(ConditionType type, uint16_t value, const IRelaxedComparison &comparison) 12 | : m_type(type) 13 | , m_value(value) 14 | , m_comparison(comparison) 15 | { 16 | m_assembled = ConditionAssembler::Uint16(identifier(), comparison.op(), value); 17 | } 18 | 19 | std::wstring ConditionIcmp::toString() const 20 | { 21 | std::wstringstream ss; 22 | 23 | switch (m_type) 24 | { 25 | case ConditionType::Type: 26 | { 27 | ss << L"icmp type"; 28 | break; 29 | } 30 | case ConditionType::Code: 31 | { 32 | ss << L"icmp code"; 33 | break; 34 | } 35 | default: 36 | { 37 | THROW_ERROR("Missing case handler in switch clause"); 38 | } 39 | } 40 | 41 | ss << L" " << m_comparison.toString() << L" " << m_value; 42 | 43 | return ss.str(); 44 | } 45 | 46 | const GUID &ConditionIcmp::identifier() const 47 | { 48 | switch (m_type) 49 | { 50 | case ConditionType::Type: 51 | { 52 | return FWPM_CONDITION_ICMP_TYPE; 53 | } 54 | case ConditionType::Code: 55 | { 56 | return FWPM_CONDITION_ICMP_CODE; 57 | } 58 | default: 59 | { 60 | THROW_ERROR("Missing case handler in switch clause"); 61 | } 62 | } 63 | } 64 | 65 | const FWPM_FILTER_CONDITION0 &ConditionIcmp::condition() const 66 | { 67 | return *reinterpret_cast(m_assembled.data()); 68 | } 69 | 70 | //static 71 | std::unique_ptr ConditionIcmp::Type(uint16_t value, const IRelaxedComparison &comparison) 72 | { 73 | return std::unique_ptr(new ConditionIcmp(ConditionType::Type, value, comparison)); 74 | } 75 | 76 | //static 77 | std::unique_ptr ConditionIcmp::Code(uint16_t value, const IRelaxedComparison &comparison) 78 | { 79 | return std::unique_ptr(new ConditionIcmp(ConditionType::Code, value, comparison)); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionicmp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace wfp::conditions { 10 | 11 | class ConditionIcmp : public IFilterCondition 12 | { 13 | enum class ConditionType 14 | { 15 | Type, 16 | Code 17 | }; 18 | 19 | ConditionIcmp(ConditionType type, uint16_t value, const IRelaxedComparison &comparison); 20 | 21 | public: 22 | 23 | static std::unique_ptr Type(uint16_t value, const IRelaxedComparison &comparison = CompareEq()); 24 | static std::unique_ptr Code(uint16_t value, const IRelaxedComparison &comparison = CompareEq()); 25 | 26 | std::wstring toString() const override; 27 | const GUID &identifier() const override; 28 | const FWPM_FILTER_CONDITION0 &condition() const override; 29 | 30 | private: 31 | 32 | ConditionType m_type; 33 | uint16_t m_value; 34 | ComparisonSpecification m_comparison; 35 | 36 | common::Buffer m_assembled; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditioninterface.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditioninterface.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 10 | 11 | namespace 12 | { 13 | 14 | UINT64 LuidFromAlias(const std::wstring &interfaceAlias) 15 | { 16 | NET_LUID luid; 17 | 18 | if (0 != ConvertInterfaceAliasToLuid(interfaceAlias.c_str(), &luid)) 19 | { 20 | std::stringstream ss; 21 | 22 | ss << "Unable to derive interface LUID from interface with alias \"" 23 | << common::string::ToAnsi(interfaceAlias) << "\""; 24 | 25 | THROW_ERROR(ss.str().c_str()); 26 | } 27 | 28 | return luid.Value; 29 | } 30 | 31 | UINT64 LuidFromName(const std::wstring &interfaceName) 32 | { 33 | NET_LUID luid; 34 | 35 | if (0 != ConvertInterfaceNameToLuidW(interfaceName.c_str(), &luid)) 36 | { 37 | std::stringstream ss; 38 | 39 | ss << "Unable to derive interface LUID from interface with name \"" 40 | << common::string::ToAnsi(interfaceName) << "\""; 41 | 42 | THROW_ERROR(ss.str().c_str()); 43 | } 44 | 45 | return luid.Value; 46 | } 47 | 48 | } // anonymous namespace 49 | 50 | namespace wfp::conditions { 51 | 52 | ConditionInterface::ConditionInterface(uint32_t interfaceIndex, const IStrictComparison &comparison) 53 | : m_interfaceIndex(interfaceIndex) 54 | , m_interfaceLuid(0) 55 | , m_identifierType(IdentifierType::Index) 56 | , m_comparison(comparison) 57 | { 58 | m_assembled = ConditionAssembler::Uint32(identifier(), m_comparison.op(), m_interfaceIndex); 59 | } 60 | 61 | ConditionInterface::ConditionInterface(uint64_t interfaceLuid, const IStrictComparison &comparison) 62 | : m_interfaceIndex(0) 63 | , m_interfaceLuid(interfaceLuid) 64 | , m_identifierType(IdentifierType::Luid) 65 | , m_comparison(comparison) 66 | { 67 | m_assembled = ConditionAssembler::Uint64(identifier(), m_comparison.op(), m_interfaceLuid); 68 | } 69 | 70 | ConditionInterface::ConditionInterface(const std::wstring &interfaceIdentifier, IdentifierType type, const IStrictComparison &comparison) 71 | : m_interfaceIndex(0) 72 | , m_interfaceLuid(0) 73 | , m_interfaceIdentifier(interfaceIdentifier) 74 | , m_identifierType(type) 75 | , m_comparison(comparison) 76 | { 77 | uint64_t luid; 78 | 79 | switch (m_identifierType) 80 | { 81 | case IdentifierType::Alias: 82 | { 83 | luid = LuidFromAlias(m_interfaceIdentifier); 84 | break; 85 | } 86 | case IdentifierType::Name: 87 | { 88 | luid = LuidFromName(m_interfaceIdentifier); 89 | break; 90 | } 91 | default: 92 | { 93 | THROW_ERROR("Missing case handler in switch clause"); 94 | } 95 | } 96 | 97 | m_assembled = ConditionAssembler::Uint64(identifier(), m_comparison.op(), luid); 98 | } 99 | 100 | //static 101 | std::unique_ptr ConditionInterface::Index(uint32_t interfaceIndex, const IStrictComparison &comparison) 102 | { 103 | return std::unique_ptr(new ConditionInterface(interfaceIndex, comparison)); 104 | } 105 | 106 | //static 107 | std::unique_ptr ConditionInterface::Luid(uint64_t interfaceLuid, const IStrictComparison &comparison) 108 | { 109 | return std::unique_ptr(new ConditionInterface(interfaceLuid, comparison)); 110 | } 111 | 112 | //static 113 | std::unique_ptr ConditionInterface::Alias(const std::wstring &interfaceAlias, const IStrictComparison &comparison) 114 | { 115 | return std::unique_ptr(new ConditionInterface(interfaceAlias, IdentifierType::Alias, comparison)); 116 | } 117 | 118 | //static 119 | std::unique_ptr ConditionInterface::Name(const std::wstring &interfaceName, const IStrictComparison &comparison) 120 | { 121 | return std::unique_ptr(new ConditionInterface(interfaceName, IdentifierType::Name, comparison)); 122 | } 123 | 124 | std::wstring ConditionInterface::toString() const 125 | { 126 | std::wstringstream ss; 127 | 128 | switch (m_identifierType) 129 | { 130 | case IdentifierType::Index: 131 | { 132 | ss << L"interface index " << m_comparison.toString() << L" " << m_interfaceIndex; 133 | break; 134 | } 135 | case IdentifierType::Luid: 136 | { 137 | ss << L"interface LUID " << m_comparison.toString() << L" 0x" << std::hex << m_interfaceLuid; 138 | break; 139 | } 140 | case IdentifierType::Alias: 141 | { 142 | ss << L"interface alias " << m_comparison.toString() << L" \"" << m_interfaceIdentifier << L"\""; 143 | break; 144 | } 145 | case IdentifierType::Name: 146 | { 147 | ss << L"interface name " << m_comparison.toString() << L" \"" << m_interfaceIdentifier << L"\""; 148 | break; 149 | } 150 | default: 151 | { 152 | THROW_ERROR("Missing case handler in switch clause"); 153 | } 154 | }; 155 | 156 | return ss.str(); 157 | } 158 | 159 | const GUID &ConditionInterface::identifier() const 160 | { 161 | switch (m_identifierType) 162 | { 163 | case IdentifierType::Index: 164 | { 165 | return FWPM_CONDITION_INTERFACE_INDEX; 166 | } 167 | case IdentifierType::Luid: 168 | case IdentifierType::Alias: 169 | case IdentifierType::Name: 170 | { 171 | return FWPM_CONDITION_IP_LOCAL_INTERFACE; 172 | } 173 | default: 174 | { 175 | THROW_ERROR("Missing case handler in switch clause"); 176 | } 177 | }; 178 | } 179 | 180 | const FWPM_FILTER_CONDITION0 &ConditionInterface::condition() const 181 | { 182 | return *reinterpret_cast(m_assembled.data()); 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditioninterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace wfp::conditions { 10 | 11 | class ConditionInterface : public IFilterCondition 12 | { 13 | enum class IdentifierType 14 | { 15 | Index, 16 | Luid, 17 | Alias, 18 | Name 19 | }; 20 | 21 | ConditionInterface(uint32_t interfaceIndex, const IStrictComparison &comparison); 22 | ConditionInterface(uint64_t interfaceLuid, const IStrictComparison &comparison); 23 | ConditionInterface(const std::wstring &interfaceIdentifier, IdentifierType type, const IStrictComparison &comparison); 24 | 25 | public: 26 | 27 | static std::unique_ptr Index(uint32_t interfaceIndex, const IStrictComparison &comparison = CompareEq()); 28 | static std::unique_ptr Luid(uint64_t interfaceLuid, const IStrictComparison &comparison = CompareEq()); 29 | static std::unique_ptr Alias(const std::wstring &interfaceAlias, const IStrictComparison &comparison = CompareEq()); 30 | static std::unique_ptr Name(const std::wstring &interfaceName, const IStrictComparison &comparison = CompareEq()); 31 | 32 | std::wstring toString() const override; 33 | const GUID &identifier() const override; 34 | const FWPM_FILTER_CONDITION0 &condition() const override; 35 | 36 | private: 37 | 38 | UINT32 m_interfaceIndex; 39 | UINT64 m_interfaceLuid; 40 | std::wstring m_interfaceIdentifier; 41 | 42 | IdentifierType m_identifierType; 43 | ComparisonSpecification m_comparison; 44 | 45 | common::Buffer m_assembled; 46 | }; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionip.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionip.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 10 | 11 | namespace wfp::conditions { 12 | 13 | ConditionIp::ConditionIp(bool local, const IpAddress &netnode, const IStrictComparison &comparison) 14 | : m_type(Type::NetNode) 15 | , m_local(local) 16 | , m_netnode(std::make_unique(netnode)) 17 | , m_comparison(comparison) 18 | { 19 | switch (netnode.type()) 20 | { 21 | case IpAddress::Type::Ipv4: 22 | { 23 | m_assembled = ConditionAssembler::Uint32(identifier(), m_comparison.op(), netnode.addr()); 24 | break; 25 | } 26 | case IpAddress::Type::Ipv6: 27 | { 28 | m_assembled = ConditionAssembler::ByteArray16(identifier(), m_comparison.op(), netnode.addr6()); 29 | break; 30 | } 31 | default: 32 | { 33 | THROW_ERROR("Missing case handler in switch clause"); 34 | } 35 | } 36 | } 37 | 38 | ConditionIp::ConditionIp(bool local, const IpNetwork &network, const IStrictComparison &comparison) 39 | : m_type(Type::Network) 40 | , m_local(local) 41 | , m_network(std::make_unique(network)) 42 | , m_comparison(comparison) 43 | { 44 | switch (network.type()) 45 | { 46 | case IpNetwork::Type::Ipv4: 47 | { 48 | m_assembled = ConditionAssembler::Ipv4Network(identifier(), m_comparison.op(), network.net()); 49 | break; 50 | } 51 | case IpAddress::Type::Ipv6: 52 | { 53 | m_assembled = ConditionAssembler::Ipv6Network(identifier(), m_comparison.op(), network.net6()); 54 | break; 55 | } 56 | default: 57 | { 58 | THROW_ERROR("Missing case handler in switch clause"); 59 | } 60 | } 61 | } 62 | 63 | //static 64 | std::unique_ptr ConditionIp::Local(const IpAddress &netnode, const IStrictComparison &comparison) 65 | { 66 | return std::unique_ptr(new ConditionIp(true, netnode, comparison)); 67 | } 68 | 69 | //static 70 | std::unique_ptr ConditionIp::Local(const IpNetwork &network, const IStrictComparison &comparison) 71 | { 72 | return std::unique_ptr(new ConditionIp(true, network, comparison)); 73 | } 74 | 75 | //static 76 | std::unique_ptr ConditionIp::Remote(const IpAddress &netnode, const IStrictComparison &comparison) 77 | { 78 | return std::unique_ptr(new ConditionIp(false, netnode, comparison)); 79 | } 80 | 81 | //static 82 | std::unique_ptr ConditionIp::Remote(const IpNetwork &network, const IStrictComparison &comparison) 83 | { 84 | return std::unique_ptr(new ConditionIp(false, network, comparison)); 85 | } 86 | 87 | std::wstring ConditionIp::toString() const 88 | { 89 | std::wstringstream ss; 90 | 91 | const auto target = (m_local ? L"local" : L"remote"); 92 | 93 | switch (m_type) 94 | { 95 | case Type::NetNode: 96 | { 97 | ss << target << L" ip " << m_comparison.toString() << L" " << m_netnode->toString(); 98 | break; 99 | } 100 | case Type::Network: 101 | { 102 | ss << target << L" ip net " << m_comparison.toString() << L" " << m_network->toString(); 103 | break; 104 | } 105 | default: 106 | { 107 | THROW_ERROR("Missing case handler in switch clause"); 108 | } 109 | }; 110 | 111 | return ss.str(); 112 | } 113 | 114 | const GUID &ConditionIp::identifier() const 115 | { 116 | return (m_local ? FWPM_CONDITION_IP_LOCAL_ADDRESS : FWPM_CONDITION_IP_REMOTE_ADDRESS); 117 | } 118 | 119 | const FWPM_FILTER_CONDITION0 &ConditionIp::condition() const 120 | { 121 | return *reinterpret_cast(m_assembled.data()); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace wfp::conditions { 11 | 12 | class ConditionIp : public IFilterCondition 13 | { 14 | enum class Type 15 | { 16 | NetNode, 17 | Network, 18 | }; 19 | 20 | ConditionIp(bool local, const IpAddress &netnode, const IStrictComparison &comparison); 21 | ConditionIp(bool local, const IpNetwork &network, const IStrictComparison &comparison); 22 | 23 | public: 24 | 25 | static std::unique_ptr Local(const IpAddress &netnode, const IStrictComparison &comparison = CompareEq()); 26 | static std::unique_ptr Local(const IpNetwork &network, const IStrictComparison &comparison = CompareEq()); 27 | static std::unique_ptr Remote(const IpAddress &netnode, const IStrictComparison &comparison = CompareEq()); 28 | static std::unique_ptr Remote(const IpNetwork &network, const IStrictComparison &comparison = CompareEq()); 29 | 30 | std::wstring toString() const override; 31 | const GUID &identifier() const override; 32 | const FWPM_FILTER_CONDITION0 &condition() const override; 33 | 34 | private: 35 | 36 | Type m_type; 37 | 38 | bool m_local; 39 | 40 | const std::shared_ptr m_netnode; 41 | const std::shared_ptr m_network; 42 | 43 | ComparisonSpecification m_comparison; 44 | common::Buffer m_assembled; 45 | }; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionloopback.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionloopback.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 9 | 10 | namespace wfp::conditions { 11 | 12 | namespace 13 | { 14 | 15 | FWP_MATCH_TYPE GetFlagsMatchType(const ComparisonSpecification &comp) 16 | { 17 | switch (comp.op()) 18 | { 19 | case FWP_MATCH_EQUAL: return FWP_MATCH_FLAGS_ALL_SET; 20 | case FWP_MATCH_NOT_EQUAL: return FWP_MATCH_FLAGS_NONE_SET; 21 | default: 22 | { 23 | THROW_ERROR("Missing case handler in switch clause"); 24 | } 25 | } 26 | } 27 | 28 | } // anonymous namespace 29 | 30 | ConditionLoopback::ConditionLoopback(Type type, const IStrictComparison &comparison) 31 | : m_type(type) 32 | , m_comparison(comparison) 33 | { 34 | switch (m_type) 35 | { 36 | case Type::LoopbackInterface: 37 | { 38 | m_assembled = ConditionAssembler::Uint32(identifier(), 39 | m_comparison.op(), UINT32(IF_TYPE_SOFTWARE_LOOPBACK)); 40 | 41 | break; 42 | } 43 | case Type::LoopbackTraffic: 44 | { 45 | m_assembled = ConditionAssembler::Uint32(identifier(), 46 | GetFlagsMatchType(m_comparison), UINT32(FWP_CONDITION_FLAG_IS_LOOPBACK)); 47 | 48 | break; 49 | } 50 | default: 51 | { 52 | THROW_ERROR("Missing case handler in switch clause"); 53 | } 54 | } 55 | } 56 | 57 | std::wstring ConditionLoopback::toString() const 58 | { 59 | std::wstringstream ss; 60 | 61 | switch (m_type) 62 | { 63 | case Type::LoopbackInterface: 64 | { 65 | ss << L"interface "; 66 | break; 67 | } 68 | case Type::LoopbackTraffic: 69 | { 70 | ss << L"traffic category "; 71 | break; 72 | } 73 | default: 74 | { 75 | THROW_ERROR("Missing case handler in switch clause"); 76 | } 77 | } 78 | 79 | ss << m_comparison.toString() << L" loopback"; 80 | 81 | return ss.str(); 82 | } 83 | 84 | const GUID &ConditionLoopback::identifier() const 85 | { 86 | switch (m_type) 87 | { 88 | case Type::LoopbackInterface: return FWPM_CONDITION_INTERFACE_TYPE; 89 | case Type::LoopbackTraffic: return FWPM_CONDITION_FLAGS; 90 | default: 91 | { 92 | THROW_ERROR("Missing case handler in switch clause"); 93 | } 94 | } 95 | } 96 | 97 | const FWPM_FILTER_CONDITION0 &ConditionLoopback::condition() const 98 | { 99 | return *reinterpret_cast(m_assembled.data()); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionloopback.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | 7 | namespace wfp::conditions { 8 | 9 | class ConditionLoopback : public IFilterCondition 10 | { 11 | public: 12 | 13 | enum class Type 14 | { 15 | LoopbackInterface, 16 | LoopbackTraffic 17 | }; 18 | 19 | ConditionLoopback(Type type = Type::LoopbackTraffic, const IStrictComparison &comparison = CompareEq()); 20 | 21 | std::wstring toString() const override; 22 | const GUID &identifier() const override; 23 | const FWPM_FILTER_CONDITION0 &condition() const override; 24 | 25 | private: 26 | 27 | Type m_type; 28 | ComparisonSpecification m_comparison; 29 | common::Buffer m_assembled; 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionport.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionport.h" 3 | #include 4 | #include 5 | 6 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 7 | 8 | namespace wfp::conditions { 9 | 10 | ConditionPort::ConditionPort(bool local, uint16_t port, const IRelaxedComparison &comparison) 11 | : m_local(local) 12 | , m_port(port) 13 | , m_comparison(comparison) 14 | { 15 | m_assembled = ConditionAssembler::Uint16(identifier(), m_comparison.op(), m_port); 16 | } 17 | 18 | //static 19 | std::unique_ptr ConditionPort::Local(uint16_t port, const IRelaxedComparison &comparison) 20 | { 21 | return std::unique_ptr(new ConditionPort(true, port, comparison)); 22 | } 23 | 24 | //static 25 | std::unique_ptr ConditionPort::Remote(uint16_t port, const IRelaxedComparison &comparison) 26 | { 27 | return std::unique_ptr(new ConditionPort(false, port, comparison)); 28 | } 29 | 30 | std::wstring ConditionPort::toString() const 31 | { 32 | std::wstringstream ss; 33 | 34 | const auto target = (m_local ? L"local" : L"remote"); 35 | 36 | ss << target << L" port " << m_comparison.toString() << L" " << m_port; 37 | 38 | return ss.str(); 39 | } 40 | 41 | const GUID &ConditionPort::identifier() const 42 | { 43 | return (m_local ? FWPM_CONDITION_IP_LOCAL_PORT : FWPM_CONDITION_IP_REMOTE_PORT); 44 | } 45 | 46 | const FWPM_FILTER_CONDITION0 &ConditionPort::condition() const 47 | { 48 | return *reinterpret_cast(m_assembled.data()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | #include 7 | 8 | namespace wfp::conditions { 9 | 10 | class ConditionPort : public IFilterCondition 11 | { 12 | ConditionPort(bool local, uint16_t port, const IRelaxedComparison &comparison); 13 | 14 | public: 15 | 16 | static std::unique_ptr Local(uint16_t port, const IRelaxedComparison &comparison = CompareEq()); 17 | static std::unique_ptr Remote(uint16_t port, const IRelaxedComparison &comparison = CompareEq()); 18 | 19 | std::wstring toString() const override; 20 | const GUID &identifier() const override; 21 | const FWPM_FILTER_CONDITION0 &condition() const override; 22 | 23 | private: 24 | 25 | bool m_local; 26 | 27 | uint16_t m_port; 28 | ComparisonSpecification m_comparison; 29 | 30 | common::Buffer m_assembled; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionportrange.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionportrange.h" 3 | #include 4 | #include 5 | 6 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 7 | 8 | namespace wfp::conditions { 9 | 10 | ConditionPortRange::ConditionPortRange(bool local, uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison) 11 | : m_local(local) 12 | , m_firstPort(firstPort) 13 | , m_lastPort(lastPort) 14 | , m_comparison(comparison) 15 | { 16 | FWP_RANGE0 range; 17 | 18 | range.valueLow.type = FWP_UINT16; 19 | range.valueLow.uint16 = m_firstPort; 20 | range.valueHigh.type = FWP_UINT16; 21 | range.valueHigh.uint16 = m_lastPort; 22 | 23 | m_assembled = ConditionAssembler::Range(identifier(), m_comparison.op(), range); 24 | } 25 | 26 | //static 27 | std::unique_ptr ConditionPortRange::Local(uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison) 28 | { 29 | return std::unique_ptr(new ConditionPortRange(true, firstPort, lastPort, comparison)); 30 | } 31 | 32 | //static 33 | std::unique_ptr ConditionPortRange::Remote(uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison) 34 | { 35 | return std::unique_ptr(new ConditionPortRange(false, firstPort, lastPort, comparison)); 36 | } 37 | 38 | std::wstring ConditionPortRange::toString() const 39 | { 40 | std::wstringstream ss; 41 | 42 | const auto target = (m_local ? L"local" : L"remote"); 43 | 44 | ss << target << L" port " << (m_comparison.op() == FWP_MATCH_EQUAL ? L"inside" : L"outside") 45 | << L" range " << m_firstPort << L"-" << m_lastPort; 46 | 47 | return ss.str(); 48 | } 49 | 50 | const GUID &ConditionPortRange::identifier() const 51 | { 52 | return (m_local ? FWPM_CONDITION_IP_LOCAL_PORT : FWPM_CONDITION_IP_REMOTE_PORT); 53 | } 54 | 55 | const FWPM_FILTER_CONDITION0 &ConditionPortRange::condition() const 56 | { 57 | return *reinterpret_cast(m_assembled.data()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionportrange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "comparison.h" 4 | #include "ifiltercondition.h" 5 | #include 6 | #include 7 | 8 | namespace wfp::conditions { 9 | 10 | class ConditionPortRange : public IFilterCondition 11 | { 12 | ConditionPortRange(bool local, uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison); 13 | 14 | public: 15 | 16 | static std::unique_ptr Local(uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison = CompareEq()); 17 | static std::unique_ptr Remote(uint16_t firstPort, uint16_t lastPort, const IStrictComparison &comparison = CompareEq()); 18 | 19 | std::wstring toString() const override; 20 | const GUID &identifier() const override; 21 | const FWPM_FILTER_CONDITION0 &condition() const override; 22 | 23 | private: 24 | 25 | bool m_local; 26 | 27 | uint16_t m_firstPort; 28 | uint16_t m_lastPort; 29 | ComparisonSpecification m_comparison; 30 | 31 | common::Buffer m_assembled; 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionprotocol.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionprotocol.h" 3 | #include 4 | #include 5 | #include 6 | 7 | using ConditionAssembler = ::wfp::internal::ConditionAssembler; 8 | 9 | namespace wfp::conditions { 10 | 11 | ConditionProtocol::ConditionProtocol(Protocol protocol) 12 | : m_protocol(protocol) 13 | { 14 | m_assembled = ConditionAssembler::Uint8 15 | ( 16 | identifier(), 17 | FWP_MATCH_EQUAL, 18 | TranslateProtocol(protocol) 19 | ); 20 | } 21 | 22 | std::wstring ConditionProtocol::toString() const 23 | { 24 | switch (m_protocol) 25 | { 26 | case Protocol::Tcp: return L"protocol = TCP"; 27 | case Protocol::Udp: return L"protocol = UDP"; 28 | case Protocol::Icmp: return L"protocol = ICMP"; 29 | case Protocol::IcmpV6: return L"protocol = ICMPv6"; 30 | case Protocol::Ip: return L"protocol = IP"; 31 | case Protocol::IpV6: return L"protocol = IPv6"; 32 | case Protocol::Raw: return L"protocol = Raw"; 33 | default: 34 | { 35 | THROW_ERROR("Missing case handler"); 36 | } 37 | } 38 | } 39 | 40 | const GUID &ConditionProtocol::identifier() const 41 | { 42 | return FWPM_CONDITION_IP_PROTOCOL; 43 | } 44 | 45 | const FWPM_FILTER_CONDITION0 &ConditionProtocol::condition() const 46 | { 47 | return *reinterpret_cast(m_assembled.data()); 48 | } 49 | 50 | //static 51 | std::unique_ptr ConditionProtocol::Tcp() 52 | { 53 | return std::unique_ptr(new ConditionProtocol(Protocol::Tcp)); 54 | } 55 | 56 | //static 57 | std::unique_ptr ConditionProtocol::Udp() 58 | { 59 | return std::unique_ptr(new ConditionProtocol(Protocol::Udp)); 60 | } 61 | 62 | //static 63 | std::unique_ptr ConditionProtocol::Icmp() 64 | { 65 | return std::unique_ptr(new ConditionProtocol(Protocol::Icmp)); 66 | } 67 | 68 | //static 69 | std::unique_ptr ConditionProtocol::IcmpV6() 70 | { 71 | return std::unique_ptr(new ConditionProtocol(Protocol::IcmpV6)); 72 | } 73 | 74 | //static 75 | std::unique_ptr ConditionProtocol::Ip() 76 | { 77 | return std::unique_ptr(new ConditionProtocol(Protocol::Ip)); 78 | } 79 | 80 | //static 81 | std::unique_ptr ConditionProtocol::IpV6() 82 | { 83 | return std::unique_ptr(new ConditionProtocol(Protocol::IpV6)); 84 | } 85 | 86 | //static 87 | std::unique_ptr ConditionProtocol::Raw() 88 | { 89 | return std::unique_ptr(new ConditionProtocol(Protocol::Raw)); 90 | } 91 | 92 | // static 93 | uint8_t ConditionProtocol::TranslateProtocol(Protocol protocol) 94 | { 95 | switch (protocol) 96 | { 97 | case Protocol::Tcp: return IPPROTO_TCP; 98 | case Protocol::Udp: return IPPROTO_UDP; 99 | case Protocol::Icmp: return IPPROTO_ICMP; 100 | case Protocol::IcmpV6: return IPPROTO_ICMPV6; 101 | case Protocol::Ip: return IPPROTO_IPV4; 102 | case Protocol::IpV6: return IPPROTO_IPV6; 103 | case Protocol::Raw: return IPPROTO_RAW; 104 | default: 105 | { 106 | THROW_ERROR("Missing case handler"); 107 | } 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/libwfp/conditions/conditionprotocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ifiltercondition.h" 4 | #include 5 | #include 6 | 7 | namespace wfp::conditions { 8 | 9 | class ConditionProtocol : public IFilterCondition 10 | { 11 | enum class Protocol 12 | { 13 | Tcp, 14 | Udp, 15 | Icmp, 16 | IcmpV6, 17 | Ip, 18 | IpV6, 19 | Raw 20 | }; 21 | 22 | ConditionProtocol(Protocol protocol); 23 | 24 | public: 25 | 26 | static std::unique_ptr Tcp(); 27 | static std::unique_ptr Udp(); 28 | static std::unique_ptr Icmp(); 29 | static std::unique_ptr IcmpV6(); 30 | static std::unique_ptr Ip(); 31 | static std::unique_ptr IpV6(); 32 | static std::unique_ptr Raw(); 33 | 34 | std::wstring toString() const override; 35 | const GUID &identifier() const override; 36 | const FWPM_FILTER_CONDITION0 &condition() const override; 37 | 38 | private: 39 | 40 | Protocol m_protocol; 41 | common::Buffer m_assembled; 42 | 43 | static uint8_t TranslateProtocol(Protocol protocol); 44 | }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/libwfp/conditions/icomparisonoperator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace wfp::conditions { 7 | 8 | struct IComparisonOperator 9 | { 10 | virtual FWP_MATCH_TYPE op() const = 0; 11 | virtual std::wstring toString() const = 0; 12 | virtual ~IComparisonOperator() {} 13 | }; 14 | 15 | struct IStrictComparison : public IComparisonOperator 16 | { 17 | }; 18 | 19 | struct IRelaxedComparison : public IComparisonOperator 20 | { 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/libwfp/conditions/ifiltercondition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wfp::conditions { 8 | 9 | struct IFilterCondition 10 | { 11 | virtual std::wstring toString() const = 0; 12 | virtual const GUID &identifier() const = 0; 13 | virtual const FWPM_FILTER_CONDITION0 &condition() const = 0; 14 | 15 | virtual ~IFilterCondition() {} 16 | }; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/libwfp/filterbuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "filterbuilder.h" 3 | #include 4 | #include 5 | 6 | namespace wfp 7 | { 8 | 9 | FilterBuilder::FilterBuilder(BuilderValidation validation) 10 | : m_validation(validation) 11 | { 12 | memset(&m_filter, 0, sizeof(m_filter)); 13 | } 14 | 15 | FilterBuilder &FilterBuilder::key(const GUID &key) 16 | { 17 | m_keyProvided = true; 18 | 19 | memcpy(&m_filter.filterKey, &key, sizeof(m_filter.filterKey)); 20 | return *this; 21 | } 22 | 23 | FilterBuilder &FilterBuilder::name(const std::wstring &name) 24 | { 25 | m_nameProvided = true; 26 | 27 | m_name = name; 28 | m_filter.displayData.name = const_cast(m_name.c_str()); 29 | 30 | return *this; 31 | } 32 | 33 | FilterBuilder &FilterBuilder::description(const std::wstring &description) 34 | { 35 | m_description = description; 36 | m_filter.displayData.description = const_cast(m_description.c_str()); 37 | 38 | return *this; 39 | } 40 | 41 | FilterBuilder &FilterBuilder::persistent() 42 | { 43 | m_filter.flags |= FWPM_FILTER_FLAG_PERSISTENT; 44 | return *this; 45 | } 46 | 47 | FilterBuilder &FilterBuilder::boottime() 48 | { 49 | m_filter.flags |= FWPM_FILTER_FLAG_BOOTTIME; 50 | return *this; 51 | } 52 | 53 | 54 | FilterBuilder &FilterBuilder::disabled() 55 | { 56 | m_filter.flags |= FWPM_FILTER_FLAG_DISABLED; 57 | return *this; 58 | } 59 | 60 | FilterBuilder &FilterBuilder::definitive() 61 | { 62 | m_filter.flags |= FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT; 63 | return *this; 64 | } 65 | 66 | FilterBuilder &FilterBuilder::provider(const GUID &provider) 67 | { 68 | m_providerProvided = true; 69 | 70 | memcpy(&m_providerKey, &provider, sizeof(m_providerKey)); 71 | m_filter.providerKey = &m_providerKey; 72 | 73 | return *this; 74 | } 75 | 76 | FilterBuilder &FilterBuilder::layer(const GUID &layer) 77 | { 78 | m_layerProvided = true; 79 | 80 | memcpy(&m_filter.layerKey, &layer, sizeof(m_filter.layerKey)); 81 | return *this; 82 | } 83 | 84 | FilterBuilder &FilterBuilder::sublayer(const GUID &sublayer) 85 | { 86 | m_sublayerProvided = true; 87 | 88 | memcpy(&m_filter.subLayerKey, &sublayer, sizeof(m_filter.subLayerKey)); 89 | return *this; 90 | } 91 | 92 | FilterBuilder &FilterBuilder::weight(UINT64 weight) 93 | { 94 | m_weightProvided = true; 95 | 96 | m_weight = weight; 97 | 98 | m_filter.weight.type = FWP_UINT64; 99 | m_filter.weight.uint64 = &m_weight; 100 | 101 | return *this; 102 | } 103 | 104 | FilterBuilder &FilterBuilder::weight(WeightClass cls) 105 | { 106 | m_weightProvided = true; 107 | 108 | m_filter.weight.type = FWP_UINT8; 109 | m_filter.weight.uint8 = static_cast(cls); 110 | 111 | return *this; 112 | } 113 | 114 | FilterBuilder &FilterBuilder::block() 115 | { 116 | m_verdictProvided = true; 117 | 118 | m_filter.action.type = FWP_ACTION_BLOCK; 119 | return *this; 120 | } 121 | 122 | FilterBuilder &FilterBuilder::permit() 123 | { 124 | m_verdictProvided = true; 125 | 126 | m_filter.action.type = FWP_ACTION_PERMIT; 127 | return *this; 128 | } 129 | 130 | bool FilterBuilder::build(FilterSink sink) 131 | { 132 | switch (m_validation) 133 | { 134 | case BuilderValidation::Extra: 135 | { 136 | if (false == m_keyProvided 137 | || false == m_providerProvided 138 | || false == m_sublayerProvided) 139 | { 140 | THROW_ERROR("Rejecting partially initialized sublayer"); 141 | } 142 | 143 | // No break, fall through. 144 | } 145 | case BuilderValidation::OnlyCritical: 146 | { 147 | if (false == m_nameProvided 148 | || false == m_layerProvided 149 | || false == m_weightProvided 150 | || false == m_verdictProvided) 151 | { 152 | THROW_ERROR("Rejecting partially initialized sublayer"); 153 | } 154 | 155 | break; 156 | } 157 | } 158 | 159 | return sink(m_filter); 160 | } 161 | 162 | const GUID &FilterBuilder::id() const 163 | { 164 | return m_filter.filterKey; 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/libwfp/filterbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iidentifiable.h" 4 | #include "buildervalidation.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace wfp 12 | { 13 | 14 | // 15 | // Note: This builder is incomplete! 16 | // 17 | // Creating a self-contained object is fairly complex so this is currently not being attempted. 18 | // Use the builder for creating almost-complete filters and complement them once built. 19 | // 20 | // More methods could be added but all fields were not needed at this time. 21 | // 22 | 23 | typedef std::function FilterSink; 24 | 25 | class FilterBuilder : public IIdentifiable 26 | { 27 | public: 28 | 29 | FilterBuilder(BuilderValidation validation = BuilderValidation::Extra); 30 | 31 | FilterBuilder(const FilterBuilder&) = delete; 32 | FilterBuilder &operator=(const FilterBuilder&) = delete; 33 | 34 | FilterBuilder &key(const GUID &key); 35 | FilterBuilder &name(const std::wstring &name); 36 | FilterBuilder &description(const std::wstring &description); 37 | 38 | FilterBuilder &persistent(); 39 | FilterBuilder &boottime(); 40 | FilterBuilder &disabled(); 41 | FilterBuilder &definitive(); 42 | 43 | FilterBuilder &provider(const GUID &provider); 44 | FilterBuilder &layer(const GUID &layer); 45 | FilterBuilder &sublayer(const GUID &sublayer); 46 | 47 | FilterBuilder &weight(UINT64 weight); 48 | 49 | enum class WeightClass : uint8_t 50 | { 51 | Class0 = 0, 52 | Class1, 53 | Class2, 54 | Class3, 55 | Class4, 56 | Class5, 57 | Class6, 58 | Class7, 59 | Class8, 60 | Class9, 61 | Class10, 62 | Class11, 63 | Class12, 64 | Class13, 65 | Class14, 66 | Class15, 67 | 68 | Min = Class0, 69 | Medium = Class7, 70 | Max = Class15 71 | }; 72 | 73 | FilterBuilder &weight(WeightClass cls); 74 | 75 | FilterBuilder &block(); 76 | FilterBuilder &permit(); 77 | 78 | bool build(FilterSink sink); 79 | 80 | const GUID &IIdentifiable::id() const override; 81 | 82 | private: 83 | 84 | FWPM_FILTER0 m_filter; 85 | 86 | std::wstring m_name; 87 | std::wstring m_description; 88 | GUID m_providerKey; 89 | UINT64 m_weight; 90 | 91 | BuilderValidation m_validation; 92 | 93 | bool m_keyProvided = false; 94 | bool m_nameProvided = false; 95 | bool m_providerProvided = false; 96 | bool m_layerProvided = false; 97 | bool m_sublayerProvided = false; 98 | bool m_weightProvided = false; 99 | bool m_verdictProvided = false; 100 | }; 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/libwfp/filterengine.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "filterengine.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wfp 9 | { 10 | 11 | FilterEngine::FilterEngine(bool dynamic, uint32_t *timeout) 12 | { 13 | FWPM_SESSION0 sessionInfo = { 0 }; 14 | 15 | // A timeout of 0 ms is interpreted by WFP to mean "system default timeout". 16 | sessionInfo.txnWaitTimeoutInMSec = (nullptr == timeout ? 0 : *timeout); 17 | 18 | if (dynamic) 19 | { 20 | sessionInfo.flags = FWPM_SESSION_FLAG_DYNAMIC; 21 | } 22 | 23 | HANDLE session = INVALID_HANDLE_VALUE; 24 | 25 | auto status = FwpmEngineOpen0( 26 | nullptr, 27 | RPC_C_AUTHN_DEFAULT, 28 | nullptr, 29 | &sessionInfo, 30 | &session 31 | ); 32 | 33 | if (ERROR_SUCCESS != status) 34 | { 35 | THROW_WINDOWS_ERROR(status, "Connect to WFP"); 36 | } 37 | 38 | m_session = session; 39 | } 40 | 41 | //static 42 | std::unique_ptr FilterEngine::DynamicSession() 43 | { 44 | return std::unique_ptr(new FilterEngine(true, nullptr)); 45 | } 46 | 47 | //static 48 | std::unique_ptr FilterEngine::StandardSession() 49 | { 50 | return std::unique_ptr(new FilterEngine(false, nullptr)); 51 | } 52 | 53 | //static 54 | std::unique_ptr FilterEngine::DynamicSession(uint32_t timeout) 55 | { 56 | return std::unique_ptr(new FilterEngine(true, &timeout)); 57 | } 58 | 59 | //static 60 | std::unique_ptr FilterEngine::StandardSession(uint32_t timeout) 61 | { 62 | return std::unique_ptr(new FilterEngine(false, &timeout)); 63 | } 64 | 65 | FilterEngine::~FilterEngine() 66 | { 67 | FwpmEngineClose0(m_session); 68 | } 69 | 70 | HANDLE FilterEngine::session() const 71 | { 72 | return m_session; 73 | } 74 | 75 | } // namespace wfp 76 | -------------------------------------------------------------------------------- /src/libwfp/filterengine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // 4 | // This would be more suitably placed into `libwfp.h`, alas there is no such file 5 | // 6 | #pragma comment(lib, "fwpuclnt.lib") 7 | #pragma comment(lib, "ws2_32.lib") 8 | #pragma comment(lib, "iphlpapi.lib") 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace wfp 15 | { 16 | 17 | class FilterEngine 18 | { 19 | FilterEngine(bool dynamic, uint32_t *timeout); 20 | 21 | public: 22 | 23 | // Create a session using a default timeout when waiting for the transaction lock. 24 | // The system default timeout on Windows 10 is 100 minutes. 25 | static std::unique_ptr DynamicSession(); 26 | static std::unique_ptr StandardSession(); 27 | 28 | // Create a session using a specific timeout when waiting for the transaction lock. 29 | // The timeout value is specified in milliseconds. 30 | // Specifying a timeout of INFINITE will cause an indefinite wait. 31 | // Zero is a reserved value in this context and means "system default timeout". 32 | static std::unique_ptr DynamicSession(uint32_t timeout); 33 | static std::unique_ptr StandardSession(uint32_t timeout); 34 | 35 | ~FilterEngine(); 36 | 37 | HANDLE session() const; 38 | 39 | private: 40 | 41 | FilterEngine(const FilterEngine &) = delete; 42 | FilterEngine &operator=(const FilterEngine &) = delete; 43 | 44 | HANDLE m_session; 45 | }; 46 | 47 | } // namespace wfp 48 | -------------------------------------------------------------------------------- /src/libwfp/iconditionbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace wfp 7 | { 8 | 9 | typedef std::function ConditionSink; 10 | 11 | struct IConditionBuilder 12 | { 13 | virtual ~IConditionBuilder() = 0 14 | { 15 | } 16 | 17 | virtual bool build(ConditionSink sink) const = 0; 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/libwfp/iidentifiable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | struct IIdentifiable 9 | { 10 | virtual ~IIdentifiable() = 0 11 | { 12 | } 13 | 14 | virtual const GUID &id() const = 0; 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/libwfp/internal/conditionassembler.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "conditionassembler.h" 3 | #include 4 | 5 | using Buffer = ::common::Buffer; 6 | using ConstBufferView = ::common::ConstBufferView; 7 | 8 | #define MAKE_PTR(ptrbase, ptroffset, datatype) reinterpret_cast(reinterpret_cast(ptrbase) + ptroffset) 9 | 10 | namespace wfp::internal { 11 | 12 | //static 13 | Buffer ConditionAssembler::ByteBlob( 14 | const GUID &identifier, 15 | FWP_MATCH_TYPE matchType, 16 | const FWP_BYTE_BLOB &blob) 17 | { 18 | FWPM_FILTER_CONDITION0 definition; 19 | 20 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 21 | definition.matchType = matchType; 22 | definition.conditionValue.type = FWP_BYTE_BLOB_TYPE; 23 | 24 | // 25 | // Goal, buffer with: 26 | // 27 | // FWPM_FILTER_CONDITION0 28 | // FWP_BYTE_BLOB 29 | // raw blob data 30 | // 31 | 32 | auto composer = ::common::BinaryComposer 33 | { 34 | ConstBufferView(&definition, sizeof(definition)), 35 | ConstBufferView(&blob, sizeof(blob)), 36 | ConstBufferView(blob.data, blob.size) 37 | }; 38 | 39 | auto buffer = composer.buffer(); 40 | auto offsets = composer.offsets(); 41 | 42 | // 43 | // Correct stored pointers 44 | // 45 | 46 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 47 | auto finalBlob = MAKE_PTR(buffer, offsets[1], FWP_BYTE_BLOB); 48 | auto finalData = MAKE_PTR(buffer, offsets[2], uint8_t); 49 | 50 | finalDefinition->conditionValue.byteBlob = finalBlob; 51 | finalBlob->data = finalData; 52 | 53 | return composer.acquire(); 54 | } 55 | 56 | //static 57 | Buffer ConditionAssembler::Uint16( 58 | const GUID &identifier, 59 | FWP_MATCH_TYPE matchType, 60 | UINT16 value) 61 | { 62 | auto definition = std::make_unique(); 63 | 64 | memcpy(&definition->fieldKey, &identifier, sizeof(identifier)); 65 | definition->matchType = matchType; 66 | definition->conditionValue.type = FWP_UINT16; 67 | definition->conditionValue.uint16 = value; 68 | 69 | return Buffer(definition.release(), sizeof(FWPM_FILTER_CONDITION0)); 70 | } 71 | 72 | //static 73 | Buffer ConditionAssembler::Uint8( 74 | const GUID &identifier, 75 | FWP_MATCH_TYPE matchType, 76 | UINT8 value) 77 | { 78 | auto definition = std::make_unique(); 79 | 80 | memcpy(&definition->fieldKey, &identifier, sizeof(identifier)); 81 | definition->matchType = matchType; 82 | definition->conditionValue.type = FWP_UINT8; 83 | definition->conditionValue.uint8 = value; 84 | 85 | return Buffer(definition.release(), sizeof(FWPM_FILTER_CONDITION0)); 86 | } 87 | 88 | //static 89 | Buffer ConditionAssembler::Uint32( 90 | const GUID &identifier, 91 | FWP_MATCH_TYPE matchType, 92 | UINT32 value) 93 | { 94 | auto definition = std::make_unique(); 95 | 96 | memcpy(&definition->fieldKey, &identifier, sizeof(identifier)); 97 | definition->matchType = matchType; 98 | definition->conditionValue.type = FWP_UINT32; 99 | definition->conditionValue.uint32 = value; 100 | 101 | return Buffer(definition.release(), sizeof(FWPM_FILTER_CONDITION0)); 102 | } 103 | 104 | //static 105 | Buffer ConditionAssembler::ByteArray16( 106 | const GUID &identifier, 107 | FWP_MATCH_TYPE matchType, 108 | const FWP_BYTE_ARRAY16 &array) 109 | { 110 | FWPM_FILTER_CONDITION0 definition; 111 | 112 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 113 | definition.matchType = matchType; 114 | definition.conditionValue.type = FWP_BYTE_ARRAY16_TYPE; 115 | 116 | // 117 | // Goal, buffer with: 118 | // 119 | // FWPM_FILTER_CONDITION0 120 | // FWP_BYTE_ARRAY16 121 | // 122 | 123 | auto composer = ::common::BinaryComposer 124 | { 125 | ConstBufferView(&definition, sizeof(definition)), 126 | ConstBufferView(&array, sizeof(array)) 127 | }; 128 | 129 | auto buffer = composer.buffer(); 130 | auto offsets = composer.offsets(); 131 | 132 | // 133 | // Correct stored pointer 134 | // 135 | 136 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 137 | auto finalArray = MAKE_PTR(buffer, offsets[1], FWP_BYTE_ARRAY16); 138 | 139 | finalDefinition->conditionValue.byteArray16 = finalArray; 140 | 141 | return composer.acquire(); 142 | } 143 | 144 | //static 145 | Buffer ConditionAssembler::Range( 146 | const GUID &identifier, 147 | FWP_MATCH_TYPE matchType, 148 | const FWP_RANGE0 &range) 149 | { 150 | FWPM_FILTER_CONDITION0 definition; 151 | 152 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 153 | definition.matchType = matchType; 154 | definition.conditionValue.type = FWP_RANGE_TYPE; 155 | 156 | // 157 | // Goal, buffer with: 158 | // 159 | // FWPM_FILTER_CONDITION0 160 | // FWP_RANGE0 161 | // 162 | 163 | auto composer = ::common::BinaryComposer 164 | { 165 | ConstBufferView(&definition, sizeof(definition)), 166 | ConstBufferView(&range, sizeof(range)) 167 | }; 168 | 169 | auto buffer = composer.buffer(); 170 | auto offsets = composer.offsets(); 171 | 172 | // 173 | // Correct stored pointer 174 | // 175 | 176 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 177 | auto finalRange = MAKE_PTR(buffer, offsets[1], FWP_RANGE0); 178 | 179 | finalDefinition->conditionValue.rangeValue = finalRange; 180 | 181 | return composer.acquire(); 182 | } 183 | 184 | //static 185 | Buffer ConditionAssembler::Uint64( 186 | const GUID &identifier, 187 | FWP_MATCH_TYPE matchType, 188 | UINT64 value) 189 | { 190 | FWPM_FILTER_CONDITION0 definition; 191 | 192 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 193 | definition.matchType = matchType; 194 | definition.conditionValue.type = FWP_UINT64; 195 | 196 | // 197 | // Goal, buffer with: 198 | // 199 | // FWPM_FILTER_CONDITION0 200 | // UINT64 201 | // 202 | 203 | auto composer = ::common::BinaryComposer 204 | { 205 | ConstBufferView(&definition, sizeof(definition)), 206 | ConstBufferView(&value, sizeof(value)) 207 | }; 208 | 209 | auto buffer = composer.buffer(); 210 | auto offsets = composer.offsets(); 211 | 212 | // 213 | // Correct stored pointer 214 | // 215 | 216 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 217 | auto finalValue = MAKE_PTR(buffer, offsets[1], UINT64); 218 | 219 | finalDefinition->conditionValue.uint64 = finalValue; 220 | 221 | return composer.acquire(); 222 | } 223 | 224 | //static 225 | Buffer ConditionAssembler::Ipv4Network( 226 | const GUID &identifier, 227 | FWP_MATCH_TYPE matchType, 228 | const FWP_V4_ADDR_AND_MASK &network) 229 | { 230 | FWPM_FILTER_CONDITION0 definition; 231 | 232 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 233 | definition.matchType = matchType; 234 | definition.conditionValue.type = FWP_V4_ADDR_MASK; 235 | 236 | // 237 | // Goal, buffer with: 238 | // 239 | // FWPM_FILTER_CONDITION0 240 | // FWP_V4_ADDR_AND_MASK 241 | // 242 | 243 | auto composer = ::common::BinaryComposer 244 | { 245 | ConstBufferView(&definition, sizeof(definition)), 246 | ConstBufferView(&network, sizeof(network)) 247 | }; 248 | 249 | auto buffer = composer.buffer(); 250 | auto offsets = composer.offsets(); 251 | 252 | // 253 | // Correct stored pointer 254 | // 255 | 256 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 257 | auto finalNetwork = MAKE_PTR(buffer, offsets[1], FWP_V4_ADDR_AND_MASK); 258 | 259 | finalDefinition->conditionValue.v4AddrMask = finalNetwork; 260 | 261 | return composer.acquire(); 262 | } 263 | 264 | //static 265 | Buffer ConditionAssembler::Ipv6Network( 266 | const GUID &identifier, 267 | FWP_MATCH_TYPE matchType, 268 | const FWP_V6_ADDR_AND_MASK &network) 269 | { 270 | FWPM_FILTER_CONDITION0 definition; 271 | 272 | memcpy(&definition.fieldKey, &identifier, sizeof(identifier)); 273 | definition.matchType = matchType; 274 | definition.conditionValue.type = FWP_V6_ADDR_MASK; 275 | 276 | // 277 | // Goal, buffer with: 278 | // 279 | // FWPM_FILTER_CONDITION0 280 | // FWP_V6_ADDR_AND_MASK 281 | // 282 | 283 | auto composer = ::common::BinaryComposer 284 | { 285 | ConstBufferView(&definition, sizeof(definition)), 286 | ConstBufferView(&network, sizeof(network)) 287 | }; 288 | 289 | auto buffer = composer.buffer(); 290 | auto offsets = composer.offsets(); 291 | 292 | // 293 | // Correct stored pointer 294 | // 295 | 296 | auto finalDefinition = MAKE_PTR(buffer, offsets[0], FWPM_FILTER_CONDITION0); 297 | auto finalNetwork = MAKE_PTR(buffer, offsets[1], FWP_V6_ADDR_AND_MASK); 298 | 299 | finalDefinition->conditionValue.v6AddrMask = finalNetwork; 300 | 301 | return composer.acquire(); 302 | } 303 | 304 | } 305 | -------------------------------------------------------------------------------- /src/libwfp/internal/conditionassembler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wfp::internal { 8 | 9 | class ConditionAssembler 10 | { 11 | public: 12 | 13 | static common::Buffer ByteBlob(const GUID &identifier, FWP_MATCH_TYPE matchType, const FWP_BYTE_BLOB &data); 14 | static common::Buffer Uint16(const GUID &identifier, FWP_MATCH_TYPE matchType, UINT16 value); 15 | static common::Buffer Uint8(const GUID &identifier, FWP_MATCH_TYPE matchType, UINT8 value); 16 | static common::Buffer Uint32(const GUID &identifier, FWP_MATCH_TYPE matchType, UINT32 value); 17 | static common::Buffer ByteArray16(const GUID &identifier, FWP_MATCH_TYPE matchType, const FWP_BYTE_ARRAY16 &array); 18 | static common::Buffer Range(const GUID &identifier, FWP_MATCH_TYPE matchType, const FWP_RANGE0 &range); 19 | static common::Buffer Uint64(const GUID &identifier, FWP_MATCH_TYPE matchType, UINT64 value); 20 | static common::Buffer Ipv4Network(const GUID &identifier, FWP_MATCH_TYPE matchType, const FWP_V4_ADDR_AND_MASK &network); 21 | static common::Buffer Ipv6Network(const GUID &identifier, FWP_MATCH_TYPE matchType, const FWP_V6_ADDR_AND_MASK &network); 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/libwfp/ipaddress.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ipaddress.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace 9 | { 10 | 11 | uint32_t PackIpv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) 12 | { 13 | return ((uint32_t(a) << 24) | (uint32_t(b) << 16) | (uint32_t(c) << 8) | d); 14 | } 15 | 16 | } // anonymous namespace 17 | 18 | namespace wfp 19 | { 20 | 21 | IpAddress::Literal::Literal(const std::initializer_list &netnode) 22 | { 23 | if (netnode.size() != 4) 24 | { 25 | THROW_ERROR("Invalid IPv4 specification"); 26 | } 27 | 28 | auto it = netnode.begin(); 29 | 30 | auto a = *it++; 31 | auto b = *it++; 32 | auto c = *it++; 33 | auto d = *it++; 34 | 35 | address = PackIpv4(a, b, c, d); 36 | } 37 | 38 | IpAddress::Literal6::Literal6(const std::initializer_list &netnode) 39 | { 40 | if (netnode.size() != 8) 41 | { 42 | THROW_ERROR("Invalid IPv6 specification"); 43 | } 44 | 45 | size_t index = 0; 46 | 47 | for (uint16_t hextet : netnode) 48 | { 49 | address[index++] = uint8_t((hextet & 0xFF00) >> 8); 50 | address[index++] = uint8_t(hextet & 0xFF); 51 | } 52 | } 53 | 54 | IpAddress::IpAddress(const std::wstring &netnode) 55 | { 56 | uint8_t buffer[sizeof(IN6_ADDR)]; 57 | 58 | if (1 == InetPtonW(AF_INET, netnode.c_str(), &buffer)) 59 | { 60 | auto parsed = reinterpret_cast(&buffer); 61 | 62 | m_ipv4 = ntohl(parsed->s_addr); 63 | m_type = Type::Ipv4; 64 | 65 | memset(m_ipv6, 0, sizeof(m_ipv6)); 66 | } 67 | else if (1 == InetPtonW(AF_INET6, netnode.c_str(), &buffer)) 68 | { 69 | auto parsed = reinterpret_cast(&buffer); 70 | 71 | memcpy(m_ipv6, parsed->u.Byte, sizeof(m_ipv6)); 72 | m_type = Type::Ipv6; 73 | 74 | m_ipv4 = 0; 75 | } 76 | else 77 | { 78 | THROW_ERROR("Parser failure: Invalid IP address"); 79 | } 80 | } 81 | 82 | IpAddress::IpAddress(uint32_t netnode) 83 | : m_ipv4(netnode) 84 | , m_type(Type::Ipv4) 85 | { 86 | memset(m_ipv6, 0, sizeof(m_ipv6)); 87 | } 88 | 89 | IpAddress::IpAddress(const IpAddress::Literal &netnode) 90 | : IpAddress(netnode.address) 91 | { 92 | } 93 | 94 | IpAddress::IpAddress(const FWP_BYTE_ARRAY16 &netnode) 95 | : m_ipv4(0) 96 | , m_type(Type::Ipv6) 97 | { 98 | memcpy(m_ipv6, netnode.byteArray16, sizeof(m_ipv6)); 99 | } 100 | 101 | IpAddress::IpAddress(const IpAddress::Literal6 &netnode) 102 | : m_ipv4(0) 103 | , m_type(Type::Ipv6) 104 | { 105 | memcpy(m_ipv6, netnode.address, sizeof(m_ipv6)); 106 | } 107 | 108 | std::wstring IpAddress::toString() const 109 | { 110 | switch (m_type) 111 | { 112 | case Type::Ipv4: 113 | { 114 | return common::string::FormatIpv4(m_ipv4); 115 | } 116 | case Type::Ipv6: 117 | { 118 | return common::string::FormatIpv6(m_ipv6); 119 | } 120 | default: 121 | { 122 | THROW_ERROR("Missing case handler in switch clause"); 123 | } 124 | } 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/libwfp/ipaddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wfp 9 | { 10 | 11 | // 12 | // Abstraction over a specific IPv4/IPv6 address. 13 | // For IPv4, host byte order is used. 14 | // 15 | class IpAddress 16 | { 17 | public: 18 | 19 | struct Literal; 20 | struct Literal6; 21 | 22 | // Generic 23 | IpAddress(const std::wstring &netnode); 24 | 25 | // IPv4 26 | IpAddress(uint32_t netnode); 27 | IpAddress(const Literal &netnode); 28 | 29 | // IPv6 30 | IpAddress(const FWP_BYTE_ARRAY16 &netnode); 31 | IpAddress(const Literal6 &netnode); 32 | 33 | // 34 | // Helper-types to construct from literal address 35 | // 36 | 37 | struct Literal 38 | { 39 | Literal(const std::initializer_list &netnode); 40 | uint32_t address; 41 | }; 42 | 43 | struct Literal6 44 | { 45 | Literal6(const std::initializer_list &netnode); 46 | uint8_t address[16]; 47 | }; 48 | 49 | enum Type 50 | { 51 | Ipv4, 52 | Ipv6 53 | }; 54 | 55 | Type type() const 56 | { 57 | return m_type; 58 | } 59 | 60 | uint32_t addr() const 61 | { 62 | return m_ipv4; 63 | } 64 | 65 | const FWP_BYTE_ARRAY16 &addr6() const 66 | { 67 | return *reinterpret_cast(m_ipv6); 68 | } 69 | 70 | std::wstring toString() const; 71 | 72 | bool operator==(const IpAddress &other) const 73 | { 74 | if (Type::Ipv4 == m_type) 75 | { 76 | return Type::Ipv4 == other.m_type && m_ipv4 == other.m_ipv4; 77 | } 78 | return Type::Ipv6 == other.m_type 79 | && 0 == memcmp(m_ipv6, other.m_ipv6, sizeof(m_ipv6)); 80 | } 81 | 82 | private: 83 | 84 | uint32_t m_ipv4; 85 | uint8_t m_ipv6[16]; 86 | 87 | Type m_type; 88 | }; 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/libwfp/ipnetwork.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ipnetwork.h" 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wfp 8 | { 9 | 10 | IpNetwork::IpNetwork(const IpAddress &addr, uint8_t prefix) 11 | : m_prefix(prefix) 12 | { 13 | switch (addr.type()) 14 | { 15 | case IpAddress::Type::Ipv4: 16 | { 17 | m_type = Type::Ipv4; 18 | 19 | m_net.addr = addr.addr(); 20 | m_net.mask = common::network::MaskFromRoutingPrefix(prefix); 21 | 22 | break; 23 | } 24 | case IpAddress::Type::Ipv6: 25 | { 26 | m_type = Type::Ipv6; 27 | 28 | memcpy(m_net6.addr, addr.addr6().byteArray16, sizeof(m_net6.addr)); 29 | m_net6.prefixLength = prefix; 30 | 31 | break; 32 | } 33 | default: 34 | { 35 | THROW_ERROR("Missing case handler in switch clause"); 36 | } 37 | } 38 | } 39 | 40 | std::wstring IpNetwork::toString() const 41 | { 42 | switch (m_type) 43 | { 44 | case Type::Ipv4: 45 | { 46 | return common::string::FormatIpv4(m_net.addr, m_prefix); 47 | } 48 | case Type::Ipv6: 49 | { 50 | return common::string::FormatIpv6(m_net6.addr, m_net6.prefixLength); 51 | } 52 | default: 53 | { 54 | THROW_ERROR("Missing case handler in switch clause"); 55 | } 56 | } 57 | } 58 | 59 | bool IpNetwork::includes(const IpAddress &address) const 60 | { 61 | if (Type::Ipv4 == m_type) 62 | { 63 | if (IpAddress::Type::Ipv4 != address.type()) 64 | { 65 | return false; 66 | } 67 | 68 | const auto mask = common::network::MaskFromRoutingPrefix(m_prefix); 69 | return (address.addr() & mask) == (m_net.addr & mask); 70 | } 71 | 72 | if (IpAddress::Type::Ipv6 != address.type()) 73 | { 74 | return false; 75 | } 76 | 77 | uint32_t numWholeBytes = m_prefix / 8; 78 | const auto otherArray = address.addr6().byteArray16; 79 | 80 | if (0 != memcmp(m_net6.addr, otherArray, numWholeBytes)) 81 | { 82 | return false; 83 | } 84 | 85 | uint32_t byteMask = ~((uint32_t(1) << (8 - (m_prefix % 8))) - 1); 86 | return (otherArray[numWholeBytes] & byteMask) == (m_net6.addr[numWholeBytes] & byteMask); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/libwfp/ipnetwork.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "ipaddress.h" 7 | 8 | namespace wfp 9 | { 10 | 11 | class IpNetwork 12 | { 13 | public: 14 | 15 | IpNetwork(const IpAddress &addr, uint8_t prefix); 16 | 17 | enum Type 18 | { 19 | Ipv4, 20 | Ipv6 21 | }; 22 | 23 | Type type() const 24 | { 25 | return m_type; 26 | } 27 | 28 | const FWP_V4_ADDR_AND_MASK &net() const 29 | { 30 | return m_net; 31 | } 32 | 33 | const FWP_V6_ADDR_AND_MASK &net6() const 34 | { 35 | return m_net6; 36 | } 37 | 38 | std::wstring toString() const; 39 | 40 | bool includes(const IpAddress &address) const; 41 | 42 | private: 43 | 44 | Type m_type; 45 | 46 | // TODO: Resolve having to store this separately for IPv4 nets. 47 | uint8_t m_prefix; 48 | 49 | FWP_V4_ADDR_AND_MASK m_net; 50 | FWP_V6_ADDR_AND_MASK m_net6; 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/libwfp/layerconditions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "layerconditions.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace wfp 13 | { 14 | 15 | namespace 16 | { 17 | 18 | // These arrays could be sorted to allow divide-and-conquer lookup, but meh 19 | 20 | static const GUID CONDITIONS_INBOUND_IP_PACKET[] = 21 | { 22 | FWPM_CONDITION_FLAGS, 23 | FWPM_CONDITION_INTERFACE_INDEX, 24 | FWPM_CONDITION_INTERFACE_TYPE, 25 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 26 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 27 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 28 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 29 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 30 | FWPM_CONDITION_TUNNEL_TYPE 31 | }; 32 | 33 | static const GUID CONDITIONS_OUTBOUND_IP_PACKET[] = 34 | { 35 | FWPM_CONDITION_FLAGS, 36 | FWPM_CONDITION_INTERFACE_INDEX, 37 | FWPM_CONDITION_INTERFACE_TYPE, 38 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 39 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 40 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 41 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 42 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 43 | FWPM_CONDITION_TUNNEL_TYPE 44 | }; 45 | 46 | static const GUID CONDITIONS_IPFORWARD[] = 47 | { 48 | FWPM_CONDITION_FLAGS, 49 | FWPM_CONDITION_DESTINATION_INTERFACE_INDEX, 50 | FWPM_CONDITION_DESTINATION_SUB_INTERFACE_INDEX, 51 | FWPM_CONDITION_IP_DESTINATION_ADDRESS, 52 | FWPM_CONDITION_IP_DESTINATION_ADDRESS_TYPE, 53 | FWPM_CONDITION_IP_FORWARD_INTERFACE, 54 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 55 | FWPM_CONDITION_IP_SOURCE_ADDRESS, 56 | FWPM_CONDITION_SOURCE_INTERFACE_INDEX, 57 | FWPM_CONDITION_SOURCE_SUB_INTERFACE_INDEX, 58 | 59 | // Windows 7 and later: 60 | FWPM_CONDITION_IP_PHYSICAL_ARRIVAL_INTERFACE, 61 | FWPM_CONDITION_IP_PHYSICAL_NEXTHOP_INTERFACE, 62 | FWPM_CONDITION_ARRIVAL_INTERFACE_PROFILE_ID, 63 | FWPM_CONDITION_NEXTHOP_INTERFACE_PROFILE_ID 64 | }; 65 | 66 | static const GUID CONDITIONS_INBOUND_TRANSPORT[] = 67 | { 68 | FWPM_CONDITION_FLAGS, 69 | FWPM_CONDITION_INTERFACE_INDEX, 70 | FWPM_CONDITION_INTERFACE_TYPE, 71 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 72 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 73 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 74 | FWPM_CONDITION_IP_LOCAL_PORT, 75 | FWPM_CONDITION_IP_PROTOCOL, 76 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 77 | FWPM_CONDITION_IP_REMOTE_PORT, 78 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 79 | FWPM_CONDITION_TUNNEL_TYPE, 80 | 81 | // Windows 7 and later: 82 | FWPM_CONDITION_CURRENT_PROFILE_ID 83 | }; 84 | 85 | static const GUID CONDITIONS_OUTBOUND_TRANSPORT[] = 86 | { 87 | FWPM_CONDITION_FLAGS, 88 | FWPM_CONDITION_INTERFACE_INDEX, 89 | FWPM_CONDITION_INTERFACE_TYPE, 90 | FWPM_CONDITION_IP_DESTINATION_ADDRESS_TYPE, 91 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 92 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 93 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 94 | FWPM_CONDITION_IP_LOCAL_PORT, 95 | FWPM_CONDITION_IP_PROTOCOL, 96 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 97 | FWPM_CONDITION_IP_REMOTE_PORT, 98 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 99 | FWPM_CONDITION_TUNNEL_TYPE, 100 | 101 | // Windows 7 and later: 102 | FWPM_CONDITION_CURRENT_PROFILE_ID 103 | }; 104 | 105 | static const GUID CONDITIONS_STREAM[] = 106 | { 107 | FWPM_CONDITION_DIRECTION, 108 | FWPM_CONDITION_FLAGS, 109 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 110 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 111 | FWPM_CONDITION_IP_LOCAL_PORT, 112 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 113 | FWPM_CONDITION_IP_REMOTE_PORT 114 | }; 115 | 116 | static const GUID CONDITIONS_DATAGRAM_DATA[] = 117 | { 118 | FWPM_CONDITION_DIRECTION, 119 | FWPM_CONDITION_FLAGS, 120 | FWPM_CONDITION_INTERFACE_INDEX, 121 | FWPM_CONDITION_INTERFACE_TYPE, 122 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 123 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 124 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 125 | FWPM_CONDITION_IP_LOCAL_PORT, 126 | FWPM_CONDITION_IP_PROTOCOL, 127 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 128 | FWPM_CONDITION_IP_REMOTE_PORT, 129 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 130 | FWPM_CONDITION_TUNNEL_TYPE 131 | }; 132 | 133 | static const GUID CONDITIONS_STREAM_PACKET[] = 134 | { 135 | // Windows 7 and later: 136 | FWPM_CONDITION_DIRECTION, 137 | FWPM_CONDITION_FLAGS, 138 | FWPM_CONDITION_INTERFACE_INDEX, 139 | FWPM_CONDITION_INTERFACE_TYPE, 140 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 141 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 142 | FWPM_CONDITION_IP_LOCAL_PORT, 143 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 144 | FWPM_CONDITION_IP_REMOTE_PORT, 145 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 146 | FWPM_CONDITION_TUNNEL_TYPE 147 | }; 148 | 149 | static const GUID CONDITIONS_INBOUND_ICMP_ERROR[] = 150 | { 151 | FWPM_CONDITION_ARRIVAL_INTERFACE_INDEX, 152 | FWPM_CONDITION_ARRIVAL_INTERFACE_TYPE, 153 | FWPM_CONDITION_ARRIVAL_SUB_INTERFACE_INDEX, 154 | 155 | // Windows Vista / Windows 7: 156 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 157 | FWPM_CONDITION_ARRIVAL_TUNNEL_TYPE, 158 | FWPM_CONDITION_FLAGS, 159 | FWPM_CONDITION_ICMP_CODE, 160 | FWPM_CONDITION_ICMP_TYPE, 161 | FWPM_CONDITION_EMBEDDED_LOCAL_ADDRESS_TYPE, 162 | FWPM_CONDITION_EMBEDDED_LOCAL_PORT, 163 | FWPM_CONDITION_EMBEDDED_PROTOCOL, 164 | FWPM_CONDITION_EMBEDDED_REMOTE_ADDRESS, 165 | FWPM_CONDITION_EMBEDDED_REMOTE_PORT, 166 | FWPM_CONDITION_IP_ARRIVAL_INTERFACE, 167 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 168 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 169 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 170 | FWPM_CONDITION_LOCAL_INTERFACE_INDEX, 171 | 172 | // Windows Vista / Windows 7: 173 | FWPM_CONDITION_INTERFACE_INDEX, 174 | FWPM_CONDITION_LOCAL_INTERFACE_TYPE, 175 | 176 | // Windows Vista / Windows 7: 177 | FWPM_CONDITION_INTERFACE_TYPE, 178 | FWPM_CONDITION_LOCAL_TUNNEL_TYPE, 179 | 180 | // Windows Vista / Windows 7: 181 | FWPM_CONDITION_TUNNEL_TYPE, 182 | 183 | // Windows 7 and later: 184 | FWPM_CONDITION_ARRIVAL_INTERFACE_PROFILE_ID 185 | }; 186 | 187 | static const GUID CONDITIONS_OUTBOUND_ICMP_ERROR[] = 188 | { 189 | FWPM_CONDITION_FLAGS, 190 | FWPM_CONDITION_ICMP_CODE, 191 | FWPM_CONDITION_ICMP_TYPE, 192 | FWPM_CONDITION_INTERFACE_INDEX, 193 | FWPM_CONDITION_INTERFACE_TYPE, 194 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 195 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 196 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 197 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 198 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 199 | FWPM_CONDITION_TUNNEL_TYPE, 200 | 201 | // Windows 7 and later: 202 | FWPM_CONDITION_NEXTHOP_INTERFACE_PROFILE_ID 203 | }; 204 | 205 | static const GUID CONDITIONS_ALE_BIND_REDIRECT[] = 206 | { 207 | // Windows 7 and later: 208 | FWPM_CONDITION_ALE_APP_ID, 209 | FWPM_CONDITION_ALE_USER_ID, 210 | FWPM_CONDITION_FLAGS, 211 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 212 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 213 | FWPM_CONDITION_IP_LOCAL_PORT, 214 | FWPM_CONDITION_IP_PROTOCOL, 215 | 216 | // Windows 8: 217 | //FWPM_CONDITION_ALE_PACKAGE_ID 218 | }; 219 | 220 | static const GUID CONDITIONS_ALE_RESOURCE_ASSIGNMENT[] = 221 | { 222 | FWPM_CONDITION_ALE_APP_ID, 223 | FWPM_CONDITION_ALE_PROMISCUOUS_MODE, 224 | FWPM_CONDITION_ALE_USER_ID, 225 | FWPM_CONDITION_FLAGS, 226 | FWPM_CONDITION_INTERFACE_TYPE, 227 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 228 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 229 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 230 | FWPM_CONDITION_IP_LOCAL_PORT, 231 | FWPM_CONDITION_IP_PROTOCOL, 232 | FWPM_CONDITION_TUNNEL_TYPE, 233 | 234 | // Windows 7 and later: 235 | FWPM_CONDITION_LOCAL_INTERFACE_PROFILE_ID, 236 | FWPM_CONDITION_ALE_SIO_FIREWALL_SYSTEM_PORT, 237 | 238 | // Windows 8 : 239 | //FWPM_CONDITION_ALE_PACKAGE_ID 240 | }; 241 | 242 | static const GUID CONDITIONS_ALE_RESOURCE_RELEASE[] = 243 | { 244 | // Windows 7 and later: 245 | FWPM_CONDITION_ALE_APP_ID, 246 | FWPM_CONDITION_ALE_USER_ID, 247 | FWPM_CONDITION_FLAGS, 248 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 249 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 250 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 251 | FWPM_CONDITION_IP_LOCAL_PORT, 252 | FWPM_CONDITION_IP_PROTOCOL, 253 | 254 | // Windows 8: 255 | //FWPM_CONDITION_ALE_PACKAGE_ID 256 | }; 257 | 258 | static const GUID CONDITIONS_ALE_ENDPOINT_CLOSURE[] = 259 | { 260 | // Windows 7 and later: 261 | FWPM_CONDITION_ALE_APP_ID, 262 | FWPM_CONDITION_ALE_USER_ID, 263 | FWPM_CONDITION_FLAGS, 264 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 265 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 266 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 267 | FWPM_CONDITION_IP_LOCAL_PORT, 268 | FWPM_CONDITION_IP_PROTOCOL, 269 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 270 | FWPM_CONDITION_IP_REMOTE_PORT, 271 | 272 | // Windows 8: 273 | //FWPM_CONDITION_ALE_PACKAGE_ID 274 | }; 275 | 276 | static const GUID CONDITIONS_ALE_AUTH_LISTEN[] = 277 | { 278 | FWPM_CONDITION_ALE_APP_ID, 279 | FWPM_CONDITION_ALE_USER_ID, 280 | FWPM_CONDITION_FLAGS, 281 | FWPM_CONDITION_INTERFACE_TYPE, 282 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 283 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 284 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 285 | FWPM_CONDITION_IP_LOCAL_PORT, 286 | FWPM_CONDITION_TUNNEL_TYPE, 287 | 288 | // Windows 7 and later: 289 | FWPM_CONDITION_LOCAL_INTERFACE_PROFILE_ID, 290 | FWPM_CONDITION_ALE_SIO_FIREWALL_SYSTEM_PORT, 291 | 292 | // Windows 8: 293 | //FWPM_CONDITION_ALE_PACKAGE_ID 294 | }; 295 | 296 | static const GUID CONDITIONS_ALE_AUTH_RECV_ACCEPT[] = 297 | { 298 | FWPM_CONDITION_ALE_APP_ID, 299 | FWPM_CONDITION_ALE_NAP_CONTEXT, 300 | FWPM_CONDITION_ALE_REMOTE_MACHINE_ID, 301 | FWPM_CONDITION_ALE_REMOTE_USER_ID, 302 | FWPM_CONDITION_ALE_SIO_FIREWALL_SYSTEM_PORT, 303 | FWPM_CONDITION_ALE_USER_ID, 304 | FWPM_CONDITION_ARRIVAL_INTERFACE_INDEX, 305 | FWPM_CONDITION_ARRIVAL_INTERFACE_TYPE, 306 | FWPM_CONDITION_ARRIVAL_SUB_INTERFACE_INDEX, 307 | 308 | // Windows Vista / Windows 7: 309 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 310 | FWPM_CONDITION_ARRIVAL_TUNNEL_TYPE, 311 | FWPM_CONDITION_FLAGS, 312 | FWPM_CONDITION_IP_ARRIVAL_INTERFACE, 313 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 314 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 315 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 316 | FWPM_CONDITION_IP_LOCAL_PORT, 317 | FWPM_CONDITION_IP_PROTOCOL, 318 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 319 | FWPM_CONDITION_IP_REMOTE_PORT, 320 | FWPM_CONDITION_LOCAL_INTERFACE_INDEX, 321 | 322 | // Windows Vista / Windows 7: 323 | FWPM_CONDITION_INTERFACE_INDEX, 324 | FWPM_CONDITION_LOCAL_INTERFACE_TYPE, 325 | 326 | // Windows Vista / Windows 7: 327 | FWPM_CONDITION_INTERFACE_TYPE, 328 | FWPM_CONDITION_LOCAL_TUNNEL_TYPE, 329 | 330 | // Windows Vista / Windows 7: 331 | FWPM_CONDITION_TUNNEL_TYPE, 332 | 333 | // Windows 7 and later: 334 | FWPM_CONDITION_NEXTHOP_SUB_INTERFACE_INDEX, 335 | FWPM_CONDITION_IP_NEXTHOP_INTERFACE, 336 | FWPM_CONDITION_NEXTHOP_INTERFACE_TYPE, 337 | FWPM_CONDITION_NEXTHOP_TUNNEL_TYPE, 338 | FWPM_CONDITION_NEXTHOP_INTERFACE_INDEX, 339 | FWPM_CONDITION_ORIGINAL_PROFILE_ID, 340 | FWPM_CONDITION_CURRENT_PROFILE_ID, 341 | FWPM_CONDITION_REAUTHORIZE_REASON, 342 | FWPM_CONDITION_ORIGINAL_ICMP_TYPE, 343 | 344 | // Windows 8: 345 | //FWPM_CONDITION_ALE_PACKAGE_ID 346 | }; 347 | 348 | static const GUID CONDITIONS_ALE_CONNECT_REDIRECT[] = 349 | { 350 | // Windows 7 and later: 351 | FWPM_CONDITION_ALE_APP_ID, 352 | FWPM_CONDITION_ALE_USER_ID, 353 | FWPM_CONDITION_FLAGS, 354 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 355 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 356 | FWPM_CONDITION_IP_LOCAL_PORT, 357 | FWPM_CONDITION_IP_PROTOCOL, 358 | FWPM_CONDITION_IP_REMOTE_PORT, 359 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 360 | FWPM_CONDITION_IP_DESTINATION_ADDRESS_TYPE, 361 | 362 | // Windows 8: 363 | //FWPM_CONDITION_ALE_PACKAGE_ID 364 | }; 365 | 366 | static const GUID CONDITIONS_ALE_AUTH_CONNECT[] = 367 | { 368 | FWPM_CONDITION_ALE_APP_ID, 369 | FWPM_CONDITION_ALE_REMOTE_MACHINE_ID, 370 | FWPM_CONDITION_ALE_REMOTE_USER_ID, 371 | FWPM_CONDITION_ALE_USER_ID, 372 | FWPM_CONDITION_FLAGS, 373 | FWPM_CONDITION_INTERFACE_TYPE, 374 | FWPM_CONDITION_IP_DESTINATION_ADDRESS_TYPE, 375 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 376 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 377 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 378 | FWPM_CONDITION_IP_LOCAL_PORT, 379 | FWPM_CONDITION_IP_PROTOCOL, 380 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 381 | FWPM_CONDITION_IP_REMOTE_PORT, 382 | FWPM_CONDITION_SUB_INTERFACE_INDEX, 383 | FWPM_CONDITION_TUNNEL_TYPE, 384 | FWPM_CONDITION_IP_ARRIVAL_INTERFACE, 385 | FWPM_CONDITION_ARRIVAL_INTERFACE_TYPE, 386 | FWPM_CONDITION_ARRIVAL_TUNNEL_TYPE, 387 | FWPM_CONDITION_ARRIVAL_INTERFACE_INDEX, 388 | 389 | // Windows Vista with SP1 and later: 390 | FWPM_CONDITION_INTERFACE_INDEX, 391 | 392 | // Windows 7 and later: 393 | FWPM_CONDITION_NEXTHOP_SUB_INTERFACE_INDEX, 394 | FWPM_CONDITION_IP_NEXTHOP_INTERFACE, 395 | FWPM_CONDITION_NEXTHOP_INTERFACE_TYPE, 396 | FWPM_CONDITION_NEXTHOP_TUNNEL_TYPE, 397 | FWPM_CONDITION_NEXTHOP_INTERFACE_INDEX, 398 | FWPM_CONDITION_ORIGINAL_PROFILE_ID, 399 | FWPM_CONDITION_CURRENT_PROFILE_ID, 400 | FWPM_CONDITION_REAUTHORIZE_REASON, 401 | FWPM_CONDITION_PEER_NAME, 402 | FWPM_CONDITION_ORIGINAL_ICMP_TYPE, 403 | 404 | // Windows 8: 405 | //FWPM_CONDITION_ALE_PACKAGE_ID 406 | }; 407 | 408 | static const GUID CONDITIONS_ALE_FLOW_ESTABLISHED[] = 409 | { 410 | FWPM_CONDITION_ALE_APP_ID, 411 | FWPM_CONDITION_ALE_REMOTE_MACHINE_ID, 412 | FWPM_CONDITION_ALE_REMOTE_USER_ID, 413 | FWPM_CONDITION_ALE_USER_ID, 414 | FWPM_CONDITION_DIRECTION, 415 | FWPM_CONDITION_FLAGS, 416 | FWPM_CONDITION_INTERFACE_TYPE, 417 | FWPM_CONDITION_IP_DESTINATION_ADDRESS_TYPE, 418 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 419 | FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE, 420 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 421 | FWPM_CONDITION_IP_LOCAL_PORT, 422 | FWPM_CONDITION_IP_PROTOCOL, 423 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 424 | FWPM_CONDITION_IP_REMOTE_PORT, 425 | FWPM_CONDITION_TUNNEL_TYPE, 426 | 427 | // Windows 8: 428 | //FWPM_CONDITION_ALE_PACKAGE_ID 429 | }; 430 | 431 | static const GUID CONDITIONS_NAME_RESOLUTION_CACHE[] = 432 | { 433 | // Windows 7 and later: 434 | FWPM_CONDITION_ALE_USER_ID, 435 | FWPM_CONDITION_ALE_APP_ID, 436 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 437 | FWPM_CONDITION_PEER_NAME 438 | }; 439 | 440 | static const GUID CONDITIONS_IPSEC_KM_DEMUX[] = 441 | { 442 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 443 | FWPM_CONDITION_IP_REMOTE_ADDRESS 444 | }; 445 | 446 | static const GUID CONDITIONS_IPSEC[] = 447 | { 448 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 449 | FWPM_CONDITION_IP_LOCAL_PORT, 450 | FWPM_CONDITION_IP_PROTOCOL, 451 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 452 | FWPM_CONDITION_IP_REMOTE_PORT, 453 | 454 | // Windows 7 and later: 455 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 456 | FWPM_CONDITION_CURRENT_PROFILE_ID 457 | }; 458 | 459 | static const GUID CONDITIONS_IKEEXT[] = 460 | { 461 | FWPM_CONDITION_IP_LOCAL_ADDRESS, 462 | FWPM_CONDITION_IP_REMOTE_ADDRESS, 463 | 464 | // Windows 7 and later: 465 | FWPM_CONDITION_IP_LOCAL_INTERFACE, 466 | FWPM_CONDITION_CURRENT_PROFILE_ID 467 | }; 468 | 469 | static const GUID CONDITIONS_RPC_UM[] = 470 | { 471 | FWPM_CONDITION_DCOM_APP_ID, 472 | FWPM_CONDITION_IMAGE_NAME, 473 | FWPM_CONDITION_IP_LOCAL_ADDRESS_V4, 474 | FWPM_CONDITION_IP_LOCAL_ADDRESS_V6, 475 | FWPM_CONDITION_IP_LOCAL_PORT, 476 | FWPM_CONDITION_IP_REMOTE_ADDRESS_V4, 477 | FWPM_CONDITION_IP_REMOTE_ADDRESS_V6, 478 | FWPM_CONDITION_PIPE, 479 | FWPM_CONDITION_REMOTE_USER_TOKEN, 480 | FWPM_CONDITION_RPC_AUTH_LEVEL, 481 | FWPM_CONDITION_RPC_AUTH_TYPE, 482 | FWPM_CONDITION_RPC_IF_FLAG, 483 | FWPM_CONDITION_RPC_IF_UUID, 484 | FWPM_CONDITION_RPC_IF_VERSION, 485 | FWPM_CONDITION_RPC_PROTOCOL, 486 | FWPM_CONDITION_SEC_ENCRYPT_ALGORITHM, 487 | FWPM_CONDITION_SEC_KEY_SIZE 488 | }; 489 | 490 | static const GUID CONDITIONS_RPC_EPMAP[] = 491 | { 492 | FWPM_CONDITION_IP_LOCAL_ADDRESS_V4, 493 | FWPM_CONDITION_IP_LOCAL_ADDRESS_V6, 494 | FWPM_CONDITION_IP_LOCAL_PORT, 495 | FWPM_CONDITION_IP_REMOTE_ADDRESS_V4, 496 | FWPM_CONDITION_IP_REMOTE_ADDRESS_V6, 497 | FWPM_CONDITION_PIPE, 498 | FWPM_CONDITION_REMOTE_USER_TOKEN, 499 | FWPM_CONDITION_RPC_AUTH_LEVEL, 500 | FWPM_CONDITION_RPC_AUTH_TYPE, 501 | FWPM_CONDITION_RPC_IF_UUID, 502 | FWPM_CONDITION_RPC_IF_VERSION, 503 | FWPM_CONDITION_RPC_PROTOCOL, 504 | FWPM_CONDITION_SEC_ENCRYPT_ALGORITHM, 505 | FWPM_CONDITION_SEC_KEY_SIZE 506 | }; 507 | 508 | static const GUID CONDITIONS_RPC_EP_ADD[] = 509 | { 510 | FWPM_CONDITION_PROCESS_WITH_RPC_IF_UUID, 511 | FWPM_CONDITION_RPC_EP_FLAGS, 512 | FWPM_CONDITION_RPC_EP_VALUE, 513 | FWPM_CONDITION_RPC_PROTOCOL 514 | }; 515 | 516 | static const GUID CONDITIONS_RPC_PROXY_CONN[] = 517 | { 518 | FWPM_CONDITION_CLIENT_CERT_KEY_LENGTH, 519 | FWPM_CONDITION_CLIENT_CERT_OID, 520 | FWPM_CONDITION_CLIENT_TOKEN, 521 | FWPM_CONDITION_RPC_PROXY_AUTH_TYPE, 522 | FWPM_CONDITION_RPC_SERVER_NAME, 523 | FWPM_CONDITION_RPC_SERVER_PORT 524 | }; 525 | 526 | static const GUID CONDITIONS_RPC_PROXY_IF[] = 527 | { 528 | FWPM_CONDITION_CLIENT_CERT_KEY_LENGTH, 529 | FWPM_CONDITION_CLIENT_CERT_OID, 530 | FWPM_CONDITION_CLIENT_TOKEN, 531 | FWPM_CONDITION_RPC_IF_UUID, 532 | FWPM_CONDITION_RPC_IF_VERSION, 533 | FWPM_CONDITION_RPC_PROXY_AUTH_TYPE, 534 | FWPM_CONDITION_RPC_SERVER_NAME, 535 | FWPM_CONDITION_RPC_SERVER_PORT 536 | }; 537 | 538 | static const GUID CONDITIONS_KM_AUTHORIZATION[] = 539 | { 540 | // Windows 7 and later: 541 | FWPM_CONDITION_REMOTE_ID, 542 | FWPM_CONDITION_AUTHENTICATION_TYPE, 543 | FWPM_CONDITION_KM_TYPE, 544 | FWPM_CONDITION_KM_MODE, 545 | FWPM_CONDITION_DIRECTION, 546 | FWPM_CONDITION_IPSEC_POLICY_KEY 547 | }; 548 | 549 | //static const GUID CONDITIONS_MAC_FRAME_ETHERNET[] = 550 | //{ 551 | // // Windows 8: 552 | // FWPM_CONDITION_INTERFACE_MAC_ADDRESS, 553 | // FWPM_CONDITION_MAC_LOCAL_ADDRESS, 554 | // FWPM_CONDITION_MAC_REMOTE_ADDRESS, 555 | // FWPM_CONDITION_MAC_LOCAL_ADDRESS_TYPE, 556 | // FWPM_CONDITION_MAC_REMOTE_ADDRESS_TYPE, 557 | // FWPM_CONDITION_ETHER_TYPE, 558 | // FWPM_CONDITION_VLAN_ID, 559 | // FWPM_CONDITION_INTERFACE, 560 | // FWPM_CONDITION_INTERFACE_INDEX, 561 | // FWPM_CONDITION_NDIS_PORT, 562 | // FWPM_CONDITION_L2_FLAGS 563 | //}; 564 | 565 | //static const GUID CONDITIONS_MAC_FRAME_NATIVE[] = 566 | //{ 567 | // // Windows 8: 568 | // FWPM_CONDITION_NDIS_MEDIA_TYPE, 569 | // FWPM_CONDITION_NDIS_PHYSICAL_MEDIA_TYPE, 570 | // FWPM_CONDITION_INTERFACE, 571 | // FWPM_CONDITION_INTERFACE_TYPE, 572 | // FWPM_CONDITION_INTERFACE_INDEX, 573 | // FWPM_CONDITION_NDIS_PORT, 574 | // FWPM_CONDITION_L2_FLAGS 575 | //}; 576 | 577 | //static const GUID CONDITIONS_VSWITCH_ETHERNET[] = 578 | //{ 579 | // // Windows 8: 580 | // FWPM_CONDITION_MAC_SOURCE_ADDRESS, 581 | // FWPM_CONDITION_MAC_SOURCE_ADDRESS_TYPE, 582 | // FWPM_CONDITION_MAC_DESTINATION_ADDRESS, 583 | // FWPM_CONDITION_MAC_DESTINATION_ADDRESS_TYPE, 584 | // FWPM_CONDITION_ETHER_TYPE, 585 | // FWPM_CONDITION_VLAN_ID, 586 | // FWPM_CONDITION_VSWITCH_TENANT_NETWORK_ID, 587 | // FWPM_CONDITION_VSWITCH_ID, 588 | // FWPM_CONDITION_VSWITCH_NETWORK_TYPE, 589 | // FWPM_CONDITION_VSWITCH_SOURCE_INTERFACE_ID, 590 | // FWPM_CONDITION_VSWITCH_SOURCE_INTERFACE_TYPE, 591 | // FWPM_CONDITION_VSWITCH_SOURCE_VM_ID, 592 | // FWPM_CONDITION_VSWITCH_L2_FLAGS 593 | //}; 594 | // 595 | //static const GUID CONDITIONS_VSWITCH_TRANSPORT[] = 596 | //{ 597 | // // Windows 8: 598 | // FWPM_CONDITION_IP_SOURCE_ADDRESS, 599 | // FWPM_CONDITION_IP_DESTINATION_ADDRESS, 600 | // FWPM_CONDITION_IP_PROTOCOL, 601 | // FWPM_CONDITION_IP_SOURCE_PORT, 602 | // FWPM_CONDITION_IP_DESTINATION_PORT, 603 | // FWPM_CONDITION_VLAN_ID, 604 | // FWPM_CONDITION_VSWITCH_TENANT_NETWORK_ID, 605 | // FWPM_CONDITION_VSWITCH_ID, 606 | // FWPM_CONDITION_VSWITCH_NETWORK_TYPE, 607 | // FWPM_CONDITION_VSWITCH_SOURCE_INTERFACE_ID, 608 | // FWPM_CONDITION_VSWITCH_SOURCE_INTERFACE_TYPE, 609 | // FWPM_CONDITION_VSWITCH_SOURCE_VM_ID, 610 | // FWPM_CONDITION_VSWITCH_DESTINATION_INTERFACE_ID, 611 | // FWPM_CONDITION_VSWITCH_DESTINATION_INTERFACE_TYPE, 612 | // FWPM_CONDITION_VSWITCH_L2_FLAGS 613 | //}; 614 | 615 | struct ConditionsCollection 616 | { 617 | const GUID *conditions; 618 | size_t numConditions; 619 | }; 620 | 621 | #define MAKE_CONDITIONS_COLLECTION(x) ConditionsCollection { x, _countof(x) } 622 | 623 | struct GuidLess 624 | { 625 | bool operator()(const GUID a, const GUID b) const 626 | { 627 | return memcmp(&a, &b, sizeof(GUID)) < 0; 628 | } 629 | }; 630 | 631 | typedef std::map ConditionMap; 632 | 633 | ConditionMap g_lookup; 634 | std::mutex g_lookupMutex; 635 | 636 | void InitializeConditionMap(ConditionMap &lookup) 637 | { 638 | ConditionMap temp 639 | { 640 | std::make_pair(FWPM_LAYER_INBOUND_IPPACKET_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_IP_PACKET)), 641 | std::make_pair(FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_IP_PACKET)), 642 | std::make_pair(FWPM_LAYER_INBOUND_IPPACKET_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_IP_PACKET)), 643 | std::make_pair(FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_IP_PACKET)), 644 | 645 | std::make_pair(FWPM_LAYER_OUTBOUND_IPPACKET_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_IP_PACKET)), 646 | std::make_pair(FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_IP_PACKET)), 647 | std::make_pair(FWPM_LAYER_OUTBOUND_IPPACKET_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_IP_PACKET)), 648 | std::make_pair(FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_IP_PACKET)), 649 | 650 | std::make_pair(FWPM_LAYER_IPFORWARD_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPFORWARD)), 651 | std::make_pair(FWPM_LAYER_IPFORWARD_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPFORWARD)), 652 | std::make_pair(FWPM_LAYER_IPFORWARD_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPFORWARD)), 653 | std::make_pair(FWPM_LAYER_IPFORWARD_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPFORWARD)), 654 | 655 | std::make_pair(FWPM_LAYER_INBOUND_TRANSPORT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_TRANSPORT)), 656 | std::make_pair(FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_TRANSPORT)), 657 | std::make_pair(FWPM_LAYER_INBOUND_TRANSPORT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_TRANSPORT)), 658 | std::make_pair(FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_TRANSPORT)), 659 | 660 | std::make_pair(FWPM_LAYER_OUTBOUND_TRANSPORT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_TRANSPORT)), 661 | std::make_pair(FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_TRANSPORT)), 662 | std::make_pair(FWPM_LAYER_OUTBOUND_TRANSPORT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_TRANSPORT)), 663 | std::make_pair(FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_TRANSPORT)), 664 | 665 | std::make_pair(FWPM_LAYER_STREAM_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM)), 666 | std::make_pair(FWPM_LAYER_STREAM_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM)), 667 | std::make_pair(FWPM_LAYER_STREAM_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM)), 668 | std::make_pair(FWPM_LAYER_STREAM_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM)), 669 | 670 | std::make_pair(FWPM_LAYER_DATAGRAM_DATA_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_DATAGRAM_DATA)), 671 | std::make_pair(FWPM_LAYER_DATAGRAM_DATA_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_DATAGRAM_DATA)), 672 | std::make_pair(FWPM_LAYER_DATAGRAM_DATA_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_DATAGRAM_DATA)), 673 | std::make_pair(FWPM_LAYER_DATAGRAM_DATA_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_DATAGRAM_DATA)), 674 | 675 | std::make_pair(FWPM_LAYER_STREAM_PACKET_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM_PACKET)), 676 | std::make_pair(FWPM_LAYER_STREAM_PACKET_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_STREAM_PACKET)), 677 | 678 | std::make_pair(FWPM_LAYER_INBOUND_ICMP_ERROR_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_ICMP_ERROR)), 679 | std::make_pair(FWPM_LAYER_INBOUND_ICMP_ERROR_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_ICMP_ERROR)), 680 | std::make_pair(FWPM_LAYER_INBOUND_ICMP_ERROR_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_ICMP_ERROR)), 681 | std::make_pair(FWPM_LAYER_INBOUND_ICMP_ERROR_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_INBOUND_ICMP_ERROR)), 682 | 683 | std::make_pair(FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_ICMP_ERROR)), 684 | std::make_pair(FWPM_LAYER_OUTBOUND_ICMP_ERROR_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_ICMP_ERROR)), 685 | std::make_pair(FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_ICMP_ERROR)), 686 | std::make_pair(FWPM_LAYER_OUTBOUND_ICMP_ERROR_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_OUTBOUND_ICMP_ERROR)), 687 | 688 | std::make_pair(FWPM_LAYER_ALE_BIND_REDIRECT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_BIND_REDIRECT)), 689 | std::make_pair(FWPM_LAYER_ALE_BIND_REDIRECT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_BIND_REDIRECT)), 690 | 691 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_ASSIGNMENT)), 692 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_ASSIGNMENT)), 693 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_ASSIGNMENT)), 694 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_ASSIGNMENT)), 695 | 696 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_RELEASE_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_RELEASE)), 697 | std::make_pair(FWPM_LAYER_ALE_RESOURCE_RELEASE_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_RESOURCE_RELEASE)), 698 | 699 | std::make_pair(FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_ENDPOINT_CLOSURE)), 700 | std::make_pair(FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_ENDPOINT_CLOSURE)), 701 | 702 | std::make_pair(FWPM_LAYER_ALE_AUTH_LISTEN_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_LISTEN)), 703 | std::make_pair(FWPM_LAYER_ALE_AUTH_LISTEN_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_LISTEN)), 704 | std::make_pair(FWPM_LAYER_ALE_AUTH_LISTEN_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_LISTEN)), 705 | std::make_pair(FWPM_LAYER_ALE_AUTH_LISTEN_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_LISTEN)), 706 | 707 | std::make_pair(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_RECV_ACCEPT)), 708 | std::make_pair(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_RECV_ACCEPT)), 709 | std::make_pair(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_RECV_ACCEPT)), 710 | std::make_pair(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_RECV_ACCEPT)), 711 | 712 | std::make_pair(FWPM_LAYER_ALE_CONNECT_REDIRECT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_CONNECT_REDIRECT)), 713 | std::make_pair(FWPM_LAYER_ALE_CONNECT_REDIRECT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_CONNECT_REDIRECT)), 714 | 715 | std::make_pair(FWPM_LAYER_ALE_AUTH_CONNECT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_CONNECT)), 716 | std::make_pair(FWPM_LAYER_ALE_AUTH_CONNECT_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_CONNECT)), 717 | std::make_pair(FWPM_LAYER_ALE_AUTH_CONNECT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_CONNECT)), 718 | std::make_pair(FWPM_LAYER_ALE_AUTH_CONNECT_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_AUTH_CONNECT)), 719 | 720 | std::make_pair(FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_FLOW_ESTABLISHED)), 721 | std::make_pair(FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_FLOW_ESTABLISHED)), 722 | std::make_pair(FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_FLOW_ESTABLISHED)), 723 | std::make_pair(FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6_DISCARD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_ALE_FLOW_ESTABLISHED)), 724 | 725 | std::make_pair(FWPM_LAYER_NAME_RESOLUTION_CACHE_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_NAME_RESOLUTION_CACHE)), 726 | std::make_pair(FWPM_LAYER_NAME_RESOLUTION_CACHE_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_NAME_RESOLUTION_CACHE)), 727 | 728 | std::make_pair(FWPM_LAYER_IPSEC_KM_DEMUX_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPSEC_KM_DEMUX)), 729 | std::make_pair(FWPM_LAYER_IPSEC_KM_DEMUX_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPSEC_KM_DEMUX)), 730 | 731 | std::make_pair(FWPM_LAYER_IPSEC_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPSEC)), 732 | std::make_pair(FWPM_LAYER_IPSEC_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IPSEC)), 733 | 734 | std::make_pair(FWPM_LAYER_IKEEXT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IKEEXT)), 735 | std::make_pair(FWPM_LAYER_IKEEXT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_IKEEXT)), 736 | 737 | // Single-occurrence layers 738 | std::make_pair(FWPM_LAYER_RPC_UM, MAKE_CONDITIONS_COLLECTION(CONDITIONS_RPC_UM)), 739 | std::make_pair(FWPM_LAYER_RPC_EPMAP, MAKE_CONDITIONS_COLLECTION(CONDITIONS_RPC_EPMAP)), 740 | std::make_pair(FWPM_LAYER_RPC_EP_ADD, MAKE_CONDITIONS_COLLECTION(CONDITIONS_RPC_EP_ADD)), 741 | std::make_pair(FWPM_LAYER_RPC_PROXY_CONN, MAKE_CONDITIONS_COLLECTION(CONDITIONS_RPC_PROXY_CONN)), 742 | std::make_pair(FWPM_LAYER_RPC_PROXY_IF, MAKE_CONDITIONS_COLLECTION(CONDITIONS_RPC_PROXY_IF)), 743 | std::make_pair(FWPM_LAYER_KM_AUTHORIZATION, MAKE_CONDITIONS_COLLECTION(CONDITIONS_KM_AUTHORIZATION)), 744 | 745 | //std::make_pair(FWPM_LAYER_INBOUND_MAC_FRAME_ETHERNET, MAKE_CONDITIONS_COLLECTION(CONDITIONS_MAC_FRAME_ETHERNET)), 746 | //std::make_pair(FWPM_LAYER_OUTBOUND_MAC_FRAME_ETHERNET, MAKE_CONDITIONS_COLLECTION(CONDITIONS_MAC_FRAME_ETHERNET)), 747 | 748 | //std::make_pair(FWPM_LAYER_INBOUND_MAC_FRAME_NATIVE, MAKE_CONDITIONS_COLLECTION(CONDITIONS_MAC_FRAME_NATIVE)), 749 | //std::make_pair(FWPM_LAYER_OUTBOUND_MAC_FRAME_NATIVE, MAKE_CONDITIONS_COLLECTION(CONDITIONS_MAC_FRAME_NATIVE)), 750 | 751 | //std::make_pair(FWPM_LAYER_EGRESS_VSWITCH_ETHERNET, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_ETHERNET)), 752 | //std::make_pair(FWPM_LAYER_INGRESS_VSWITCH_ETHERNET, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_ETHERNET)), 753 | 754 | //std::make_pair(FWPM_LAYER_EGRESS_VSWITCH_TRANSPORT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_TRANSPORT)), 755 | //std::make_pair(FWPM_LAYER_INGRESS_VSWITCH_TRANSPORT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_TRANSPORT)), 756 | //std::make_pair(FWPM_LAYER_EGRESS_VSWITCH_TRANSPORT_V6, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_TRANSPORT)), 757 | //std::make_pair(FWPM_LAYER_INGRESS_VSWITCH_TRANSPORT_V4, MAKE_CONDITIONS_COLLECTION(CONDITIONS_VSWITCH_TRANSPORT)), 758 | }; 759 | 760 | lookup = temp; 761 | } 762 | 763 | bool ExecuteConditionMap(std::function callback) 764 | { 765 | std::lock_guard lock(g_lookupMutex); 766 | 767 | if (g_lookup.empty()) 768 | { 769 | InitializeConditionMap(g_lookup); 770 | } 771 | 772 | return callback(g_lookup); 773 | } 774 | 775 | ConditionsCollection GetLayerConditions(const GUID &layer) 776 | { 777 | ConditionsCollection result; 778 | 779 | ExecuteConditionMap([&result, layer](const ConditionMap &lookup) 780 | { 781 | auto match = lookup.find(layer); 782 | 783 | if (lookup.end() == match) 784 | { 785 | const auto msg = std::wstring(L"Invalid layer GUID: ").append(common::string::FormatGuid(layer)); 786 | THROW_ERROR(common::string::ToAnsi(msg).c_str()); 787 | } 788 | 789 | result = match->second; 790 | return true; 791 | }); 792 | 793 | return result; 794 | } 795 | 796 | } // anon namespace 797 | 798 | //static 799 | bool LayerConditions::IsCompatible(const GUID &layer, const GUID &condition) 800 | { 801 | auto layerConditions = GetLayerConditions(layer); 802 | 803 | for (size_t i = 0; i < layerConditions.numConditions; ++i) 804 | { 805 | if (0 == memcmp(&condition, &layerConditions.conditions[i], sizeof(GUID))) 806 | { 807 | return true; 808 | } 809 | } 810 | 811 | return false; 812 | } 813 | 814 | } 815 | -------------------------------------------------------------------------------- /src/libwfp/layerconditions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | struct LayerConditions 9 | { 10 | static bool IsCompatible(const GUID &layer, const GUID &condition); 11 | }; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/libwfp/libwfp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Create 54 | Create 55 | Create 56 | Create 57 | Create 58 | Create 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 16.0 100 | {2164E6D9-6023-4932-A08F-7A5C15E2CA0B} 101 | Win32Proj 102 | libwfp 103 | 10.0 104 | 105 | 106 | 107 | StaticLibrary 108 | true 109 | v143 110 | Unicode 111 | 112 | 113 | StaticLibrary 114 | false 115 | v143 116 | true 117 | Unicode 118 | 119 | 120 | StaticLibrary 121 | true 122 | v143 123 | Unicode 124 | 125 | 126 | StaticLibrary 127 | true 128 | v143 129 | Unicode 130 | 131 | 132 | StaticLibrary 133 | false 134 | v143 135 | true 136 | Unicode 137 | 138 | 139 | StaticLibrary 140 | false 141 | v143 142 | true 143 | Unicode 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | true 171 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 172 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 173 | 174 | 175 | true 176 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 177 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 178 | 179 | 180 | true 181 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 182 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 183 | 184 | 185 | false 186 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 187 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 188 | 189 | 190 | false 191 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 192 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 193 | 194 | 195 | false 196 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 197 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 198 | 199 | 200 | 201 | Use 202 | Level4 203 | Disabled 204 | true 205 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 206 | MultiThreadedDebug 207 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 208 | stdcpp20 209 | 210 | 211 | Windows 212 | true 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | Use 222 | Level4 223 | Disabled 224 | true 225 | _DEBUG;_LIB;%(PreprocessorDefinitions) 226 | MultiThreadedDebug 227 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 228 | stdcpp20 229 | 230 | 231 | Windows 232 | true 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | Use 242 | Level4 243 | Disabled 244 | true 245 | _DEBUG;_LIB;%(PreprocessorDefinitions) 246 | MultiThreadedDebug 247 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 248 | stdcpp20 249 | 250 | 251 | Windows 252 | true 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | Use 262 | Level4 263 | MaxSpeed 264 | true 265 | true 266 | true 267 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 268 | MultiThreaded 269 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 270 | stdcpp20 271 | Guard 272 | 273 | 274 | Windows 275 | true 276 | true 277 | true 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | Use 287 | Level4 288 | MaxSpeed 289 | true 290 | true 291 | true 292 | NDEBUG;_LIB;%(PreprocessorDefinitions) 293 | MultiThreaded 294 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 295 | stdcpp20 296 | Guard 297 | 298 | 299 | Windows 300 | true 301 | true 302 | true 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | Use 312 | Level4 313 | MaxSpeed 314 | true 315 | true 316 | true 317 | NDEBUG;_LIB;%(PreprocessorDefinitions) 318 | MultiThreaded 319 | $(ProjectDir)..\;$(ProjectDir)..\..\..\windows-libraries\src\ 320 | stdcpp20 321 | Guard 322 | 323 | 324 | Windows 325 | true 326 | true 327 | true 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /src/libwfp/libwfp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {ad7718b2-1e11-482d-b604-612f7a31f7dc} 6 | 7 | 8 | {11b46d71-26c0-45bf-b963-d28c86b9e6eb} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | internal 22 | 23 | 24 | conditions 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | conditions 33 | 34 | 35 | conditions 36 | 37 | 38 | conditions 39 | 40 | 41 | conditions 42 | 43 | 44 | 45 | conditions 46 | 47 | 48 | conditions 49 | 50 | 51 | conditions 52 | 53 | 54 | 55 | conditions 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | internal 70 | 71 | 72 | conditions 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | conditions 81 | 82 | 83 | conditions 84 | 85 | 86 | conditions 87 | 88 | 89 | conditions 90 | 91 | 92 | conditions 93 | 94 | 95 | conditions 96 | 97 | 98 | conditions 99 | 100 | 101 | 102 | 103 | 104 | conditions 105 | 106 | 107 | conditions 108 | 109 | 110 | conditions 111 | 112 | 113 | 114 | 115 | conditions 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/libwfp/nullconditionbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iconditionbuilder.h" 4 | 5 | namespace wfp 6 | { 7 | 8 | struct NullConditionBuilder : public IConditionBuilder 9 | { 10 | bool build(ConditionSink sink) const override 11 | { 12 | return sink(nullptr, 0); 13 | } 14 | }; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/libwfp/objectdeleter.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "objectdeleter.h" 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | //static 9 | void ObjectDeleter::DeleteFilter(FilterEngine &engine, const GUID &key) 10 | { 11 | auto status = FwpmFilterDeleteByKey0( 12 | engine.session(), 13 | &key 14 | ); 15 | 16 | if (ERROR_SUCCESS == status || FWP_E_FILTER_NOT_FOUND == status) 17 | { 18 | return; 19 | } 20 | 21 | THROW_WINDOWS_ERROR(status, "Delete filter") 22 | } 23 | 24 | //static 25 | void ObjectDeleter::DeleteFilter(FilterEngine &engine, UINT64 key) 26 | { 27 | auto status = FwpmFilterDeleteById0( 28 | engine.session(), 29 | key 30 | ); 31 | 32 | if (ERROR_SUCCESS == status || FWP_E_FILTER_NOT_FOUND == status) 33 | { 34 | return; 35 | } 36 | 37 | THROW_WINDOWS_ERROR(status, "Delete filter"); 38 | } 39 | 40 | //static 41 | void ObjectDeleter::DeleteProvider(FilterEngine &engine, const GUID &key) 42 | { 43 | auto status = FwpmProviderDeleteByKey0( 44 | engine.session(), 45 | &key 46 | ); 47 | 48 | if (ERROR_SUCCESS == status || FWP_E_PROVIDER_NOT_FOUND == status) 49 | { 50 | return; 51 | } 52 | 53 | THROW_WINDOWS_ERROR(status, "Delete provider"); 54 | } 55 | 56 | //static 57 | void ObjectDeleter::DeleteSublayer(FilterEngine &engine, const GUID &key) 58 | { 59 | auto status = FwpmSubLayerDeleteByKey0( 60 | engine.session(), 61 | &key 62 | ); 63 | 64 | if (ERROR_SUCCESS == status || FWP_E_SUBLAYER_NOT_FOUND == status) 65 | { 66 | return; 67 | } 68 | 69 | THROW_WINDOWS_ERROR(status, "Delete sublayer"); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/libwfp/objectdeleter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "filterengine.h" 4 | #include 5 | #include 6 | 7 | namespace wfp 8 | { 9 | 10 | class ObjectDeleter 11 | { 12 | public: 13 | 14 | static void DeleteFilter(FilterEngine &engine, const GUID &key); 15 | static void DeleteFilter(FilterEngine &engine, UINT64 key); 16 | static void DeleteProvider(FilterEngine &engine, const GUID &key); 17 | static void DeleteSublayer(FilterEngine &engine, const GUID &key); 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/libwfp/objectenumerator.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "objectenumerator.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wfp 9 | { 10 | 11 | //static 12 | bool ObjectEnumerator::Sessions( 13 | FilterEngine &engine, 14 | std::function callback) 15 | { 16 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 17 | 18 | auto status = FwpmSessionCreateEnumHandle0( 19 | engine.session(), 20 | nullptr, 21 | &enumHandle 22 | ); 23 | 24 | if (ERROR_SUCCESS != status) 25 | { 26 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP sessions"); 27 | } 28 | 29 | ::common::memory::ScopeDestructor scopeDestructor; 30 | 31 | scopeDestructor += [&engine, &enumHandle]() 32 | { 33 | FwpmSessionDestroyEnumHandle0(engine.session(), enumHandle); 34 | }; 35 | 36 | FWPM_SESSION0** sessions = nullptr; 37 | UINT32 sessionsReturned = 0; 38 | 39 | static const UINT32 SESSIONS_REQUESTED = 100; 40 | 41 | do 42 | { 43 | status = FwpmSessionEnum0( 44 | engine.session(), 45 | enumHandle, 46 | SESSIONS_REQUESTED, 47 | &sessions, 48 | &sessionsReturned 49 | ); 50 | 51 | if (ERROR_SUCCESS != status) 52 | { 53 | THROW_WINDOWS_ERROR(status, "Enumerate WFP sessions"); 54 | } 55 | 56 | if (0 == sessionsReturned) 57 | { 58 | break; 59 | } 60 | 61 | #pragma warning(suppress: 4456) 62 | common::memory::ScopeDestructor scopeDestructor; 63 | 64 | scopeDestructor += [&sessions]() 65 | { 66 | FwpmFreeMemory0((void**)&sessions); 67 | }; 68 | 69 | for (UINT32 i = 0; i < sessionsReturned; ++i) 70 | { 71 | if (false == callback(*sessions[i])) 72 | { 73 | return false; 74 | } 75 | } 76 | } while (SESSIONS_REQUESTED == sessionsReturned); 77 | 78 | return true; 79 | } 80 | 81 | //static 82 | bool ObjectEnumerator::Providers( 83 | FilterEngine &engine, 84 | std::function callback) 85 | { 86 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 87 | 88 | auto status = FwpmProviderCreateEnumHandle0( 89 | engine.session(), 90 | nullptr, 91 | &enumHandle 92 | ); 93 | 94 | if (ERROR_SUCCESS != status) 95 | { 96 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP providers"); 97 | } 98 | 99 | common::memory::ScopeDestructor scopeDestructor; 100 | 101 | scopeDestructor += [&engine, &enumHandle]() 102 | { 103 | FwpmProviderDestroyEnumHandle0(engine.session(), enumHandle); 104 | }; 105 | 106 | FWPM_PROVIDER0** providers = nullptr; 107 | UINT32 providersReturned = 0; 108 | 109 | static const UINT32 PROVIDERS_REQUESTED = 100; 110 | 111 | do 112 | { 113 | status = FwpmProviderEnum0( 114 | engine.session(), 115 | enumHandle, 116 | PROVIDERS_REQUESTED, 117 | &providers, 118 | &providersReturned 119 | ); 120 | 121 | if (ERROR_SUCCESS != status) 122 | { 123 | THROW_WINDOWS_ERROR(status, "Enumerate WFP providers"); 124 | } 125 | 126 | if (0 == providersReturned) 127 | { 128 | break; 129 | } 130 | 131 | #pragma warning(suppress: 4456) 132 | common::memory::ScopeDestructor scopeDestructor; 133 | 134 | scopeDestructor += [&providers]() 135 | { 136 | FwpmFreeMemory0((void**)&providers); 137 | }; 138 | 139 | for (UINT32 i = 0; i < providersReturned; ++i) 140 | { 141 | if (false == callback(*providers[i])) 142 | { 143 | return false; 144 | } 145 | } 146 | } while (PROVIDERS_REQUESTED == providersReturned); 147 | 148 | return true; 149 | } 150 | 151 | //static 152 | bool ObjectEnumerator::Events( 153 | FilterEngine &engine, 154 | std::function callback) 155 | { 156 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 157 | 158 | auto status = FwpmNetEventCreateEnumHandle0( 159 | engine.session(), 160 | nullptr, 161 | &enumHandle 162 | ); 163 | 164 | if (ERROR_SUCCESS != status) 165 | { 166 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP events"); 167 | } 168 | 169 | common::memory::ScopeDestructor scopeDestructor; 170 | 171 | scopeDestructor += [&engine, &enumHandle]() 172 | { 173 | FwpmNetEventDestroyEnumHandle0(engine.session(), enumHandle); 174 | }; 175 | 176 | FWPM_NET_EVENT0** events = nullptr; 177 | UINT32 eventsReturned = 0; 178 | 179 | static const UINT32 EVENTS_REQUESTED = 100; 180 | 181 | do 182 | { 183 | status = FwpmNetEventEnum0( 184 | engine.session(), 185 | enumHandle, 186 | EVENTS_REQUESTED, 187 | &events, 188 | &eventsReturned 189 | ); 190 | 191 | if (ERROR_SUCCESS != status) 192 | { 193 | THROW_WINDOWS_ERROR(status, "Enumerate WFP events"); 194 | } 195 | 196 | if (0 == eventsReturned) 197 | { 198 | break; 199 | } 200 | 201 | #pragma warning(suppress: 4456) 202 | common::memory::ScopeDestructor scopeDestructor; 203 | 204 | scopeDestructor += [&events]() 205 | { 206 | FwpmFreeMemory0((void**)&events); 207 | }; 208 | 209 | for (UINT32 i = 0; i < eventsReturned; ++i) 210 | { 211 | if (false == callback(*events[i])) 212 | { 213 | return false; 214 | } 215 | } 216 | } while (EVENTS_REQUESTED == eventsReturned); 217 | 218 | return true; 219 | } 220 | 221 | //static 222 | bool ObjectEnumerator::Filters( 223 | FilterEngine &engine, 224 | std::function callback) 225 | { 226 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 227 | 228 | auto status = FwpmFilterCreateEnumHandle0( 229 | engine.session(), 230 | nullptr, 231 | &enumHandle 232 | ); 233 | 234 | if (ERROR_SUCCESS != status) 235 | { 236 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP filters"); 237 | } 238 | 239 | common::memory::ScopeDestructor scopeDestructor; 240 | 241 | scopeDestructor += [&engine, &enumHandle]() 242 | { 243 | FwpmFilterDestroyEnumHandle0(engine.session(), enumHandle); 244 | }; 245 | 246 | FWPM_FILTER0** filters = nullptr; 247 | UINT32 filtersReturned = 0; 248 | 249 | static const UINT32 FILTERS_REQUESTED = 100; 250 | 251 | do 252 | { 253 | status = FwpmFilterEnum0( 254 | engine.session(), 255 | enumHandle, 256 | FILTERS_REQUESTED, 257 | &filters, 258 | &filtersReturned 259 | ); 260 | 261 | if (ERROR_SUCCESS != status) 262 | { 263 | THROW_WINDOWS_ERROR(status, "Enumerate WFP filters"); 264 | } 265 | 266 | if (0 == filtersReturned) 267 | { 268 | break; 269 | } 270 | 271 | #pragma warning(suppress: 4456) 272 | common::memory::ScopeDestructor scopeDestructor; 273 | 274 | scopeDestructor += [&filters]() 275 | { 276 | FwpmFreeMemory0((void**)&filters); 277 | }; 278 | 279 | for (UINT32 i = 0; i < filtersReturned; ++i) 280 | { 281 | if (false == callback(*filters[i])) 282 | { 283 | return false; 284 | } 285 | } 286 | } while (FILTERS_REQUESTED == filtersReturned); 287 | 288 | return true; 289 | } 290 | 291 | //static 292 | bool ObjectEnumerator::Layers( 293 | FilterEngine &engine, 294 | std::function callback) 295 | { 296 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 297 | 298 | auto status = FwpmLayerCreateEnumHandle0( 299 | engine.session(), 300 | nullptr, 301 | &enumHandle 302 | ); 303 | 304 | if (ERROR_SUCCESS != status) 305 | { 306 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP layers"); 307 | } 308 | 309 | common::memory::ScopeDestructor scopeDestructor; 310 | 311 | scopeDestructor += [&engine, &enumHandle]() 312 | { 313 | FwpmLayerDestroyEnumHandle0(engine.session(), enumHandle); 314 | }; 315 | 316 | FWPM_LAYER0** layers = nullptr; 317 | UINT32 layersReturned = 0; 318 | 319 | static const UINT32 LAYERS_REQUESTED = 100; 320 | 321 | do 322 | { 323 | status = FwpmLayerEnum0( 324 | engine.session(), 325 | enumHandle, 326 | LAYERS_REQUESTED, 327 | &layers, 328 | &layersReturned 329 | ); 330 | 331 | if (ERROR_SUCCESS != status) 332 | { 333 | THROW_WINDOWS_ERROR(status, "Enumerate WFP layers"); 334 | } 335 | 336 | if (0 == layersReturned) 337 | { 338 | break; 339 | } 340 | 341 | #pragma warning(suppress: 4456) 342 | common::memory::ScopeDestructor scopeDestructor; 343 | 344 | scopeDestructor += [&layers]() 345 | { 346 | FwpmFreeMemory0((void**)&layers); 347 | }; 348 | 349 | for (UINT32 i = 0; i < layersReturned; ++i) 350 | { 351 | if (false == callback(*layers[i])) 352 | { 353 | return false; 354 | } 355 | } 356 | } while (LAYERS_REQUESTED == layersReturned); 357 | 358 | return true; 359 | } 360 | 361 | //static 362 | bool ObjectEnumerator::ProviderContexts( 363 | FilterEngine &engine, 364 | std::function callback) 365 | { 366 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 367 | 368 | auto status = FwpmProviderContextCreateEnumHandle0( 369 | engine.session(), 370 | nullptr, 371 | &enumHandle 372 | ); 373 | 374 | if (ERROR_SUCCESS != status) 375 | { 376 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP provider contexts"); 377 | } 378 | 379 | common::memory::ScopeDestructor scopeDestructor; 380 | 381 | scopeDestructor += [&engine, &enumHandle]() 382 | { 383 | FwpmProviderContextDestroyEnumHandle0(engine.session(), enumHandle); 384 | }; 385 | 386 | FWPM_PROVIDER_CONTEXT0** contexts = nullptr; 387 | UINT32 contextsReturned = 0; 388 | 389 | static const UINT32 CONTEXTS_REQUESTED = 100; 390 | 391 | do 392 | { 393 | status = FwpmProviderContextEnum0( 394 | engine.session(), 395 | enumHandle, 396 | CONTEXTS_REQUESTED, 397 | &contexts, 398 | &contextsReturned 399 | ); 400 | 401 | if (ERROR_SUCCESS != status) 402 | { 403 | THROW_WINDOWS_ERROR(status, "Enumerate WFP provider contexts"); 404 | } 405 | 406 | if (0 == contextsReturned) 407 | { 408 | break; 409 | } 410 | 411 | #pragma warning(suppress: 4456) 412 | common::memory::ScopeDestructor scopeDestructor; 413 | 414 | scopeDestructor += [&contexts]() 415 | { 416 | FwpmFreeMemory0((void**)&contexts); 417 | }; 418 | 419 | for (UINT32 i = 0; i < contextsReturned; ++i) 420 | { 421 | if (false == callback(*contexts[i])) 422 | { 423 | return false; 424 | } 425 | } 426 | } while (CONTEXTS_REQUESTED == contextsReturned); 427 | 428 | return true; 429 | } 430 | 431 | //static 432 | bool ObjectEnumerator::Sublayers( 433 | FilterEngine &engine, 434 | std::function callback) 435 | { 436 | HANDLE enumHandle = INVALID_HANDLE_VALUE; 437 | 438 | auto status = FwpmSubLayerCreateEnumHandle0( 439 | engine.session(), 440 | nullptr, 441 | &enumHandle 442 | ); 443 | 444 | if (ERROR_SUCCESS != status) 445 | { 446 | THROW_WINDOWS_ERROR(status, "Create enumeration context for WFP sublayers"); 447 | } 448 | 449 | common::memory::ScopeDestructor scopeDestructor; 450 | 451 | scopeDestructor += [&engine, &enumHandle]() 452 | { 453 | FwpmSubLayerDestroyEnumHandle0(engine.session(), enumHandle); 454 | }; 455 | 456 | FWPM_SUBLAYER0** sublayers = nullptr; 457 | UINT32 sublayersReturned = 0; 458 | 459 | static const UINT32 SUBLAYERS_REQUESTED = 100; 460 | 461 | do 462 | { 463 | status = FwpmSubLayerEnum0( 464 | engine.session(), 465 | enumHandle, 466 | SUBLAYERS_REQUESTED, 467 | &sublayers, 468 | &sublayersReturned 469 | ); 470 | 471 | if (ERROR_SUCCESS != status) 472 | { 473 | THROW_WINDOWS_ERROR(status, "Enumerate WFP sublayers"); 474 | } 475 | 476 | if (0 == sublayersReturned) 477 | { 478 | break; 479 | } 480 | 481 | #pragma warning(suppress: 4456) 482 | common::memory::ScopeDestructor scopeDestructor; 483 | 484 | scopeDestructor += [&sublayers]() 485 | { 486 | FwpmFreeMemory0((void**)&sublayers); 487 | }; 488 | 489 | for (UINT32 i = 0; i < sublayersReturned; ++i) 490 | { 491 | if (false == callback(*sublayers[i])) 492 | { 493 | return false; 494 | } 495 | } 496 | } while (SUBLAYERS_REQUESTED == sublayersReturned); 497 | 498 | return true; 499 | } 500 | 501 | } // namespace wfp 502 | -------------------------------------------------------------------------------- /src/libwfp/objectenumerator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "filterengine.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace wfp 10 | { 11 | 12 | class ObjectEnumerator 13 | { 14 | ObjectEnumerator(); 15 | 16 | public: 17 | 18 | static bool Sessions(FilterEngine &engine, std::function callback); 19 | static bool Providers(FilterEngine &engine, std::function callback); 20 | static bool Events(FilterEngine &engine, std::function callback); 21 | static bool Filters(FilterEngine &engine, std::function callback); 22 | static bool Layers(FilterEngine &engine, std::function callback); 23 | static bool ProviderContexts(FilterEngine &engine, std::function callback); 24 | static bool Sublayers(FilterEngine &engine, std::function callback); 25 | }; 26 | 27 | } // namespace wfp 28 | -------------------------------------------------------------------------------- /src/libwfp/objectexplorer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "objectexplorer.h" 3 | 4 | namespace wfp 5 | { 6 | 7 | //static 8 | bool ObjectExplorer::GetFilter(FilterEngine &engine, const GUID &key, std::function callback) 9 | { 10 | FWPM_FILTER0 *filter; 11 | 12 | auto status = FwpmFilterGetByKey0( 13 | engine.session(), 14 | &key, 15 | &filter 16 | ); 17 | 18 | if (status != ERROR_SUCCESS) 19 | { 20 | return false; 21 | } 22 | 23 | auto result = callback(*filter); 24 | 25 | FwpmFreeMemory0((void**)&filter); 26 | 27 | return result; 28 | } 29 | 30 | //static 31 | bool ObjectExplorer::GetFilter(FilterEngine &engine, UINT64 id, std::function callback) 32 | { 33 | FWPM_FILTER0 *filter; 34 | 35 | auto status = FwpmFilterGetById0( 36 | engine.session(), 37 | id, 38 | &filter 39 | ); 40 | 41 | if (status != ERROR_SUCCESS) 42 | { 43 | return false; 44 | } 45 | 46 | auto result = callback(*filter); 47 | 48 | FwpmFreeMemory0((void**)&filter); 49 | 50 | return result; 51 | } 52 | 53 | //static 54 | bool ObjectExplorer::GetLayer(FilterEngine &engine, const GUID &key, std::function callback) 55 | { 56 | FWPM_LAYER0 *layer; 57 | 58 | auto status = FwpmLayerGetByKey0( 59 | engine.session(), 60 | &key, 61 | &layer 62 | ); 63 | 64 | if (status != ERROR_SUCCESS) 65 | { 66 | return false; 67 | } 68 | 69 | auto result = callback(*layer); 70 | 71 | FwpmFreeMemory0((void**)&layer); 72 | 73 | return result; 74 | } 75 | 76 | //static 77 | bool ObjectExplorer::GetLayer(FilterEngine &engine, UINT16 id, std::function callback) 78 | { 79 | FWPM_LAYER0 *layer; 80 | 81 | auto status = FwpmLayerGetById0( 82 | engine.session(), 83 | id, 84 | &layer 85 | ); 86 | 87 | if (status != ERROR_SUCCESS) 88 | { 89 | return false; 90 | } 91 | 92 | auto result = callback(*layer); 93 | 94 | FwpmFreeMemory0((void**)&layer); 95 | 96 | return result; 97 | } 98 | 99 | //static 100 | bool ObjectExplorer::GetProvider(FilterEngine &engine, const GUID &key, std::function callback) 101 | { 102 | FWPM_PROVIDER0 *provider; 103 | 104 | auto status = FwpmProviderGetByKey0( 105 | engine.session(), 106 | &key, 107 | &provider 108 | ); 109 | 110 | if (status != ERROR_SUCCESS) 111 | { 112 | return false; 113 | } 114 | 115 | auto result = callback(*provider); 116 | 117 | FwpmFreeMemory0((void**)&provider); 118 | 119 | return result; 120 | } 121 | 122 | //static 123 | bool ObjectExplorer::GetSublayer(FilterEngine &engine, const GUID &key, std::function callback) 124 | { 125 | FWPM_SUBLAYER0 *sublayer; 126 | 127 | auto status = FwpmSubLayerGetByKey0( 128 | engine.session(), 129 | &key, 130 | &sublayer 131 | ); 132 | 133 | if (status != ERROR_SUCCESS) 134 | { 135 | return false; 136 | } 137 | 138 | auto result = callback(*sublayer); 139 | 140 | FwpmFreeMemory0((void**)&sublayer); 141 | 142 | return result; 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/libwfp/objectexplorer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "filterengine.h" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wfp 9 | { 10 | 11 | class ObjectExplorer 12 | { 13 | public: 14 | 15 | static bool GetFilter(FilterEngine &engine, const GUID &key, std::function callback); 16 | static bool GetFilter(FilterEngine &engine, UINT64 id, std::function callback); 17 | static bool GetLayer(FilterEngine &engine, const GUID &key, std::function callback); 18 | static bool GetLayer(FilterEngine &engine, UINT16 id, std::function callback); 19 | static bool GetProvider(FilterEngine &engine, const GUID &key, std::function callback); 20 | static bool GetSublayer(FilterEngine &engine, const GUID &key, std::function callback); 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/libwfp/objectinstaller.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "objectinstaller.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace wfp 9 | { 10 | 11 | //static 12 | bool ObjectInstaller::AddFilter(FilterEngine &engine, FilterBuilder &filterBuilder, const IConditionBuilder &conditionBuilder, UINT64 *id) 13 | { 14 | return conditionBuilder.build([&](FWPM_FILTER_CONDITION0 *conditions, size_t numConditions) 15 | { 16 | return filterBuilder.build([&](FWPM_FILTER0 &filter) 17 | { 18 | filter.filterCondition = conditions; 19 | filter.numFilterConditions = static_cast(numConditions); 20 | 21 | auto status = FwpmFilterAdd0( 22 | engine.session(), 23 | &filter, 24 | nullptr, 25 | id 26 | ); 27 | 28 | if (ERROR_SUCCESS != status) 29 | { 30 | THROW_WINDOWS_ERROR(status, "Register filter with BFE"); 31 | } 32 | 33 | return true; 34 | }); 35 | }); 36 | } 37 | 38 | //static 39 | bool ObjectInstaller::AddProvider(FilterEngine &engine, ProviderBuilder &providerBuilder, GUID *key) 40 | { 41 | return providerBuilder.build([&](FWPM_PROVIDER0 &provider) 42 | { 43 | if (nullptr != key && common::Guid::Empty(provider.providerKey)) 44 | { 45 | provider.providerKey = common::Guid::GenerateQuick(); 46 | } 47 | 48 | auto status = FwpmProviderAdd0( 49 | engine.session(), 50 | &provider, 51 | nullptr 52 | ); 53 | 54 | if (ERROR_SUCCESS != status) 55 | { 56 | THROW_WINDOWS_ERROR(status, "Register provider with BFE"); 57 | } 58 | 59 | if (nullptr != key) 60 | { 61 | *key = provider.providerKey; 62 | } 63 | 64 | return true; 65 | }); 66 | } 67 | 68 | //static 69 | bool ObjectInstaller::AddSublayer(FilterEngine &engine, SublayerBuilder &sublayerBuilder, GUID *key) 70 | { 71 | return sublayerBuilder.build([&](FWPM_SUBLAYER0 &sublayer) 72 | { 73 | if (nullptr != key && common::Guid::Empty(sublayer.subLayerKey)) 74 | { 75 | sublayer.subLayerKey = common::Guid::GenerateQuick(); 76 | } 77 | 78 | auto status = FwpmSubLayerAdd0( 79 | engine.session(), 80 | &sublayer, 81 | nullptr 82 | ); 83 | 84 | if (ERROR_SUCCESS != status) 85 | { 86 | THROW_WINDOWS_ERROR(status, "Register sublayer with BFE"); 87 | } 88 | 89 | if (nullptr != key) 90 | { 91 | *key = sublayer.subLayerKey; 92 | } 93 | 94 | return true; 95 | }); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/libwfp/objectinstaller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iconditionbuilder.h" 4 | #include "filterbuilder.h" 5 | #include "filterengine.h" 6 | #include "providerbuilder.h" 7 | #include "sublayerbuilder.h" 8 | 9 | namespace wfp 10 | { 11 | 12 | class ObjectInstaller 13 | { 14 | public: 15 | 16 | static bool AddFilter(FilterEngine &engine, FilterBuilder &filterBuilder, const IConditionBuilder &conditionBuilder, UINT64 *id = nullptr); 17 | static bool AddProvider(FilterEngine &engine, ProviderBuilder &providerBuilder, GUID *key = nullptr); 18 | static bool AddSublayer(FilterEngine &engine, SublayerBuilder &sublayerBuilder, GUID *key = nullptr); 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/libwfp/objectmonitor.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "objectmonitor.h" 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | ObjectMonitor::ObjectMonitor(std::shared_ptr engine) 9 | : m_engine(engine) 10 | , m_eventSubscription(nullptr) 11 | { 12 | } 13 | 14 | ObjectMonitor::~ObjectMonitor() 15 | { 16 | monitorEventsStop(); 17 | } 18 | 19 | void ObjectMonitor::monitorEvents(std::function callback) 20 | { 21 | m_eventCallback = callback; 22 | 23 | FWPM_NET_EVENT_SUBSCRIPTION0 spec = { 0 }; 24 | 25 | auto status = FwpmNetEventSubscribe0(m_engine->session(), &spec, EventCallback, this, &m_eventSubscription); 26 | 27 | if (ERROR_SUCCESS != status) 28 | { 29 | THROW_WINDOWS_ERROR(status, "Register subscription for net events."); 30 | } 31 | } 32 | 33 | //static 34 | void CALLBACK ObjectMonitor::EventCallback(void *context, const FWPM_NET_EVENT1 *event) 35 | { 36 | reinterpret_cast(context)->m_eventCallback(*event); 37 | } 38 | 39 | void ObjectMonitor::monitorEventsStop() 40 | { 41 | FwpmNetEventUnsubscribe0(m_engine->session(), m_eventSubscription); 42 | m_eventSubscription = nullptr; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/libwfp/objectmonitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "filterengine.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace wfp 10 | { 11 | 12 | class ObjectMonitor 13 | { 14 | public: 15 | 16 | ObjectMonitor(std::shared_ptr engine); 17 | ~ObjectMonitor(); 18 | 19 | void monitorEvents(std::function callback); 20 | void monitorEventsStop(); 21 | 22 | private: 23 | 24 | std::shared_ptr m_engine; 25 | 26 | std::function m_eventCallback; 27 | HANDLE m_eventSubscription; 28 | 29 | static void CALLBACK EventCallback(void *context, const FWPM_NET_EVENT1 *event); 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/libwfp/providerbuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "providerbuilder.h" 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | ProviderBuilder::ProviderBuilder(BuilderValidation validation) 9 | : m_validation(validation) 10 | { 11 | memset(&m_provider, 0, sizeof(m_provider)); 12 | } 13 | 14 | ProviderBuilder &ProviderBuilder::key(const GUID &key) 15 | { 16 | m_keyProvided = true; 17 | 18 | memcpy(&m_provider.providerKey, &key, sizeof(m_provider.providerKey)); 19 | return *this; 20 | } 21 | 22 | ProviderBuilder &ProviderBuilder::name(const std::wstring &name) 23 | { 24 | m_nameProvided = true; 25 | 26 | m_name = name; 27 | m_provider.displayData.name = const_cast(m_name.c_str()); 28 | 29 | return *this; 30 | } 31 | 32 | ProviderBuilder &ProviderBuilder::description(const std::wstring &description) 33 | { 34 | m_description = description; 35 | m_provider.displayData.description = const_cast(m_description.c_str()); 36 | 37 | return *this; 38 | } 39 | 40 | ProviderBuilder &ProviderBuilder::persistent() 41 | { 42 | m_provider.flags |= FWPM_PROVIDER_FLAG_PERSISTENT; 43 | return *this; 44 | } 45 | 46 | ProviderBuilder &ProviderBuilder::data(const uint8_t *data, size_t size) 47 | { 48 | m_data = std::make_unique(size); 49 | m_dataSize = size; 50 | 51 | memcpy(m_data.get(), data, size); 52 | 53 | m_provider.providerData.data = m_data.get(); 54 | m_provider.providerData.size = static_cast(m_dataSize); 55 | 56 | return *this; 57 | } 58 | 59 | ProviderBuilder &ProviderBuilder::serviceName(const std::wstring &serviceName) 60 | { 61 | m_serviceName = serviceName; 62 | m_provider.serviceName = const_cast(m_serviceName.c_str()); 63 | 64 | return *this; 65 | } 66 | 67 | bool ProviderBuilder::build(ProviderSink sink) 68 | { 69 | switch (m_validation) 70 | { 71 | case BuilderValidation::Extra: 72 | { 73 | if (false == m_keyProvided) 74 | { 75 | THROW_ERROR("Rejecting partially initialized sublayer"); 76 | } 77 | 78 | // No break, fall through. 79 | } 80 | case BuilderValidation::OnlyCritical: 81 | { 82 | if (false == m_nameProvided) 83 | { 84 | THROW_ERROR("Rejecting partially initialized sublayer"); 85 | } 86 | 87 | break; 88 | } 89 | } 90 | 91 | return sink(m_provider); 92 | } 93 | 94 | const GUID &ProviderBuilder::id() const 95 | { 96 | return m_provider.providerKey; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/libwfp/providerbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iidentifiable.h" 4 | #include "buildervalidation.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace wfp 12 | { 13 | 14 | typedef std::function ProviderSink; 15 | 16 | class ProviderBuilder : public IIdentifiable 17 | { 18 | public: 19 | 20 | ProviderBuilder(BuilderValidation validation = BuilderValidation::Extra); 21 | 22 | ProviderBuilder(const ProviderBuilder&) = delete; 23 | ProviderBuilder &operator=(const ProviderBuilder&) = delete; 24 | 25 | ProviderBuilder &key(const GUID &key); 26 | ProviderBuilder &name(const std::wstring &name); 27 | ProviderBuilder &description(const std::wstring &description); 28 | 29 | ProviderBuilder &persistent(); 30 | 31 | // Optional data to provide additional context. 32 | ProviderBuilder &data(const uint8_t *data, size_t size); 33 | 34 | // Optional name of Windows service hosting the provider. 35 | // This allows the BFE to detect that a provider has been disabled. 36 | ProviderBuilder &serviceName(const std::wstring &serviceName); 37 | 38 | bool build(ProviderSink sink); 39 | 40 | const GUID &IIdentifiable::id() const override; 41 | 42 | private: 43 | 44 | FWPM_PROVIDER0 m_provider; 45 | 46 | std::wstring m_name; 47 | std::wstring m_description; 48 | std::unique_ptr m_data; 49 | size_t m_dataSize; 50 | std::wstring m_serviceName; 51 | 52 | BuilderValidation m_validation; 53 | 54 | bool m_keyProvided = false; 55 | bool m_nameProvided = false; 56 | }; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/libwfp/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // libwfp.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/libwfp/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | -------------------------------------------------------------------------------- /src/libwfp/sublayerbuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sublayerbuilder.h" 3 | #include 4 | 5 | namespace wfp 6 | { 7 | 8 | SublayerBuilder::SublayerBuilder(BuilderValidation validation) 9 | : m_validation(validation) 10 | { 11 | memset(&m_sublayer, 0, sizeof(m_sublayer)); 12 | } 13 | 14 | SublayerBuilder &SublayerBuilder::key(const GUID &key) 15 | { 16 | m_keyProvided = true; 17 | 18 | memcpy(&m_sublayer.subLayerKey, &key, sizeof(m_sublayer.subLayerKey)); 19 | return *this; 20 | } 21 | 22 | SublayerBuilder &SublayerBuilder::name(const std::wstring &name) 23 | { 24 | m_nameProvided = true; 25 | 26 | m_name = name; 27 | m_sublayer.displayData.name = const_cast(m_name.c_str()); 28 | 29 | return *this; 30 | } 31 | 32 | SublayerBuilder &SublayerBuilder::description(const std::wstring &description) 33 | { 34 | m_description = description; 35 | m_sublayer.displayData.description = const_cast(m_description.c_str()); 36 | 37 | return *this; 38 | } 39 | 40 | SublayerBuilder &SublayerBuilder::persistent() 41 | { 42 | m_sublayer.flags |= FWPM_SUBLAYER_FLAG_PERSISTENT; 43 | return *this; 44 | } 45 | 46 | SublayerBuilder &SublayerBuilder::provider(const GUID &provider) 47 | { 48 | m_providerProvided = true; 49 | 50 | memcpy(&m_providerKey, &provider, sizeof(m_providerKey)); 51 | m_sublayer.providerKey = &m_providerKey; 52 | 53 | return *this; 54 | } 55 | 56 | SublayerBuilder &SublayerBuilder::data(const uint8_t *data, size_t size) 57 | { 58 | m_data = std::make_unique(size); 59 | m_dataSize = size; 60 | 61 | memcpy(m_data.get(), data, size); 62 | 63 | m_sublayer.providerData.data = m_data.get(); 64 | m_sublayer.providerData.size = static_cast(m_dataSize); 65 | 66 | return *this; 67 | } 68 | 69 | SublayerBuilder &SublayerBuilder::weight(UINT16 weight) 70 | { 71 | m_weightProvided = true; 72 | 73 | m_sublayer.weight = weight; 74 | return *this; 75 | } 76 | 77 | bool SublayerBuilder::build(SublayerSink sink) 78 | { 79 | switch (m_validation) 80 | { 81 | case BuilderValidation::Extra: 82 | { 83 | if (false == m_keyProvided 84 | || false == m_providerProvided) 85 | { 86 | THROW_ERROR("Rejecting partially initialized sublayer"); 87 | } 88 | 89 | // No break, fall through. 90 | } 91 | case BuilderValidation::OnlyCritical: 92 | { 93 | if (false == m_nameProvided 94 | || false == m_weightProvided) 95 | { 96 | THROW_ERROR("Rejecting partially initialized sublayer"); 97 | } 98 | 99 | break; 100 | } 101 | } 102 | 103 | return sink(m_sublayer); 104 | } 105 | 106 | const GUID &SublayerBuilder::id() const 107 | { 108 | return m_sublayer.subLayerKey; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/libwfp/sublayerbuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iidentifiable.h" 4 | #include "buildervalidation.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace wfp 13 | { 14 | 15 | typedef std::function SublayerSink; 16 | 17 | class SublayerBuilder : public IIdentifiable 18 | { 19 | public: 20 | 21 | SublayerBuilder(BuilderValidation validation = BuilderValidation::Extra); 22 | 23 | SublayerBuilder(const SublayerBuilder&) = delete; 24 | SublayerBuilder &operator=(const SublayerBuilder&) = delete; 25 | 26 | SublayerBuilder &key(const GUID &key); 27 | SublayerBuilder &name(const std::wstring &name); 28 | SublayerBuilder &description(const std::wstring &description); 29 | 30 | SublayerBuilder &persistent(); 31 | SublayerBuilder &provider(const GUID &provider); 32 | SublayerBuilder &data(const uint8_t *data, size_t size); 33 | SublayerBuilder &weight(UINT16 weight); 34 | 35 | bool build(SublayerSink sink); 36 | 37 | const GUID &IIdentifiable::id() const override; 38 | 39 | private: 40 | 41 | FWPM_SUBLAYER0 m_sublayer; 42 | 43 | std::wstring m_name; 44 | std::wstring m_description; 45 | GUID m_providerKey; 46 | std::unique_ptr m_data; 47 | size_t m_dataSize; 48 | 49 | BuilderValidation m_validation; 50 | 51 | bool m_keyProvided = false; 52 | bool m_nameProvided = false; 53 | bool m_providerProvided = false; 54 | bool m_weightProvided = false; 55 | }; 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/libwfp/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /src/libwfp/transaction.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "transaction.h" 3 | #include 4 | #include 5 | #include 6 | 7 | namespace wfp 8 | { 9 | 10 | //static 11 | bool Transaction::Execute(FilterEngine &engine, std::function operation) 12 | { 13 | return Execute(engine, operation, true); 14 | } 15 | 16 | //static 17 | bool Transaction::ExecuteReadOnly(FilterEngine &engine, std::function operation) 18 | { 19 | return Execute(engine, operation, false); 20 | } 21 | 22 | //static 23 | bool Transaction::Execute(FilterEngine &engine, std::function operation, bool readWrite) 24 | { 25 | auto status = FwpmTransactionBegin0(engine.session(), (readWrite ? 0 : FWPM_TXN_READ_ONLY)); 26 | 27 | if (ERROR_SUCCESS != status) 28 | { 29 | THROW_WINDOWS_ERROR(status, "Initiate WFP transaction"); 30 | } 31 | 32 | bool operationResult = false; 33 | 34 | try 35 | { 36 | operationResult = operation(); 37 | } 38 | catch (...) 39 | { 40 | // Attemp to abort and throw with inner exception if it fails 41 | status = FwpmTransactionAbort0(engine.session()); 42 | 43 | if (ERROR_SUCCESS != status) 44 | { 45 | THROW_WINDOWS_ERROR(status, "Abort WFP transaction"); 46 | } 47 | 48 | // Successfully aborted so rethrow original exception 49 | throw; 50 | } 51 | 52 | if (operationResult) 53 | { 54 | status = FwpmTransactionCommit0(engine.session()); 55 | 56 | if (ERROR_SUCCESS != status) 57 | { 58 | THROW_WINDOWS_ERROR(status, "Commit WFP transaction"); 59 | } 60 | } 61 | else 62 | { 63 | status = FwpmTransactionAbort0(engine.session()); 64 | 65 | if (ERROR_SUCCESS != status) 66 | { 67 | THROW_WINDOWS_ERROR(status, "Abort WFP transaction"); 68 | } 69 | } 70 | 71 | return operationResult; 72 | } 73 | 74 | } // namespace wfp 75 | -------------------------------------------------------------------------------- /src/libwfp/transaction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "filterengine.h" 4 | #include 5 | #include 6 | 7 | namespace wfp 8 | { 9 | 10 | class Transaction 11 | { 12 | public: 13 | 14 | static bool Execute(FilterEngine &engine, std::function operation); 15 | static bool ExecuteReadOnly(FilterEngine &engine, std::function operation); 16 | 17 | private: 18 | 19 | static bool Execute(FilterEngine &engine, std::function operation, bool readWrite); 20 | }; 21 | 22 | } // namespace wfp 23 | -------------------------------------------------------------------------------- /src/test-libwfp/integration/operations.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CppUnitTest.h" 3 | #include "libwfp/conditionbuilder.h" 4 | #include "libwfp/conditions/conditionapplication.h" 5 | #include "libwfp/conditions/conditionport.h" 6 | #include "libwfp/filterbuilder.h" 7 | #include "libwfp/sublayerbuilder.h" 8 | #include "libwfp/providerbuilder.h" 9 | #include "libwfp/filterengine.h" 10 | #include "libwfp/objectexplorer.h" 11 | #include "libwfp/objectdeleter.h" 12 | #include "libwfp/objectinstaller.h" 13 | #include "libwfp/transaction.h" 14 | #include "libcommon/string.h" 15 | #include "test-libwfp/ncat.h" 16 | #include 17 | 18 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 19 | using namespace ::wfp::conditions; 20 | 21 | namespace testlibwfp 22 | { 23 | 24 | TEST_CLASS(IntegrationTest) 25 | { 26 | public: 27 | 28 | TEST_METHOD(BasicFilterOps) 29 | { 30 | static const GUID Layer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; 31 | 32 | wfp::ConditionBuilder conditionBuilder(Layer); 33 | conditionBuilder.add_condition(ConditionPort::Remote(5555)); 34 | 35 | wfp::FilterBuilder filterBuilder; 36 | 37 | static const GUID FilterKey = { 38 | 0xa86fd1bf, 39 | 0x21cd, 40 | 0x6432, 41 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 42 | }; 43 | 44 | filterBuilder 45 | .key(FilterKey) 46 | .name(L"BasicFilterOps") 47 | .description(L"Integration test: Block outgoing traffic with destination port 5555") 48 | .layer(Layer) 49 | .weight(MAXUINT64) 50 | .block(); 51 | 52 | auto engine = wfp::FilterEngine::DynamicSession(); 53 | 54 | Assert::IsTrue(wfp::ObjectInstaller::AddFilter(*engine, filterBuilder, conditionBuilder)); 55 | 56 | Assert::IsTrue(wfp::ObjectExplorer::GetFilter(*engine, FilterKey, [](const FWPM_FILTER0 &filter) 57 | { 58 | return 0 == wcscmp(filter.displayData.name, L"BasicFilterOps"); 59 | })); 60 | 61 | wfp::ObjectDeleter::DeleteFilter(*engine, FilterKey); 62 | 63 | Assert::IsFalse(wfp::ObjectExplorer::GetFilter(*engine, FilterKey, [](const FWPM_FILTER0 &) 64 | { 65 | return true; 66 | })); 67 | } 68 | 69 | TEST_METHOD(BasicProviderOps) 70 | { 71 | static const GUID ProviderKey = { 72 | 0xa86fd1bf, 73 | 0x21d0, 74 | 0x6432, 75 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 76 | }; 77 | 78 | static const uint8_t ProviderData[]{ 79 | 0xaa, 0xbb, 0xcc, 0xdd, 0xee 80 | }; 81 | 82 | wfp::ProviderBuilder providerBuilder; 83 | 84 | providerBuilder 85 | .key(ProviderKey) 86 | .name(L"BasicProviderOps") 87 | .description(L"Integration test: Dummy provider") 88 | .data(ProviderData, sizeof(ProviderData)); 89 | 90 | auto engine = wfp::FilterEngine::DynamicSession(); 91 | 92 | Assert::IsTrue(wfp::ObjectInstaller::AddProvider(*engine, providerBuilder)); 93 | 94 | Assert::IsTrue(wfp::ObjectExplorer::GetProvider(*engine, ProviderKey, [](const FWPM_PROVIDER0 &provider) 95 | { 96 | return 0 == wcscmp(provider.displayData.name, L"BasicProviderOps") 97 | && sizeof(ProviderData) == provider.providerData.size 98 | && 0 == memcmp(provider.providerData.data, ProviderData, sizeof(ProviderData)); 99 | })); 100 | 101 | wfp::ObjectDeleter::DeleteProvider(*engine, ProviderKey); 102 | 103 | Assert::IsFalse(wfp::ObjectExplorer::GetProvider(*engine, ProviderKey, [](const FWPM_PROVIDER0 &) 104 | { 105 | return true; 106 | })); 107 | } 108 | 109 | TEST_METHOD(BasicSublayerOps) 110 | { 111 | static const GUID SublayerKey = { 112 | 0xa86fd1bf, 113 | 0x21d0, 114 | 0x6433, 115 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 116 | }; 117 | 118 | // Context data is always referred to as "provider data". 119 | static const uint8_t ProviderData[]{ 120 | 0xaa, 0xbb, 0xcc, 0xdd, 0xee 121 | }; 122 | 123 | wfp::SublayerBuilder sublayerBuilder; 124 | 125 | sublayerBuilder 126 | .key(SublayerKey) 127 | .name(L"BasicSublayerOps") 128 | .description(L"Integration test: Dummy sublayer") 129 | .data(ProviderData, sizeof(ProviderData)); 130 | 131 | auto engine = wfp::FilterEngine::DynamicSession(); 132 | 133 | Assert::IsTrue(wfp::ObjectInstaller::AddSublayer(*engine, sublayerBuilder)); 134 | 135 | Assert::IsTrue(wfp::ObjectExplorer::GetSublayer(*engine, SublayerKey, [](const FWPM_SUBLAYER0 &sublayer) 136 | { 137 | return 0 == wcscmp(sublayer.displayData.name, L"BasicSublayerOps") 138 | && sizeof(ProviderData) == sublayer.providerData.size 139 | && 0 == memcmp(sublayer.providerData.data, ProviderData, sizeof(ProviderData)); 140 | })); 141 | 142 | wfp::ObjectDeleter::DeleteSublayer(*engine, SublayerKey); 143 | 144 | Assert::IsFalse(wfp::ObjectExplorer::GetSublayer(*engine, SublayerKey, [](const FWPM_SUBLAYER0 &) 145 | { 146 | return true; 147 | })); 148 | } 149 | 150 | TEST_METHOD(BlockOutgoingByPort) 151 | { 152 | static const GUID ProviderKey = { 153 | 0xa86fd1bf, 154 | 0x21d0, 155 | 0x0000, 156 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 157 | }; 158 | 159 | static const uint8_t ProviderData[]{ 160 | 0xaa, 0xbb, 0xcc, 0xdd, 0xee 161 | }; 162 | 163 | wfp::ProviderBuilder providerBuilder; 164 | 165 | providerBuilder 166 | .key(ProviderKey) 167 | .name(L"BlockOutgoingByPort") 168 | .description(L"Integration test: Block Ncat outgoing traffic with destination port 80") 169 | .data(ProviderData, sizeof(ProviderData)); 170 | 171 | auto engine = wfp::FilterEngine::DynamicSession(); 172 | 173 | Assert::IsTrue(wfp::ObjectInstaller::AddProvider(*engine, providerBuilder)); 174 | 175 | static const GUID SublayerKey = { 176 | 0xa86fd1bf, 177 | 0x21d0, 178 | 0x0001, 179 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 180 | }; 181 | 182 | // Context data is always referred to as "provider data". 183 | static const uint8_t SublayerProviderData[]{ 184 | 0xaa, 0xbb, 0xcc, 0xdd, 0xef 185 | }; 186 | 187 | wfp::SublayerBuilder sublayerBuilder; 188 | 189 | sublayerBuilder 190 | .key(SublayerKey) 191 | .name(L"BlockOutgoingByPort") 192 | .description(L"Integration test: Block Ncat outgoing traffic with destination port 80") 193 | .provider(ProviderKey) 194 | .data(SublayerProviderData, sizeof(SublayerProviderData)) 195 | .weight(MAXUINT16); 196 | 197 | Assert::IsTrue(wfp::ObjectInstaller::AddSublayer(*engine, sublayerBuilder)); 198 | 199 | static const unsigned short PORT = 80; 200 | static const GUID LayerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; 201 | 202 | static const GUID FilterKey = { 203 | 0xa86fd1bf, 204 | 0x21d0, 205 | 0x0002, 206 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 207 | }; 208 | 209 | wfp::ConditionBuilder conditionBuilder(LayerKey); 210 | 211 | conditionBuilder.add_condition(std::make_unique(Ncat::Path())); 212 | conditionBuilder.add_condition(ConditionPort::Remote(PORT)); 213 | 214 | wfp::FilterBuilder filterBuilder; 215 | 216 | filterBuilder 217 | .key(FilterKey) 218 | .name(L"BlockOutgoingByPort") 219 | .description(L"Integration test: Block Ncat outgoing traffic with destination port 80") 220 | .provider(ProviderKey) 221 | .layer(LayerKey) 222 | .sublayer(SublayerKey) 223 | .weight(MAXUINT64) 224 | .block(); 225 | 226 | Assert::IsTrue(wfp::ObjectInstaller::AddFilter(*engine, filterBuilder, conditionBuilder)); 227 | 228 | Ncat ncat(L"-4 www.mullvad.net 80"); 229 | 230 | // Verify error message was printed 231 | Assert::IsTrue(common::string::BeginsWith(ncat.output(), std::string("Ncat:"))); 232 | 233 | // Verify return code 234 | Assert::AreEqual(ncat.returnCode(), (DWORD)Ncat::ReturnCode::Error); 235 | } 236 | 237 | }; 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/test-libwfp/integration/transaction.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CppUnitTest.h" 3 | #include "libwfp/filterengine.h" 4 | #include "libwfp/objectinstaller.h" 5 | #include "libwfp/objectdeleter.h" 6 | #include "libwfp/objectexplorer.h" 7 | #include "libwfp/providerbuilder.h" 8 | #include "libwfp/transaction.h" 9 | 10 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 11 | 12 | namespace testlibwfp 13 | { 14 | 15 | TEST_CLASS(TransactionIntegrationTest) 16 | { 17 | public: 18 | 19 | TEST_METHOD(ReadWriteTransaction) 20 | { 21 | static const GUID ProviderKey = { 22 | 0xa86fd1bf, 23 | 0x21d0, 24 | 0x6432, 25 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 26 | }; 27 | 28 | wfp::ProviderBuilder builder; 29 | 30 | builder 31 | .key(ProviderKey) 32 | .name(L"ReadWriteTransaction") 33 | .description(L"Integration test: Dummy provider"); 34 | 35 | auto engine = wfp::FilterEngine::DynamicSession(); 36 | 37 | auto providerOps = [&]() 38 | { 39 | return wfp::ObjectInstaller::AddProvider(*engine, builder) 40 | && wfp::ObjectExplorer::GetProvider(*engine, ProviderKey, [](const FWPM_PROVIDER0 &) 41 | { 42 | return true; 43 | }); 44 | }; 45 | 46 | Assert::IsTrue(wfp::Transaction::Execute(*engine, providerOps)); 47 | } 48 | 49 | TEST_METHOD(ReadOnlyTransaction) 50 | { 51 | static const GUID ProviderKey = { 52 | 0xa86fd1bf, 53 | 0x21d0, 54 | 0x6432, 55 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 56 | }; 57 | 58 | wfp::ProviderBuilder builder; 59 | 60 | builder 61 | .key(ProviderKey) 62 | .name(L"ReadOnlyTransaction") 63 | .description(L"Integration test: Dummy provider"); 64 | 65 | auto engine = wfp::FilterEngine::DynamicSession(); 66 | 67 | Assert::IsTrue(wfp::ObjectInstaller::AddProvider(*engine, builder)); 68 | 69 | auto verifyProvider = [&]() 70 | { 71 | return wfp::ObjectExplorer::GetProvider(*engine, ProviderKey, [](const FWPM_PROVIDER0 &provider) 72 | { 73 | return 0 == wcscmp(provider.displayData.name, L"ReadOnlyTransaction"); 74 | }); 75 | }; 76 | 77 | Assert::IsTrue(wfp::Transaction::ExecuteReadOnly(*engine, verifyProvider)); 78 | } 79 | 80 | TEST_METHOD(ReadOnlyTransactionIsReadOnly) 81 | { 82 | auto engine = wfp::FilterEngine::DynamicSession(); 83 | 84 | auto addProvider = [&]() 85 | { 86 | wfp::ProviderBuilder builder; 87 | 88 | builder 89 | .name(L"ReadOnlyTransactionIsReadOnly") 90 | .description(L"Integration test: Dummy provider"); 91 | 92 | return wfp::ObjectInstaller::AddProvider(*engine, builder); 93 | }; 94 | 95 | Assert::ExpectException([&]() { wfp::Transaction::ExecuteReadOnly(*engine, addProvider); }); 96 | } 97 | 98 | }; 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/test-libwfp/ncat.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ncat.h" 3 | #include 4 | #include 5 | #include 6 | 7 | Ncat::Ncat(const std::wstring &args) 8 | { 9 | m_nc = common::process::ApplicationRunner::StartDetached(Path(), args); 10 | } 11 | 12 | bool Ncat::write(const std::string &data) 13 | { 14 | return m_nc->write(data); 15 | } 16 | 17 | std::string Ncat::output() 18 | { 19 | std::string data; 20 | 21 | if (m_nc->read(data, 1000, 1000)) 22 | { 23 | return data; 24 | } 25 | 26 | THROW_ERROR("Failed to read Ncat output"); 27 | } 28 | 29 | DWORD Ncat::returnCode() 30 | { 31 | DWORD returnCode; 32 | 33 | if (m_nc->join(returnCode, 1000)) 34 | { 35 | return returnCode; 36 | } 37 | 38 | THROW_ERROR("Failed to read Ncat return code"); 39 | } 40 | 41 | // static 42 | std::wstring Ncat::Path() 43 | { 44 | // 45 | // Current process is started from 46 | // x:\foo\bar\libwfp\bin\-\tests.exe 47 | // 48 | // From that, we need to construct: 49 | // x:\foo\bar\libwfp\thirdparty\ncat\ncat.exe 50 | // 51 | 52 | wchar_t rawPath[MAX_PATH]; 53 | 54 | if (0 == GetCurrentDirectory(_countof(rawPath), rawPath)) 55 | { 56 | THROW_ERROR("Failed to construct path for Ncat"); 57 | } 58 | 59 | std::wstring path(rawPath); 60 | 61 | static const auto repositoryDir = L"libwfp\\"; 62 | 63 | auto repositoryOffset = path.rfind(repositoryDir); 64 | 65 | if (repositoryOffset == std::wstring::npos) 66 | { 67 | THROW_ERROR("Failed to construct path for Ncat"); 68 | } 69 | 70 | return path.substr(0, repositoryOffset + wcslen(repositoryDir)) 71 | .append(L"thirdparty\\ncat\\ncat.exe"); 72 | } 73 | -------------------------------------------------------------------------------- /src/test-libwfp/ncat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class Ncat 8 | { 9 | public: 10 | 11 | enum ReturnCode 12 | { 13 | Ok = 0, 14 | Error = 1 15 | }; 16 | 17 | Ncat(const std::wstring &args); 18 | 19 | bool write(const std::string &data); 20 | std::string output(); 21 | DWORD returnCode(); 22 | 23 | static std::wstring Path(); 24 | 25 | private: 26 | 27 | std::unique_ptr m_nc; 28 | }; 29 | -------------------------------------------------------------------------------- /src/test-libwfp/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // test.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/test-libwfp/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | -------------------------------------------------------------------------------- /src/test-libwfp/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <WinSDKVer.h> 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 11 | 12 | #include <SDKDDKVer.h> 13 | -------------------------------------------------------------------------------- /src/test-libwfp/test-libwfp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | {F3FEBDE7-FBC8-48EC-8F24-5F33B8ACFB2A} 32 | Win32Proj 33 | tests 34 | 10.0 35 | NativeUnitTestProject 36 | 37 | 38 | 39 | DynamicLibrary 40 | true 41 | v143 42 | Unicode 43 | false 44 | 45 | 46 | DynamicLibrary 47 | false 48 | v143 49 | true 50 | Unicode 51 | false 52 | 53 | 54 | DynamicLibrary 55 | true 56 | v143 57 | Unicode 58 | false 59 | 60 | 61 | DynamicLibrary 62 | true 63 | v143 64 | Unicode 65 | false 66 | 67 | 68 | DynamicLibrary 69 | false 70 | v143 71 | true 72 | Unicode 73 | false 74 | 75 | 76 | DynamicLibrary 77 | false 78 | v143 79 | true 80 | Unicode 81 | false 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | true 109 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 110 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 111 | 112 | 113 | true 114 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 115 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 116 | 117 | 118 | true 119 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 120 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 121 | 122 | 123 | false 124 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 125 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 126 | 127 | 128 | false 129 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 130 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 131 | 132 | 133 | false 134 | $(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\ 135 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 136 | 137 | 138 | 139 | Use 140 | Level4 141 | Disabled 142 | true 143 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 144 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 145 | MultiThreadedDebug 146 | stdcpp20 147 | 148 | 149 | Console 150 | true 151 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 152 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 153 | 154 | 155 | 156 | 157 | Use 158 | Level4 159 | Disabled 160 | true 161 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 162 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 163 | MultiThreadedDebug 164 | stdcpp20 165 | 166 | 167 | Console 168 | true 169 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 170 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 171 | 172 | 173 | 174 | 175 | Use 176 | Level4 177 | Disabled 178 | true 179 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 180 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 181 | MultiThreadedDebug 182 | stdcpp20 183 | 184 | 185 | Console 186 | true 187 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 188 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 189 | 190 | 191 | 192 | 193 | Use 194 | Level4 195 | MaxSpeed 196 | true 197 | true 198 | true 199 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 200 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 201 | MultiThreaded 202 | stdcpp20 203 | Guard 204 | 205 | 206 | Console 207 | true 208 | true 209 | true 210 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 211 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 212 | 213 | 214 | 215 | 216 | Use 217 | Level4 218 | MaxSpeed 219 | true 220 | true 221 | true 222 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 223 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 224 | MultiThreaded 225 | stdcpp20 226 | Guard 227 | 228 | 229 | Console 230 | true 231 | true 232 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 233 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 234 | 235 | 236 | 237 | 238 | Use 239 | Level4 240 | MaxSpeed 241 | true 242 | true 243 | true 244 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 245 | $(ProjectDir)..\;$(VCInstallDir)UnitTest\include;$(ProjectDir)..\..\..\windows-libraries\src\ 246 | MultiThreaded 247 | stdcpp20 248 | Guard 249 | 250 | 251 | Console 252 | true 253 | true 254 | $(SolutionDir)bin/$(Platform)-$(Configuration);$(VCInstallDir)UnitTest\lib 255 | libwfp.lib;libcommon.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | Create 264 | Create 265 | Create 266 | Create 267 | Create 268 | Create 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /src/test-libwfp/test-libwfp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {2bb539b3-69f0-48d7-9b0d-f99bf08f3970} 6 | 7 | 8 | {22e5eafa-5221-4399-a3ed-bfd1e7b0a110} 9 | 10 | 11 | 12 | 13 | wfp 14 | 15 | 16 | integration 17 | 18 | 19 | 20 | 21 | wfp 22 | 23 | 24 | integration 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/test-libwfp/wfp/ipaddress.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CppUnitTest.h" 3 | #include "libwfp/ipaddress.h" 4 | #include "libwfp/ipnetwork.h" 5 | 6 | using IpAddress = ::wfp::IpAddress; 7 | using IpNetwork = ::wfp::IpNetwork; 8 | 9 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 10 | 11 | namespace Microsoft::VisualStudio::CppUnitTestFramework 12 | { 13 | 14 | template<> 15 | std::wstring ToString(const wfp::IpAddress::Type &address) 16 | { 17 | switch (address) 18 | { 19 | case IpAddress::Type::Ipv4: 20 | return L"IpAddress::Type::Ipv4"; 21 | case IpAddress::Type::Ipv6: 22 | return L"IpAddress::Type::Ipv6"; 23 | } 24 | return L"IpAddress::Type::UNKNOWN"; 25 | } 26 | 27 | } 28 | 29 | namespace testlibwfp 30 | { 31 | 32 | TEST_CLASS(TestLibWfpIpAddr) 33 | { 34 | public: 35 | 36 | TEST_METHOD(ConstructIpv4) 37 | { 38 | static const wchar_t *literalString = L"127.0.0.1"; 39 | 40 | IpAddress ip_from_literal(IpAddress::Literal({ 127, 0, 0, 1 })); 41 | IpAddress ip_from_string(literalString); 42 | IpAddress ip_from_raw(0x7f000001); 43 | 44 | Assert::AreEqual(ip_from_literal.type(), IpAddress::Type::Ipv4); 45 | Assert::AreEqual(ip_from_string.type(), IpAddress::Type::Ipv4); 46 | Assert::AreEqual(ip_from_raw.type(), IpAddress::Type::Ipv4); 47 | 48 | Assert::AreEqual(ip_from_string.toString().c_str(), literalString); 49 | Assert::AreEqual(ip_from_literal.toString().c_str(), literalString); 50 | Assert::AreEqual(ip_from_raw.toString().c_str(), literalString); 51 | } 52 | 53 | TEST_METHOD(ConstructIpv4NetworkIncludes) 54 | { 55 | static const uint32_t prefix = 16; 56 | IpAddress network_address(IpAddress::Literal{ 192, 168, 0, 0 }); 57 | IpNetwork network(network_address, prefix); 58 | 59 | const IpAddress::Literal matchingAddresses[] = { 60 | IpAddress::Literal { 192, 168, 0, 1 }, 61 | IpAddress::Literal { 192, 168, 254, 254 } 62 | }; 63 | 64 | for (const auto &address : matchingAddresses) 65 | { 66 | Assert::IsTrue(network.includes(address)); 67 | } 68 | 69 | const IpAddress::Literal nonMatchingAddresses[] = { 70 | IpAddress::Literal { 192, 169, 0, 1 }, 71 | IpAddress::Literal { 193, 168, 254, 254 }, 72 | IpAddress::Literal { 127, 0, 0, 1 } 73 | }; 74 | 75 | for (const auto &address : nonMatchingAddresses) 76 | { 77 | Assert::IsFalse(network.includes(address)); 78 | } 79 | } 80 | 81 | TEST_METHOD(ConstructIpv6NetworkIncludes) 82 | { 83 | static const uint32_t prefix = 10; 84 | IpAddress network_address(IpAddress::Literal6{ 0xfe80, 0, 0, 0, 0, 0, 0, 0 }); 85 | IpNetwork network(network_address, prefix); 86 | 87 | const IpAddress::Literal6 matchingAddresses[] = { 88 | IpAddress::Literal6 { 0xfe80, 0, 0, 0, 0, 0, 0, 0 }, 89 | // Test trailing bits 90 | IpAddress::Literal6 { 0xfebf, 0, 0, 0, 0, 0, 0, 0 }, 91 | IpAddress::Literal6 { 0xfe80, 0, 1, 0, 1, 0, 1, 0 } 92 | }; 93 | 94 | for (const auto &address : matchingAddresses) 95 | { 96 | Assert::IsTrue(network.includes(address)); 97 | } 98 | 99 | const IpAddress::Literal6 nonMatchingAddresses[] = { 100 | IpAddress::Literal6 { 0, 1, 0, 1, 0, 1, 0, 1 }, 101 | // Test trailing bits 102 | IpAddress::Literal6 { 0xfec0, 0, 0, 0, 0, 0, 0, 0 } 103 | }; 104 | 105 | for (const auto &address : nonMatchingAddresses) 106 | { 107 | Assert::IsFalse(network.includes(address)); 108 | } 109 | } 110 | 111 | TEST_METHOD(ConstructIpv6) 112 | { 113 | static const wchar_t *literalString = L"1000:1100:1200:1300:1400:1500:1600:1700"; 114 | 115 | IpAddress ip_from_literal(IpAddress::Literal6({ 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700 })); 116 | IpAddress ip_from_string(literalString); 117 | 118 | const uint8_t raw[16] = { 0x10, 00, 0x11, 00, 0x12, 00, 0x13, 00, 0x14, 00, 0x15, 00, 0x16, 00, 0x17, 00 }; 119 | 120 | FWP_BYTE_ARRAY16 netnode; 121 | memcpy(netnode.byteArray16, raw, sizeof(netnode.byteArray16)); 122 | 123 | IpAddress ip_from_raw(netnode); 124 | 125 | Assert::AreEqual(ip_from_literal.type(), IpAddress::Type::Ipv6); 126 | Assert::AreEqual(ip_from_string.type(), IpAddress::Type::Ipv6); 127 | Assert::AreEqual(ip_from_raw.type(), IpAddress::Type::Ipv6); 128 | 129 | Assert::AreEqual(ip_from_string.toString().c_str(), literalString); 130 | Assert::AreEqual(ip_from_literal.toString().c_str(), literalString); 131 | Assert::AreEqual(ip_from_raw.toString().c_str(), literalString); 132 | } 133 | 134 | }; 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/test-libwfp/wfp/layerconditions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CppUnitTest.h" 3 | #include "libwfp/layerconditions.h" 4 | #include 5 | #include 6 | 7 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 8 | 9 | namespace testlibwfp 10 | { 11 | 12 | TEST_CLASS(TestLibWfpLayerConditions) 13 | { 14 | public: 15 | 16 | TEST_METHOD(IsCompatibleWithCompatibleCondition) 17 | { 18 | Assert::IsTrue(wfp::LayerConditions::IsCompatible(FWPM_LAYER_OUTBOUND_TRANSPORT_V6, FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE)); 19 | 20 | // Match last item in defined condition array, to ensure no off-by-one issues 21 | Assert::IsTrue(wfp::LayerConditions::IsCompatible(FWPM_LAYER_OUTBOUND_TRANSPORT_V6, FWPM_CONDITION_CURRENT_PROFILE_ID)); 22 | } 23 | 24 | TEST_METHOD(IsNotCompatibleWithIncompatibleCondition) 25 | { 26 | Assert::IsFalse(wfp::LayerConditions::IsCompatible(FWPM_LAYER_OUTBOUND_TRANSPORT_V6, FWPM_CONDITION_DIRECTION)); 27 | } 28 | 29 | TEST_METHOD(IsCompatibleWithInvalidLayerThrows) 30 | { 31 | static const GUID InvalidLayer = { 32 | 0xa86fd1bf, 33 | 0x21cd, 34 | 0x497e, 35 | { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 } 36 | }; 37 | 38 | Assert::ExpectException([&]() { wfp::LayerConditions::IsCompatible(InvalidLayer, FWPM_CONDITION_DIRECTION); }); 39 | } 40 | 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /thirdparty/ncat/README: -------------------------------------------------------------------------------- 1 | This is a portable (statically compiled) Win32 version of Ncat. You 2 | should be able to take the ncat.exe and run it on other systems 3 | without having to also copy over a bunch of DLLs, etc. 4 | 5 | More information on Ncat: http://nmap.org/ncat/ 6 | 7 | You can get the version number of this ncat by runnign "ncat 8 | --version". We don't create a new Ncat portable for each Ncat 9 | release, so you will have to compile your own if you want a newer 10 | version. Instructions for doing so are available at: 11 | https://secwiki.org/w/Nmap/Ncat_Portable 12 | 13 | Ncat is distributed under the same free and open source license as 14 | Nmap. See http://nmap.org/book/man-legal.html. 15 | 16 | -------------------------------------------------------------------------------- /thirdparty/ncat/ncat.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mullvad/libwfp/105a27f44a1c129b751fe533aabc9938eeec1bc9/thirdparty/ncat/ncat.exe --------------------------------------------------------------------------------