aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Firewall
diff options
context:
space:
mode:
authorchris_bednarski <Chris.Bednarski@minfos.com.au>2023-08-26 18:51:38 +1000
committerBob Arnson <github@bobs.org>2023-11-19 12:17:13 -0500
commit80e604761b4f43b9b79a4878fcae360b071a7c35 (patch)
tree9ca40a1d60a2ef1a5a1a426382356ae8b7cf9868 /src/ext/Firewall
parent6e974490eeabc9a3728aa2fb9ad07e8a5adf4fb6 (diff)
downloadwix-80e604761b4f43b9b79a4878fcae360b071a7c35.tar.gz
wix-80e604761b4f43b9b79a4878fcae360b071a7c35.tar.bz2
wix-80e604761b4f43b9b79a4878fcae360b071a7c35.zip
change firewall extension table name to Wix5FirewallException
Diffstat (limited to 'src/ext/Firewall')
-rw-r--r--src/ext/Firewall/ca/firewall.cpp18
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs160
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs4
-rw-r--r--src/ext/Firewall/wixext/FirewallCompiler.cs40
-rw-r--r--src/ext/Firewall/wixext/FirewallDecompiler.cs40
-rw-r--r--src/ext/Firewall/wixext/FirewallTableDefinitions.cs6
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi32
7 files changed, 235 insertions, 65 deletions
diff --git a/src/ext/Firewall/ca/firewall.cpp b/src/ext/Firewall/ca/firewall.cpp
index 2a1ef825..eed6f9df 100644
--- a/src/ext/Firewall/ca/firewall.cpp
+++ b/src/ext/Firewall/ca/firewall.cpp
@@ -3,7 +3,7 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5LPCWSTR vcsFirewallExceptionQuery = 5LPCWSTR vcsFirewallExceptionQuery =
6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix4FirewallException`"; 6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix5FirewallException`";
7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection }; 7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection };
8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown }; 8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 }; 9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
@@ -49,15 +49,15 @@ static UINT SchedFirewallExceptions(
49 ExitOnFailure(hr, "Failed to initialize"); 49 ExitOnFailure(hr, "Failed to initialize");
50 50
51 // anything to do? 51 // anything to do?
52 if (S_OK != WcaTableExists(L"Wix4FirewallException")) 52 if (S_OK != WcaTableExists(L"Wix5FirewallException"))
53 { 53 {
54 WcaLog(LOGMSG_STANDARD, "Wix4FirewallException table doesn't exist, so there are no firewall exceptions to configure."); 54 WcaLog(LOGMSG_STANDARD, "Wix5FirewallException table doesn't exist, so there are no firewall exceptions to configure.");
55 ExitFunction(); 55 ExitFunction();
56 } 56 }
57 57
58 // query and loop through all the firewall exceptions 58 // query and loop through all the firewall exceptions
59 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView); 59 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView);
60 ExitOnFailure(hr, "Failed to open view on Wix4FirewallException table"); 60 ExitOnFailure(hr, "Failed to open view on Wix5FirewallException table");
61 61
62 while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) 62 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
63 { 63 {
@@ -150,7 +150,7 @@ static UINT SchedFirewallExceptions(
150 { 150 {
151 hr = S_OK; 151 hr = S_OK;
152 } 152 }
153 ExitOnFailure(hr, "failure occured while processing Wix4FirewallException table"); 153 ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table");
154 154
155 // schedule ExecFirewallExceptions if there's anything to do 155 // schedule ExecFirewallExceptions if there's anything to do
156 if (pwzCustomActionData && *pwzCustomActionData) 156 if (pwzCustomActionData && *pwzCustomActionData)
@@ -159,16 +159,16 @@ static UINT SchedFirewallExceptions(
159 159
160 if (WCA_TODO_INSTALL == todoSched) 160 if (WCA_TODO_INSTALL == todoSched)
161 { 161 {
162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
163 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback"); 163 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
164 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 164 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
165 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution"); 165 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
166 } 166 }
167 else 167 else
168 { 168 {
169 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 169 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
170 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback"); 170 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
171 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 171 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
172 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution"); 172 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
173 } 173 }
174 } 174 }
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index 06a877f6..7119e92d 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -18,17 +18,21 @@ namespace WixToolsetTest.Firewall
18 var folder = TestData.Get(@"TestData\UsingFirewall"); 18 var folder = TestData.Get(@"TestData\UsingFirewall");
19 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); 19 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
20 20
21 var results = build.BuildAndQuery(Build, "Wix4FirewallException", "CustomAction"); 21 var results = build.BuildAndQuery(Build, "Wix5FirewallException", "CustomAction");
22 WixAssert.CompareLineByLine(new[] 22 WixAssert.CompareLineByLine(new[]
23 { 23 {
24 "CustomAction:Wix4ExecFirewallExceptionsInstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", 24 "CustomAction:Wix5ExecFirewallExceptionsInstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
25 "CustomAction:Wix4ExecFirewallExceptionsUninstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", 25 "CustomAction:Wix5ExecFirewallExceptionsUninstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
26 "CustomAction:Wix4RollbackFirewallExceptionsInstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", 26 "CustomAction:Wix5RollbackFirewallExceptionsInstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
27 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", 27 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
28 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t", 28 "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
29 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t", 29 "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
30 "Wix4FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 30 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
31 "Wix4FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 31 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1",
32 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1",
33 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2",
34 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1",
35 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1",
32 }, results); 36 }, results);
33 } 37 }
34 38
@@ -38,17 +42,21 @@ namespace WixToolsetTest.Firewall
38 var folder = TestData.Get(@"TestData\UsingFirewall"); 42 var folder = TestData.Get(@"TestData\UsingFirewall");
39 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); 43 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
40 44
41 var results = build.BuildAndQuery(BuildARM64, "Wix4FirewallException", "CustomAction"); 45 var results = build.BuildAndQuery(BuildARM64, "Wix5FirewallException", "CustomAction");
42 WixAssert.CompareLineByLine(new[] 46 WixAssert.CompareLineByLine(new[]
43 { 47 {
44 "CustomAction:Wix4ExecFirewallExceptionsInstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", 48 "CustomAction:Wix5ExecFirewallExceptionsInstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
45 "CustomAction:Wix4ExecFirewallExceptionsUninstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", 49 "CustomAction:Wix5ExecFirewallExceptionsUninstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
46 "CustomAction:Wix4RollbackFirewallExceptionsInstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", 50 "CustomAction:Wix5RollbackFirewallExceptionsInstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
47 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", 51 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
48 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t", 52 "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
49 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t", 53 "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
50 "Wix4FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 54 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
51 "Wix4FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 55 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1",
56 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1",
57 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2",
58 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1",
59 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1",
52 }, results); 60 }, results);
53 } 61 }
54 62
@@ -71,8 +79,17 @@ namespace WixToolsetTest.Firewall
71 { 79 {
72 "FirewallException", 80 "FirewallException",
73 "FirewallException", 81 "FirewallException",
82 "FirewallException",
83 "FirewallException",
84 "FirewallException",
85 "FirewallException",
74 }, actual.Select(a => a.Name).ToArray()); 86 }, actual.Select(a => a.Name).ToArray());
87 }
75 88
89 [Fact]
90 public void RoundtripAttributesAreCorrectForApp()
91 {
92 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleApp");
76 WixAssert.CompareLineByLine(new[] 93 WixAssert.CompareLineByLine(new[]
77 { 94 {
78 "Id=ExampleFirewall", 95 "Id=ExampleFirewall",
@@ -85,8 +102,13 @@ namespace WixToolsetTest.Firewall
85 "Description=An app-based firewall exception", 102 "Description=An app-based firewall exception",
86 "Outbound=no", 103 "Outbound=no",
87 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 104 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
88 }, actual[0].Attributes); 105 }, actual.Attributes);
106 }
89 107
108 [Fact]
109 public void RoundtripAttributesAreCorrectForPort()
110 {
111 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort");
90 WixAssert.CompareLineByLine(new[] 112 WixAssert.CompareLineByLine(new[]
91 { 113 {
92 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs", 114 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs",
@@ -98,7 +120,79 @@ namespace WixToolsetTest.Firewall
98 "Description=A port-based firewall exception", 120 "Description=A port-based firewall exception",
99 "Outbound=yes", 121 "Outbound=yes",
100 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 122 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
101 }, actual[1].Attributes); 123 }, actual.Attributes);
124 }
125
126 [Fact]
127 public void RoundtripAttributesAreCorrectForDNSScope()
128 {
129 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope");
130 WixAssert.CompareLineByLine(new[]
131 {
132 "Id=fexxY71H2ZBkPalv7uid1Yy4qaA_lA",
133 "Name=ExampleDNSScope",
134 "Scope=DNS",
135 "Port=356",
136 "Protocol=udp",
137 "Profile=all",
138 "Description=DNS scope firewall exception",
139 "Outbound=no",
140 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
141 }, actual.Attributes);
142 }
143
144 [Fact]
145 public void RoundtripAttributesAreCorrectForDHCPScope()
146 {
147 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope");
148 WixAssert.CompareLineByLine(new[]
149 {
150 "Id=fex6bkfWwpiRGI.wVFx0T7W4LXIHxU",
151 "Name=ExampleDHCPScope",
152 "Scope=DHCP",
153 "Protocol=211",
154 "Program=test.exe",
155 "Profile=public",
156 "Description=DHCP scope firewall exception",
157 "Outbound=no",
158 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
159 }, actual.Attributes);
160 }
161
162 [Fact]
163 public void RoundtripAttributesAreCorrectForWINSScope()
164 {
165 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope");
166 WixAssert.CompareLineByLine(new[]
167 {
168 "Id=fexXxaXCXXFh.UxO_BjmZxi1B1du_Q",
169 "Name=ExampleWINSScope",
170 "Scope=WINS",
171 "Port=6573",
172 "Protocol=tcp",
173 "Profile=domain",
174 "Description=WINS scope firewall exception",
175 "Outbound=no",
176 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
177 }, actual.Attributes);
178 }
179
180 [Fact]
181 public void RoundtripAttributesAreCorrectForDefaultGatewayScope()
182 {
183 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope");
184 WixAssert.CompareLineByLine(new[]
185 {
186 "Id=fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8",
187 "Name=ExampleDefaultGatewayScope",
188 "Scope=defaultGateway",
189 "Port=4432",
190 "Protocol=tcp",
191 "Profile=private",
192 "Description=defaultGateway scope firewall exception",
193 "Outbound=no",
194 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
195 }, actual.Attributes);
102 } 196 }
103 197
104 private static void Build(string[] args) 198 private static void Build(string[] args)
@@ -122,5 +216,31 @@ namespace WixToolsetTest.Firewall
122 var result = WixRunner.Execute(args); 216 var result = WixRunner.Execute(args);
123 result.AssertSuccess(); 217 result.AssertSuccess();
124 } 218 }
219 class AttributeVerifier
220 {
221 public string Name { get; set; }
222 public string[] Attributes { get; set; }
223 }
224
225 private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName)
226 {
227 var folder = TestData.Get(@"TestData", "UsingFirewall");
228 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
229 var output = Path.Combine(folder, $"Firewall{ruleName}.xml");
230
231 build.BuildAndDecompileAndBuild(Build, Decompile, output);
232
233 var doc = XDocument.Load(output);
234 var actual = doc.Descendants()
235 .Where(e => e.Name.Namespace == nameSpace)
236 .Select(fe => new AttributeVerifier
237 {
238 Name = fe.Attributes().Single(a => a.Name.LocalName == "Name").Value,
239 Attributes = fe.Attributes().Select(a => $"{a.Name.LocalName}={a.Value}").ToArray()
240 })
241 .Single(av => av.Name == ruleName);
242
243 return actual;
244 }
125 } 245 }
126} 246}
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
index c712d895..957aa642 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
@@ -12,6 +12,10 @@
12 </File> 12 </File>
13 13
14 <fw:FirewallException Description="A port-based firewall exception" Name="ExamplePort" Port="42" Outbound="yes" Scope="localSubnet" /> 14 <fw:FirewallException Description="A port-based firewall exception" Name="ExamplePort" Port="42" Outbound="yes" Scope="localSubnet" />
15 <fw:FirewallException Description="DNS scope firewall exception" Name="ExampleDNSScope" Port="356" Protocol="udp" Scope="DNS" />
16 <fw:FirewallException Description="DHCP scope firewall exception" Name="ExampleDHCPScope" Program="test.exe" Protocol="211" Scope="DHCP" Profile="public" />
17 <fw:FirewallException Description="WINS scope firewall exception" Name="ExampleWINSScope" Port="6573" Scope="WINS" Profile="domain"/>
18 <fw:FirewallException Description="defaultGateway scope firewall exception" Name="ExampleDefaultGatewayScope" Port="4432" Scope="defaultGateway" Profile="private" />
15 </Component> 19 </Component>
16 </ComponentGroup> 20 </ComponentGroup>
17 </Fragment> 21 </Fragment>
diff --git a/src/ext/Firewall/wixext/FirewallCompiler.cs b/src/ext/Firewall/wixext/FirewallCompiler.cs
index 19ee0b6d..ed49ba9c 100644
--- a/src/ext/Firewall/wixext/FirewallCompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallCompiler.cs
@@ -135,7 +135,12 @@ namespace WixToolset.Firewall
135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP; 135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
136 break; 136 break;
137 default: 137 default:
138 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp")); 138 int parsedProtocol;
139 if (!Int32.TryParse(protocolValue, out parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0)
140 {
141 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255"));
142 }
143 protocol = parsedProtocol;
139 break; 144 break;
140 } 145 }
141 break; 146 break;
@@ -149,8 +154,20 @@ namespace WixToolset.Firewall
149 case "localSubnet": 154 case "localSubnet":
150 remoteAddresses = "LocalSubnet"; 155 remoteAddresses = "LocalSubnet";
151 break; 156 break;
157 case "DNS":
158 remoteAddresses = "dns";
159 break;
160 case "DHCP":
161 remoteAddresses = "dhcp";
162 break;
163 case "WINS":
164 remoteAddresses = "wins";
165 break;
166 case "defaultGateway":
167 remoteAddresses = "DefaultGateway";
168 break;
152 default: 169 default:
153 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet")); 170 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
154 break; 171 break;
155 } 172 }
156 break; 173 break;
@@ -251,6 +268,21 @@ namespace WixToolset.Firewall
251 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers)); 268 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
252 } 269 }
253 270
271 // Ports can only be specified if the protocol is TCP or UDP.
272 if (!String.IsNullOrEmpty(port) && protocol.HasValue)
273 {
274 switch(protocol.Value)
275 {
276 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
277 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
278 break;
279
280 default:
281 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "Protocol", protocol.Value.ToString()));
282 break;
283 }
284 }
285
254 if (!this.Messaging.EncounteredError) 286 if (!this.Messaging.EncounteredError)
255 { 287 {
256 // at this point, File attribute and File parent element are treated the same 288 // at this point, File attribute and File parent element are treated the same
@@ -300,8 +332,8 @@ namespace WixToolset.Firewall
300 symbol.Attributes = attributes; 332 symbol.Attributes = attributes;
301 } 333 }
302 334
303 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); 335 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix5SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
304 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); 336 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix5SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
305 } 337 }
306 } 338 }
307 339
diff --git a/src/ext/Firewall/wixext/FirewallDecompiler.cs b/src/ext/Firewall/wixext/FirewallDecompiler.cs
index 69f2c3f4..9ddd8a9a 100644
--- a/src/ext/Firewall/wixext/FirewallDecompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallDecompiler.cs
@@ -32,7 +32,7 @@ namespace WixToolset.Firewall
32 { 32 {
33 switch (table.Name) 33 switch (table.Name)
34 { 34 {
35 case "Wix4FirewallException": 35 case "Wix5FirewallException":
36 this.DecompileWixFirewallExceptionTable(table); 36 this.DecompileWixFirewallExceptionTable(table);
37 break; 37 break;
38 default: 38 default:
@@ -69,18 +69,29 @@ namespace WixToolset.Firewall
69 string[] addresses = ((string)row[2]).Split(','); 69 string[] addresses = ((string)row[2]).Split(',');
70 if (addresses.Length == 1) 70 if (addresses.Length == 1)
71 { 71 {
72 // special-case the Scope attribute values 72 switch(addresses[0])
73 if (addresses[0] == "*")
74 { 73 {
75 firewallException.Add(new XAttribute("Scope", "any")); 74 case "*":
76 } 75 firewallException.Add(new XAttribute("Scope", "any"));
77 else if (addresses[0] == "LocalSubnet") 76 break;
78 { 77 case "LocalSubnet":
79 firewallException.Add(new XAttribute("Scope", "localSubnet")); 78 firewallException.Add(new XAttribute("Scope", "localSubnet"));
80 } 79 break;
81 else 80 case "dns":
82 { 81 firewallException.Add(new XAttribute("Scope", "DNS"));
83 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]); 82 break;
83 case "dhcp":
84 firewallException.Add(new XAttribute("Scope", "DHCP"));
85 break;
86 case "wins":
87 firewallException.Add(new XAttribute("Scope", "WINS"));
88 break;
89 case "DefaultGateway":
90 firewallException.Add(new XAttribute("Scope", "defaultGateway"));
91 break;
92 default:
93 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
94 break;
84 } 95 }
85 } 96 }
86 else 97 else
@@ -107,6 +118,9 @@ namespace WixToolset.Firewall
107 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: 118 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
108 firewallException.Add(new XAttribute("Protocol", "udp")); 119 firewallException.Add(new XAttribute("Protocol", "udp"));
109 break; 120 break;
121 default:
122 firewallException.Add(new XAttribute("Protocol", row[4]));
123 break;
110 } 124 }
111 } 125 }
112 126
@@ -183,7 +197,7 @@ namespace WixToolset.Firewall
183 /// <param name="tables">Collection of all tables.</param> 197 /// <param name="tables">Collection of all tables.</param>
184 private void FinalizeFirewallExceptionTable(TableIndexedCollection tables) 198 private void FinalizeFirewallExceptionTable(TableIndexedCollection tables)
185 { 199 {
186 if (tables.TryGetTable("Wix4FirewallException", out var firewallExceptionTable)) 200 if (tables.TryGetTable("Wix5FirewallException", out var firewallExceptionTable))
187 { 201 {
188 foreach (var row in firewallExceptionTable.Rows) 202 foreach (var row in firewallExceptionTable.Rows)
189 { 203 {
diff --git a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
index 04918f5f..26dedbf1 100644
--- a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
+++ b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
@@ -7,15 +7,15 @@ namespace WixToolset.Firewall
7 public static class FirewallTableDefinitions 7 public static class FirewallTableDefinitions
8 { 8 {
9 public static readonly TableDefinition WixFirewallException = new TableDefinition( 9 public static readonly TableDefinition WixFirewallException = new TableDefinition(
10 "Wix4FirewallException", 10 "Wix5FirewallException",
11 FirewallSymbolDefinitions.WixFirewallException, 11 FirewallSymbolDefinitions.WixFirewallException,
12 new[] 12 new[]
13 { 13 {
14 new ColumnDefinition("Wix4FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column), 14 new ColumnDefinition("Wix5FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column),
15 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property), 15 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property),
16 new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property), 16 new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property),
17 new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property), 17 new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property),
18 new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 6, maxValue: 17, description: "Protocol (6=TCP; 17=UDP)."), 18 new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, maxValue: 255, description: "Protocol (6=TCP; 17=UDP). https://www.iana.org/assignments/protocol-numbers"),
19 new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property), 19 new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property),
20 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"), 20 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"),
21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."), 21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."),
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
index ae02bcd0..736a54b0 100644
--- a/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
+++ b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
@@ -6,32 +6,32 @@
6 <Fragment> 6 <Fragment>
7 <UIRef Id="WixFirewallErrors" /> 7 <UIRef Id="WixFirewallErrors" />
8 <UI> 8 <UI>
9 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsInstall)" /> 9 <ProgressText Action="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsInstall)" />
10 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsUninstall)" /> 10 <ProgressText Action="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsUninstall)" />
11 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsInstall)" /> 11 <ProgressText Action="$(var.Prefix5)RollbackFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsInstall)" />
12 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsInstall)" /> 12 <ProgressText Action="$(var.Prefix5)ExecFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsInstall)" />
13 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsUninstall)" /> 13 <ProgressText Action="$(var.Prefix5)RollbackFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsUninstall)" />
14 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsUninstall)" /> 14 <ProgressText Action="$(var.Prefix5)ExecFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsUninstall)" />
15 </UI> 15 </UI>
16 16
17 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsInstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 17 <CustomAction Id="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsInstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
18 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 18 <CustomAction Id="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
19 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 19 <CustomAction Id="$(var.Prefix5)RollbackFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
20 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 20 <CustomAction Id="$(var.Prefix5)ExecFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
21 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 21 <CustomAction Id="$(var.Prefix5)RollbackFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
22 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 22 <CustomAction Id="$(var.Prefix5)ExecFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
23 23
24 <!-- 24 <!--
25 We need the firewall on Windows XP SP2 or later. 25 We need the firewall on Windows Vista or later.
26 --> 26 -->
27 <InstallExecuteSequence> 27 <InstallExecuteSequence>
28 <Custom Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" /> 28 <Custom Action="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt;= 600" />
29 <Custom Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" /> 29 <Custom Action="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt;= 600" />
30 </InstallExecuteSequence> 30 </InstallExecuteSequence>
31 </Fragment> 31 </Fragment>
32 32
33 <!-- Firewall Custom Action DLL Definitions --> 33 <!-- Firewall Custom Action DLL Definitions -->
34 <Fragment> 34 <Fragment>
35 <Binary Id="$(var.Prefix)FWCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))fwca.dll" /> 35 <Binary Id="$(var.Prefix5)FWCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))fwca.dll" />
36 </Fragment> 36 </Fragment>
37</Include> 37</Include>