add firewall extension decompiler, make msi modifications work, add all attributes
chris_bednarski committed
Sep 21, 2023 at 16:03 UTC
dfb7512b85536b7726080648f2228cf8d0153724
35 files changed
+3356
-347
src/ext/Firewall/ca/firewall.cpp
+783
-197
@@ -3,34 +3,54 @@
3
#include "precomp.h"
4
5
LPCWSTR vcsFirewallExceptionQuery =
6
- L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix5FirewallException`";
7
-enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection };
8
-enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9
-enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
6
+L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction`, `Action`, `EdgeTraversal`, `Enabled`, `Grouping`, `IcmpTypesAndCodes`, `Interfaces`, `InterfaceTypes`, `LocalAddresses`, `RemotePort`, `ServiceName`, `LocalAppPackageId`, `LocalUserAuthorizedList`, `LocalUserOwner`, `RemoteMachineAuthorizedList`, `RemoteUserAuthorizedList`, `SecureFlags` FROM `Wix5FirewallException`";
7
+enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection, feqAction, feqEdgeTraversal, feqEnabled, feqGrouping, feqIcmpTypesAndCodes, feqInterfaces, feqInterfaceTypes, feqLocalAddresses, feqRemotePort, feqServiceName, feqLocalAppPackageId, feqLocalUserAuthorizedList, feqLocalUserOwner, feqRemoteMachineAuthorizedList, feqRemoteUserAuthorizedList, feqSecureFlags };
8
+enum eFirewallExceptionAttributes { feaIgnoreFailures = 1, feaIgnoreUpdates = 2, feaEnableOnUpdate = 4, feaAddINetFwRule2 = 8, feaAddINetFwRule3 = 16 };
9
10
struct FIREWALL_EXCEPTION_ATTRIBUTES
11
{
12
LPWSTR pwzName;
14
-
15
- LPWSTR pwzRemoteAddresses;
16
- LPWSTR pwzPort;
17
- int iProtocol;
18
- LPWSTR pwzProgram;
13
int iAttributes;
20
- int iProfile;
14
+
15
+ // INetFwRule
16
+ int iAction;
17
+ LPWSTR pwzApplicationName;
18
LPWSTR pwzDescription;
19
int iDirection;
20
+ int iEnabled;
21
+ LPWSTR pwzGrouping;
22
+ LPWSTR pwzIcmpTypesAndCodes;
23
+ LPWSTR pwzInterfaces;
24
+ LPWSTR pwzInterfaceTypes;
25
+ LPWSTR pwzLocalAddresses;
26
+ LPWSTR pwzLocalPorts;
27
+ int iProfile;
28
+ int iProtocol;
29
+ LPWSTR pwzRemoteAddresses;
30
+ LPWSTR pwzRemotePorts;
31
+ LPWSTR pwzServiceName;
32
+
33
+ // INetFwRule2
34
+ int iEdgeTraversal;
35
+
36
+ // INetFwRule3
37
+ LPWSTR pwzLocalAppPackageId;
38
+ LPWSTR pwzLocalUserAuthorizedList;
39
+ LPWSTR pwzLocalUserOwner;
40
+ LPWSTR pwzRemoteMachineAuthorizedList;
41
+ LPWSTR pwzRemoteUserAuthorizedList;
42
+ int iSecureFlags;
43
};
44
45
/******************************************************************
26
- SchedFirewallExceptions - immediate custom action worker to
46
+ SchedFirewallExceptions - immediate custom action worker to
47
register and remove firewall exceptions.
48
49
********************************************************************/
50
static UINT SchedFirewallExceptions(
51
__in MSIHANDLE hInstall,
32
- WCA_TODO todoSched
33
- )
52
+ __in WCA_TODO todoSched
53
+)
54
{
55
HRESULT hr = S_OK;
56
UINT er = ERROR_SUCCESS;
@@ -67,19 +87,19 @@ static UINT SchedFirewallExceptions(
87
hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &attrs.pwzRemoteAddresses);
88
ExitOnFailure(hr, "Failed to get firewall exception remote addresses.");
89
70
- hr = WcaGetRecordFormattedString(hRec, feqPort, &attrs.pwzPort);
90
+ hr = WcaGetRecordFormattedString(hRec, feqPort, &attrs.pwzLocalPorts);
91
ExitOnFailure(hr, "Failed to get firewall exception port.");
92
73
- hr = WcaGetRecordInteger(hRec, feqProtocol, &attrs.iProtocol);
93
+ hr = WcaGetRecordFormattedInteger(hRec, feqProtocol, &attrs.iProtocol);
94
ExitOnFailure(hr, "Failed to get firewall exception protocol.");
95
76
- hr = WcaGetRecordFormattedString(hRec, feqProgram, &attrs.pwzProgram);
96
+ hr = WcaGetRecordFormattedString(hRec, feqProgram, &attrs.pwzApplicationName);
97
ExitOnFailure(hr, "Failed to get firewall exception program.");
98
99
hr = WcaGetRecordInteger(hRec, feqAttributes, &attrs.iAttributes);
100
ExitOnFailure(hr, "Failed to get firewall exception attributes.");
81
-
82
- hr = WcaGetRecordInteger(hRec, feqProfile, &attrs.iProfile);
101
+
102
+ hr = WcaGetRecordFormattedInteger(hRec, feqProfile, &attrs.iProfile);
103
ExitOnFailure(hr, "Failed to get firewall exception profile.");
104
105
hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent);
@@ -91,6 +111,54 @@ static UINT SchedFirewallExceptions(
111
hr = WcaGetRecordInteger(hRec, feqDirection, &attrs.iDirection);
112
ExitOnFailure(hr, "Failed to get firewall exception direction.");
113
114
+ hr = WcaGetRecordFormattedInteger(hRec, feqAction, &attrs.iAction);
115
+ ExitOnFailure(hr, "Failed to get firewall exception action.");
116
+
117
+ hr = WcaGetRecordFormattedInteger(hRec, feqEdgeTraversal, &attrs.iEdgeTraversal);
118
+ ExitOnFailure(hr, "Failed to get firewall exception edge traversal.");
119
+
120
+ hr = WcaGetRecordFormattedInteger(hRec, feqEnabled, &attrs.iEnabled);
121
+ ExitOnFailure(hr, "Failed to get firewall exception enabled flag.");
122
+
123
+ hr = WcaGetRecordFormattedString(hRec, feqGrouping, &attrs.pwzGrouping);
124
+ ExitOnFailure(hr, "Failed to get firewall exception grouping.");
125
+
126
+ hr = WcaGetRecordFormattedString(hRec, feqIcmpTypesAndCodes, &attrs.pwzIcmpTypesAndCodes);
127
+ ExitOnFailure(hr, "Failed to get firewall exception ICMP types and codes.");
128
+
129
+ hr = WcaGetRecordFormattedString(hRec, feqInterfaces, &attrs.pwzInterfaces);
130
+ ExitOnFailure(hr, "Failed to get firewall exception interfaces.");
131
+
132
+ hr = WcaGetRecordFormattedString(hRec, feqInterfaceTypes, &attrs.pwzInterfaceTypes);
133
+ ExitOnFailure(hr, "Failed to get firewall exception interface types.");
134
+
135
+ hr = WcaGetRecordFormattedString(hRec, feqLocalAddresses, &attrs.pwzLocalAddresses);
136
+ ExitOnFailure(hr, "Failed to get firewall exception local addresses.");
137
+
138
+ hr = WcaGetRecordFormattedString(hRec, feqRemotePort, &attrs.pwzRemotePorts);
139
+ ExitOnFailure(hr, "Failed to get firewall exception remote port.");
140
+
141
+ hr = WcaGetRecordFormattedString(hRec, feqServiceName, &attrs.pwzServiceName);
142
+ ExitOnFailure(hr, "Failed to get firewall exception service name.");
143
+
144
+ hr = WcaGetRecordFormattedString(hRec, feqLocalAppPackageId, &attrs.pwzLocalAppPackageId);
145
+ ExitOnFailure(hr, "Failed to get firewall exception local app package id.");
146
+
147
+ hr = WcaGetRecordFormattedString(hRec, feqLocalUserAuthorizedList, &attrs.pwzLocalUserAuthorizedList);
148
+ ExitOnFailure(hr, "Failed to get firewall exception local user authorized list.");
149
+
150
+ hr = WcaGetRecordFormattedString(hRec, feqLocalUserOwner, &attrs.pwzLocalUserOwner);
151
+ ExitOnFailure(hr, "Failed to get firewall exception local user owner.");
152
+
153
+ hr = WcaGetRecordFormattedString(hRec, feqRemoteMachineAuthorizedList, &attrs.pwzRemoteMachineAuthorizedList);
154
+ ExitOnFailure(hr, "Failed to get firewall exception remote machine authorized list.");
155
+
156
+ hr = WcaGetRecordFormattedString(hRec, feqRemoteUserAuthorizedList, &attrs.pwzRemoteUserAuthorizedList);
157
+ ExitOnFailure(hr, "Failed to get firewall exception remote user authorized list.");
158
+
159
+ hr = WcaGetRecordFormattedInteger(hRec, feqSecureFlags, &attrs.iSecureFlags);
160
+ ExitOnFailure(hr, "Failed to get firewall exception secure flag.");
161
+
162
// figure out what we're doing for this exception, treating reinstall the same as install
163
WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent);
164
if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
@@ -99,7 +167,6 @@ static UINT SchedFirewallExceptions(
167
continue;
168
}
169
102
- // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path}
170
++cFirewallExceptions;
171
hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData);
172
ExitOnFailure(hr, "failed to write exception action to custom action data");
@@ -116,40 +183,75 @@ static UINT SchedFirewallExceptions(
183
hr = WcaWriteIntegerToCaData(attrs.iAttributes, &pwzCustomActionData);
184
ExitOnFailure(hr, "failed to write exception attributes to custom action data");
185
119
- if (*attrs.pwzProgram)
120
- {
121
- // If program is defined, we have an application exception.
122
- hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData);
123
- ExitOnFailure(hr, "failed to write exception target (application) to custom action data");
124
-
125
- hr = WcaWriteStringToCaData(attrs.pwzProgram, &pwzCustomActionData);
126
- ExitOnFailure(hr, "failed to write application path to custom action data");
127
- }
128
- else
129
- {
130
- // we have a port-only exception
131
- hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData);
132
- ExitOnFailure(hr, "failed to write exception target (port) to custom action data");
133
- }
134
-
135
- hr = WcaWriteStringToCaData(attrs.pwzPort, &pwzCustomActionData);
186
+ hr = WcaWriteStringToCaData(attrs.pwzApplicationName, &pwzCustomActionData);
187
ExitOnFailure(hr, "failed to write application path to custom action data");
188
189
+ hr = WcaWriteStringToCaData(attrs.pwzLocalPorts, &pwzCustomActionData);
190
+ ExitOnFailure(hr, "failed to write local ports to custom action data");
191
+
192
hr = WcaWriteIntegerToCaData(attrs.iProtocol, &pwzCustomActionData);
193
ExitOnFailure(hr, "failed to write exception protocol to custom action data");
194
195
hr = WcaWriteStringToCaData(attrs.pwzDescription, &pwzCustomActionData);
142
- ExitOnFailure(hr, "failed to write firewall rule description to custom action data");
196
+ ExitOnFailure(hr, "failed to write firewall exception description to custom action data");
197
198
hr = WcaWriteIntegerToCaData(attrs.iDirection, &pwzCustomActionData);
145
- ExitOnFailure(hr, "failed to write firewall rule direction to custom action data");
199
+ ExitOnFailure(hr, "failed to write firewall exception direction to custom action data");
200
+
201
+ hr = WcaWriteIntegerToCaData(attrs.iAction, &pwzCustomActionData);
202
+ ExitOnFailure(hr, "failed to write exception action to custom action data");
203
+
204
+ hr = WcaWriteIntegerToCaData(attrs.iEdgeTraversal, &pwzCustomActionData);
205
+ ExitOnFailure(hr, "failed to write exception edge traversal to custom action data");
206
+
207
+ hr = WcaWriteIntegerToCaData(attrs.iEnabled, &pwzCustomActionData);
208
+ ExitOnFailure(hr, "failed to write exception enabled flag to custom action data");
209
+
210
+ hr = WcaWriteStringToCaData(attrs.pwzGrouping, &pwzCustomActionData);
211
+ ExitOnFailure(hr, "failed to write grouping to custom action data");
212
+
213
+ hr = WcaWriteStringToCaData(attrs.pwzIcmpTypesAndCodes, &pwzCustomActionData);
214
+ ExitOnFailure(hr, "failed to write icmp types and codes to custom action data");
215
+
216
+ hr = WcaWriteStringToCaData(attrs.pwzInterfaces, &pwzCustomActionData);
217
+ ExitOnFailure(hr, "failed to write interfaces to custom action data");
218
+
219
+ hr = WcaWriteStringToCaData(attrs.pwzInterfaceTypes, &pwzCustomActionData);
220
+ ExitOnFailure(hr, "failed to write interface types to custom action data");
221
+
222
+ hr = WcaWriteStringToCaData(attrs.pwzLocalAddresses, &pwzCustomActionData);
223
+ ExitOnFailure(hr, "failed to write local addresses to custom action data");
224
+
225
+ hr = WcaWriteStringToCaData(attrs.pwzRemotePorts, &pwzCustomActionData);
226
+ ExitOnFailure(hr, "failed to write remote ports to custom action data");
227
+
228
+ hr = WcaWriteStringToCaData(attrs.pwzServiceName, &pwzCustomActionData);
229
+ ExitOnFailure(hr, "failed to write service name to custom action data");
230
+
231
+ hr = WcaWriteStringToCaData(attrs.pwzLocalAppPackageId, &pwzCustomActionData);
232
+ ExitOnFailure(hr, "failed to write local app package id to custom action data");
233
+
234
+ hr = WcaWriteStringToCaData(attrs.pwzLocalUserAuthorizedList, &pwzCustomActionData);
235
+ ExitOnFailure(hr, "failed to write local user authorized list to custom action data");
236
+
237
+ hr = WcaWriteStringToCaData(attrs.pwzLocalUserOwner, &pwzCustomActionData);
238
+ ExitOnFailure(hr, "failed to write local user owner to custom action data");
239
+
240
+ hr = WcaWriteStringToCaData(attrs.pwzRemoteMachineAuthorizedList, &pwzCustomActionData);
241
+ ExitOnFailure(hr, "failed to write remote machine authorized list to custom action data");
242
+
243
+ hr = WcaWriteStringToCaData(attrs.pwzRemoteUserAuthorizedList, &pwzCustomActionData);
244
+ ExitOnFailure(hr, "failed to write remote user authorized list to custom action data");
245
+
246
+ hr = WcaWriteIntegerToCaData(attrs.iSecureFlags, &pwzCustomActionData);
247
+ ExitOnFailure(hr, "failed to write exception secure flags to custom action data");
248
}
249
250
// reaching the end of the list is actually a good thing, not an error
251
if (E_NOMOREITEMS == hr)
252
{
253
hr = S_OK;
152
- }
254
+ }
255
ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table");
256
257
// schedule ExecFirewallExceptions if there's anything to do
@@ -160,14 +262,14 @@ static UINT SchedFirewallExceptions(
262
if (WCA_TODO_INSTALL == todoSched)
263
{
264
hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
163
- ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
265
+ ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
266
hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
267
ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
268
}
269
else
270
{
271
hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
170
- ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
272
+ ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
273
hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
274
ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
275
}
@@ -180,53 +282,68 @@ static UINT SchedFirewallExceptions(
282
LExit:
283
ReleaseStr(attrs.pwzName);
284
ReleaseStr(attrs.pwzRemoteAddresses);
183
- ReleaseStr(attrs.pwzPort);
184
- ReleaseStr(attrs.pwzProgram);
285
+ ReleaseStr(attrs.pwzLocalPorts);
286
+ ReleaseStr(attrs.pwzApplicationName);
287
ReleaseStr(attrs.pwzDescription);
288
+ ReleaseStr(attrs.pwzGrouping);
289
+ ReleaseStr(attrs.pwzIcmpTypesAndCodes);
290
+ ReleaseStr(attrs.pwzInterfaces);
291
+ ReleaseStr(attrs.pwzInterfaceTypes);
292
+ ReleaseStr(attrs.pwzLocalAddresses);
293
+ ReleaseStr(attrs.pwzRemotePorts);
294
+ ReleaseStr(attrs.pwzServiceName);
295
+ ReleaseStr(attrs.pwzLocalAppPackageId);
296
+ ReleaseStr(attrs.pwzLocalUserAuthorizedList);
297
+ ReleaseStr(attrs.pwzLocalUserOwner);
298
+ ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
299
+ ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
300
ReleaseStr(pwzComponent);
301
ReleaseStr(pwzCustomActionData);
302
303
return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
304
}
305
192
-/******************************************************************
306
+
307
+/*******************************************************************
308
SchedFirewallExceptionsInstall - immediate custom action entry
309
point to register firewall exceptions.
310
311
********************************************************************/
312
extern "C" UINT __stdcall SchedFirewallExceptionsInstall(
313
__in MSIHANDLE hInstall
199
- )
314
+)
315
{
316
return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL);
317
}
318
204
-/******************************************************************
319
+
320
+/*******************************************************************
321
SchedFirewallExceptionsUninstall - immediate custom action entry
322
point to remove firewall exceptions.
323
324
********************************************************************/
325
extern "C" UINT __stdcall SchedFirewallExceptionsUninstall(
326
__in MSIHANDLE hInstall
211
- )
327
+)
328
{
329
return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL);
330
}
331
216
-/******************************************************************
332
+
333
+/*******************************************************************
334
GetFirewallRules - Get the collection of firewall rules.
335
336
********************************************************************/
337
static HRESULT GetFirewallRules(
338
__in BOOL fIgnoreFailures,
339
__out INetFwRules** ppNetFwRules
223
- )
340
+)
341
{
342
HRESULT hr = S_OK;
343
INetFwPolicy2* pNetFwPolicy2 = NULL;
344
INetFwRules* pNetFwRules = NULL;
345
*ppNetFwRules = NULL;
229
-
346
+
347
do
348
{
349
ReleaseNullObject(pNetFwPolicy2);
@@ -262,7 +379,7 @@ static HRESULT GetFirewallRules(
379
380
*ppNetFwRules = pNetFwRules;
381
pNetFwRules = NULL;
265
-
382
+
383
LExit:
384
ReleaseObject(pNetFwPolicy2);
385
ReleaseObject(pNetFwRules);
@@ -270,51 +387,380 @@ LExit:
387
return hr;
388
}
389
273
-/******************************************************************
274
- CreateFwRuleObject - CoCreate a firewall rule, and set the common set of properties which are shared
275
- between port and application firewall rules
390
+
391
+/*******************************************************************
392
+ CreateFwRuleObject - CoCreate a firewall rule, and set the name
393
394
********************************************************************/
395
static HRESULT CreateFwRuleObject(
396
__in BSTR bstrName,
280
- __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
397
__out INetFwRule** ppNetFwRule
282
- )
398
+)
399
+{
400
+ HRESULT hr = S_OK;
401
+ INetFwRule* pNetFwRule = NULL;
402
+ *ppNetFwRule = NULL;
403
+
404
+ hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (LPVOID*)&pNetFwRule);
405
+ ExitOnFailure(hr, "failed to create NetFwRule object");
406
+
407
+ hr = pNetFwRule->put_Name(bstrName);
408
+ ExitOnFailure(hr, "failed to set firewall exception name");
409
+
410
+ *ppNetFwRule = pNetFwRule;
411
+
412
+LExit:
413
+ return hr;
414
+}
415
+
416
+
417
+/*********************************************************************
418
+ GetFwRuleInterfaces - pack firewall rule interfaces into a VARIANT.
419
+ The populated VARIANT needs to be cleaned up by the calling function.
420
+
421
+**********************************************************************/
422
+static HRESULT GetFwRuleInterfaces(
423
+ __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
424
+ __out VARIANT& vInterfaces
425
+)
426
+{
427
+ HRESULT hr = S_OK;
428
+ BSTR bstrInterfaces = NULL;
429
+ const WCHAR FORBIDDEN_FIREWALL_CHAR = L'|';
430
+ LONG iInterfacesCount = 0;
431
+ UINT iLength = 0;
432
+ LONG iIndex = 0;
433
+
434
+ ::VariantInit(&vInterfaces);
435
+ ExitOnNull(attrs.pwzInterfaces, hr, S_OK, "No interfaces to pack");
436
+
437
+ bstrInterfaces = ::SysAllocString(attrs.pwzInterfaces);
438
+ ExitOnNull(bstrInterfaces, hr, E_OUTOFMEMORY, "failed SysAllocString for interfaces");
439
+
440
+ iLength = ::SysStringLen(bstrInterfaces);
441
+
442
+ LPWSTR pwzT = bstrInterfaces;
443
+ while (*pwzT)
444
+ {
445
+ if (FORBIDDEN_FIREWALL_CHAR == *pwzT)
446
+ {
447
+ *pwzT = L'\0';
448
+ pwzT++;
449
+
450
+ // skip empty values inside the interfaces eg. |||
451
+ if (*pwzT && FORBIDDEN_FIREWALL_CHAR != *pwzT)
452
+ {
453
+ iInterfacesCount++;
454
+ }
455
+ }
456
+ else
457
+ {
458
+ if (pwzT == bstrInterfaces)
459
+ {
460
+ iInterfacesCount++;
461
+ }
462
+
463
+ pwzT++;
464
+ }
465
+ }
466
+
467
+ ExitOnNull(iInterfacesCount, hr, S_OK, "All interfaces are empty values");
468
+
469
+ vInterfaces.vt = VT_ARRAY | VT_VARIANT;
470
+ // this will be cleaned up by ReleaseVariant call of the calling function
471
+ vInterfaces.parray = SafeArrayCreateVector(VT_VARIANT, 0, iInterfacesCount);
472
+
473
+ for (LPCWSTR pwzElement = bstrInterfaces; pwzElement < (bstrInterfaces + iLength); ++pwzElement)
474
+ {
475
+ if (*pwzElement)
476
+ {
477
+ VARIANT vElement;
478
+ ::VariantInit(&vElement);
479
+
480
+ vElement.vt = VT_BSTR;
481
+ // this will be cleaned up by ReleaseVariant call of the calling function
482
+ vElement.bstrVal = ::SysAllocString(pwzElement);
483
+ ExitOnNull(vElement.bstrVal, hr, E_OUTOFMEMORY, "failed SysAllocString for interface element");
484
+
485
+ hr = SafeArrayPutElement(vInterfaces.parray, &iIndex, &vElement);
486
+ ExitOnFailure(hr, "failed to put interface '%ls' into safe array", pwzElement);
487
+
488
+ pwzElement += ::SysStringLen(vElement.bstrVal);
489
+ iIndex++;
490
+ }
491
+ }
492
+
493
+LExit:
494
+ ReleaseBSTR(bstrInterfaces);
495
+
496
+ return hr;
497
+}
498
+
499
+/******************************************************************************
500
+ UpdateFwRule2Object - update properties for a firewall INetFwRule2 interface.
501
+ Requires Windows 7 / 2008 R2
502
+
503
+ ******************************************************************************/
504
+static HRESULT UpdateFwRule2Object(
505
+ __in INetFwRule* pNetFwRule,
506
+ __in BOOL fUpdateRule,
507
+ __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
508
+)
509
{
510
HRESULT hr = S_OK;
511
+ INetFwRule2* pNetFwRule2 = NULL;
512
+
513
+ hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule2), (LPVOID*)&pNetFwRule2);
514
+ ExitOnFailure(hr, "failed to query INetFwRule2 interface");
515
+
516
+ if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
517
+ {
518
+ hr = pNetFwRule2->put_EdgeTraversalOptions(attrs.iEdgeTraversal);
519
+ ExitOnFailure(hr, "failed to set exception edge traversal option");
520
+ }
521
+ else if (fUpdateRule)
522
+ {
523
+ hr = pNetFwRule2->put_EdgeTraversalOptions(NET_FW_EDGE_TRAVERSAL_TYPE_DENY);
524
+ ExitOnFailure(hr, "failed to remove exception edge traversal option");
525
+ }
526
+
527
+LExit:
528
+ ReleaseObject(pNetFwRule2);
529
+
530
+ return hr;
531
+}
532
+
533
+
534
+/******************************************************************************
535
+ UpdateFwRule3Object - update properties for a firewall INetFwRule3 interface.
536
+ Requires Windows 8 / 2012
537
+
538
+ ******************************************************************************/
539
+static HRESULT UpdateFwRule3Object(
540
+ __in INetFwRule* pNetFwRule,
541
+ __in BOOL fUpdateRule,
542
+ __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
543
+)
544
+{
545
+ HRESULT hr = S_OK;
546
+
547
+ BSTR bstrLocalAppPackageId = NULL;
548
+ BSTR bstrLocalUserAuthorizedList = NULL;
549
+ BSTR bstrLocalUserOwner = NULL;
550
+ BSTR bstrRemoteMachineAuthorizedList = NULL;
551
+ BSTR bstrRemoteUserAuthorizedList = NULL;
552
+ INetFwRule3* pNetFwRule3 = NULL;
553
+
554
+ bstrLocalAppPackageId = ::SysAllocString(attrs.pwzLocalAppPackageId);
555
+ ExitOnNull(bstrLocalAppPackageId, hr, E_OUTOFMEMORY, "failed SysAllocString for local app package id");
556
+ bstrLocalUserAuthorizedList = ::SysAllocString(attrs.pwzLocalUserAuthorizedList);
557
+ ExitOnNull(bstrLocalUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for local user authorized list");
558
+ bstrLocalUserOwner = ::SysAllocString(attrs.pwzLocalUserOwner);
559
+ ExitOnNull(bstrLocalUserOwner, hr, E_OUTOFMEMORY, "failed SysAllocString for local user owner");
560
+ bstrRemoteMachineAuthorizedList = ::SysAllocString(attrs.pwzRemoteMachineAuthorizedList);
561
+ ExitOnNull(bstrRemoteMachineAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote machine authorized list");
562
+ bstrRemoteUserAuthorizedList = ::SysAllocString(attrs.pwzRemoteUserAuthorizedList);
563
+ ExitOnNull(bstrRemoteUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote user authorized list");
564
+
565
+ hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule3), (LPVOID*)&pNetFwRule3);
566
+ ExitOnFailure(hr, "failed to query INetFwRule3 interface");
567
+
568
+ if (bstrLocalAppPackageId && *bstrLocalAppPackageId)
569
+ {
570
+ hr = pNetFwRule3->put_LocalAppPackageId(bstrLocalAppPackageId);
571
+ ExitOnFailure(hr, "failed to set exception local app package id");
572
+ }
573
+ else if (fUpdateRule)
574
+ {
575
+ hr = pNetFwRule3->put_LocalAppPackageId(NULL);
576
+ ExitOnFailure(hr, "failed to remove exception local app package id");
577
+ }
578
+
579
+ if (bstrLocalUserAuthorizedList && *bstrLocalUserAuthorizedList)
580
+ {
581
+ hr = pNetFwRule3->put_LocalUserAuthorizedList(bstrLocalUserAuthorizedList);
582
+ ExitOnFailure(hr, "failed to set exception local user authorized list");
583
+ }
584
+ else if (fUpdateRule)
585
+ {
586
+ hr = pNetFwRule3->put_LocalUserAuthorizedList(NULL);
587
+ ExitOnFailure(hr, "failed to remove exception local user authorized list");
588
+ }
589
+
590
+ if (bstrLocalUserOwner && *bstrLocalUserOwner)
591
+ {
592
+ hr = pNetFwRule3->put_LocalUserOwner(bstrLocalUserOwner);
593
+ ExitOnFailure(hr, "failed to set exception local user owner");
594
+ }
595
+ else if (fUpdateRule)
596
+ {
597
+ hr = pNetFwRule3->put_LocalUserOwner(NULL);
598
+ ExitOnFailure(hr, "failed to remove exception local user owner");
599
+ }
600
+
601
+ if (bstrRemoteMachineAuthorizedList && *bstrRemoteMachineAuthorizedList)
602
+ {
603
+ hr = pNetFwRule3->put_RemoteMachineAuthorizedList(bstrRemoteMachineAuthorizedList);
604
+ ExitOnFailure(hr, "failed to set exception remote machine authorized list");
605
+ }
606
+ else if (fUpdateRule)
607
+ {
608
+ hr = pNetFwRule3->put_RemoteMachineAuthorizedList(NULL);
609
+ ExitOnFailure(hr, "failed to remove exception remote machine authorized list");
610
+ }
611
+
612
+ if (bstrRemoteUserAuthorizedList && *bstrRemoteUserAuthorizedList)
613
+ {
614
+ hr = pNetFwRule3->put_RemoteUserAuthorizedList(bstrRemoteUserAuthorizedList);
615
+ ExitOnFailure(hr, "failed to set exception remote user authorized list");
616
+ }
617
+ else if (fUpdateRule)
618
+ {
619
+ hr = pNetFwRule3->put_RemoteUserAuthorizedList(NULL);
620
+ ExitOnFailure(hr, "failed to remove exception remote user authorized list");
621
+ }
622
+
623
+ if (MSI_NULL_INTEGER != attrs.iSecureFlags)
624
+ {
625
+ hr = pNetFwRule3->put_SecureFlags(attrs.iSecureFlags);
626
+ ExitOnFailure(hr, "failed to set exception IPsec secure flags");
627
+ }
628
+ else if (fUpdateRule)
629
+ {
630
+ hr = pNetFwRule3->put_SecureFlags(NET_FW_AUTHENTICATE_NONE);
631
+ ExitOnFailure(hr, "failed to reset exception IPsec secure flags");
632
+ }
633
+
634
+LExit:
635
+ ReleaseBSTR(bstrLocalAppPackageId);
636
+ ReleaseBSTR(bstrLocalUserAuthorizedList);
637
+ ReleaseBSTR(bstrLocalUserOwner);
638
+ ReleaseBSTR(bstrRemoteMachineAuthorizedList);
639
+ ReleaseBSTR(bstrRemoteUserAuthorizedList);
640
+ ReleaseObject(pNetFwRule3);
641
+
642
+ return hr;
643
+}
644
+
645
+
646
+/**********************************************************************
647
+ UpdateFwRuleObject - update all properties for a basic firewall rule.
648
+ Requires Windows Vista / 2008
649
+
650
+ **********************************************************************/
651
+static HRESULT UpdateFwRuleObject(
652
+ __in INetFwRule* pNetFwRule,
653
+ __in BOOL fUpdateRule,
654
+ __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
655
+)
656
+{
657
+ HRESULT hr = S_OK;
658
+ BSTR bstrEmpty = NULL;
659
BSTR bstrRemoteAddresses = NULL;
660
+ BSTR bstrFile = NULL;
661
BSTR bstrPort = NULL;
662
BSTR bstrDescription = NULL;
288
- INetFwRule* pNetFwRule = NULL;
289
- *ppNetFwRule = NULL;
663
+ BSTR bstrGrouping = NULL;
664
+ BSTR bstrIcmpTypesAndCodes = NULL;
665
+ BSTR bstrInterfaceTypes = NULL;
666
+ BSTR bstrLocalAddresses = NULL;
667
+ BSTR bstrRemotePort = NULL;
668
+ BSTR bstrServiceName = NULL;
669
+ VARIANT vInterfaces;
670
+ ::VariantInit(&vInterfaces);
671
+ LONG iProtocol = 0;
672
+
673
+ INetFwRule2* pNetFwRule2 = NULL;
674
675
// convert to BSTRs to make COM happy
676
+ bstrEmpty = ::SysAllocString(L"");
677
+ ExitOnNull(bstrEmpty, hr, E_OUTOFMEMORY, "failed SysAllocString for empty placeholder");
678
+
679
bstrRemoteAddresses = ::SysAllocString(attrs.pwzRemoteAddresses);
680
ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
294
- bstrPort = ::SysAllocString(attrs.pwzPort);
681
+ bstrFile = ::SysAllocString(attrs.pwzApplicationName);
682
+ ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for application name");
683
+ bstrPort = ::SysAllocString(attrs.pwzLocalPorts);
684
ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port");
685
bstrDescription = ::SysAllocString(attrs.pwzDescription);
686
ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description");
687
+ bstrGrouping = ::SysAllocString(attrs.pwzGrouping);
688
+ ExitOnNull(bstrGrouping, hr, E_OUTOFMEMORY, "failed SysAllocString for grouping");
689
+ bstrIcmpTypesAndCodes = ::SysAllocString(attrs.pwzIcmpTypesAndCodes);
690
+ ExitOnNull(bstrIcmpTypesAndCodes, hr, E_OUTOFMEMORY, "failed SysAllocString for icmp types and codes");
691
+ bstrInterfaceTypes = ::SysAllocString(attrs.pwzInterfaceTypes);
692
+ ExitOnNull(bstrInterfaceTypes, hr, E_OUTOFMEMORY, "failed SysAllocString for interface types");
693
+ bstrLocalAddresses = ::SysAllocString(attrs.pwzLocalAddresses);
694
+ ExitOnNull(bstrLocalAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for local addresses");
695
+ bstrRemotePort = ::SysAllocString(attrs.pwzRemotePorts);
696
+ ExitOnNull(bstrRemotePort, hr, E_OUTOFMEMORY, "failed SysAllocString for remote port");
697
+ bstrServiceName = ::SysAllocString(attrs.pwzServiceName);
698
+ ExitOnNull(bstrServiceName, hr, E_OUTOFMEMORY, "failed SysAllocString for service name");
699
+
700
+ if (fUpdateRule)
701
+ {
702
+ hr = pNetFwRule->get_Protocol(&iProtocol);
703
+ ExitOnFailure(hr, "failed to get exception protocol");
704
299
- hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (void**)&pNetFwRule);
300
- ExitOnFailure(hr, "failed to create NetFwRule object");
705
+ // If you are editing a TCP port rule and converting it into an ICMP rule,
706
+ // first delete the ports, change protocol from TCP to ICMP, and then add the ports.
707
302
- hr = pNetFwRule->put_Name(bstrName);
303
- ExitOnFailure(hr, "failed to set exception name");
708
+ switch (iProtocol)
709
+ {
710
+ case NET_FW_IP_PROTOCOL_ANY:
711
+ break;
712
305
- hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2>(attrs.iProfile));
306
- ExitOnFailure(hr, "failed to set exception profile");
713
+ case 1: // ICMP
714
+ hr = pNetFwRule->put_IcmpTypesAndCodes(NULL);
715
+ ExitOnFailure(hr, "failed to remove exception icmp types and codes");
716
+ // fall through and reset ports too
717
718
+ default:
719
+ hr = pNetFwRule->put_LocalPorts(NULL);
720
+ ExitOnFailure(hr, "failed to update exception local ports to NULL");
721
+
722
+ hr = pNetFwRule->put_RemotePorts(NULL);
723
+ ExitOnFailure(hr, "failed to update exception remote ports to NULL");
724
+ break;
725
+ }
726
+ }
727
+
728
+ if (MSI_NULL_INTEGER != attrs.iProfile)
729
+ {
730
+ hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2> (attrs.iProfile));
731
+ ExitOnFailure(hr, "failed to set exception profile");
732
+ }
733
+ else if (fUpdateRule)
734
+ {
735
+ hr = pNetFwRule->put_Profiles(NET_FW_PROFILE2_ALL);
736
+ ExitOnFailure(hr, "failed to reset exception profile to all");
737
+ }
738
+
739
+ // The Protocol property must be set before the LocalPorts/RemotePorts properties or an error will be returned.
740
if (MSI_NULL_INTEGER != attrs.iProtocol)
741
{
310
- hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL>(attrs.iProtocol));
742
+ hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL> (attrs.iProtocol));
743
ExitOnFailure(hr, "failed to set exception protocol");
744
}
745
+ else if (fUpdateRule)
746
+ {
747
+ if ((bstrPort && *bstrPort) || (bstrRemotePort && *bstrRemotePort))
748
+ {
749
+ // default protocol is "TCP" in the WiX firewall compiler if a port is specified
750
+ hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
751
+ ExitOnFailure(hr, "failed to reset exception protocol to TCP");
752
+ }
753
+ else
754
+ {
755
+ hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_ANY);
756
+ ExitOnFailure(hr, "failed to reset exception protocol to ANY");
757
+ }
758
+ }
759
760
if (bstrPort && *bstrPort)
761
{
762
hr = pNetFwRule->put_LocalPorts(bstrPort);
317
- ExitOnFailure(hr, "failed to set exception port");
763
+ ExitOnFailure(hr, "failed to set exception local ports '%ls'", bstrPort);
764
}
765
766
if (bstrRemoteAddresses && *bstrRemoteAddresses)
@@ -322,122 +768,195 @@ static HRESULT CreateFwRuleObject(
768
hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses);
769
ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses);
770
}
771
+ else if (fUpdateRule)
772
+ {
773
+ hr = pNetFwRule->put_RemoteAddresses(bstrEmpty);
774
+ ExitOnFailure(hr, "failed to remove exception remote addresses");
775
+ }
776
777
if (bstrDescription && *bstrDescription)
778
{
779
hr = pNetFwRule->put_Description(bstrDescription);
780
ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
781
}
782
+ else if (fUpdateRule)
783
+ {
784
+ hr = pNetFwRule->put_Description(bstrEmpty);
785
+ ExitOnFailure(hr, "failed to remove exception description");
786
+ }
787
788
if (MSI_NULL_INTEGER != attrs.iDirection)
789
{
790
hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (attrs.iDirection));
791
ExitOnFailure(hr, "failed to set exception direction");
792
}
793
+ else if (fUpdateRule)
794
+ {
795
+ hr = pNetFwRule->put_Direction(NET_FW_RULE_DIR_IN);
796
+ ExitOnFailure(hr, "failed to reset exception direction to in");
797
+ }
798
338
- *ppNetFwRule = pNetFwRule;
339
- pNetFwRule = NULL;
799
+ if (MSI_NULL_INTEGER != attrs.iAction)
800
+ {
801
+ hr = pNetFwRule->put_Action(static_cast<NET_FW_ACTION> (attrs.iAction));
802
+ ExitOnFailure(hr, "failed to set exception action");
803
+ }
804
+ else if (fUpdateRule)
805
+ {
806
+ hr = pNetFwRule->put_Action(NET_FW_ACTION_ALLOW);
807
+ ExitOnFailure(hr, "failed to reset exception action to allow");
808
+ }
809
341
-LExit:
342
- ReleaseBSTR(bstrRemoteAddresses);
343
- ReleaseBSTR(bstrPort);
344
- ReleaseBSTR(bstrDescription);
345
- ReleaseObject(pNetFwRule);
810
+ if (bstrFile && *bstrFile)
811
+ {
812
+ hr = pNetFwRule->put_ApplicationName(bstrFile);
813
+ ExitOnFailure(hr, "failed to set exception application name");
814
+ }
815
+ else if (fUpdateRule)
816
+ {
817
+ hr = pNetFwRule->put_ApplicationName(NULL);
818
+ ExitOnFailure(hr, "failed to remove exception application name");
819
+ }
820
347
- return hr;
348
-}
821
+ if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
822
+ {
823
+ switch (attrs.iEdgeTraversal)
824
+ {
825
+ default:
826
+ hr = pNetFwRule->put_EdgeTraversal(NET_FW_EDGE_TRAVERSAL_TYPE_DENY != attrs.iEdgeTraversal ? VARIANT_TRUE : VARIANT_FALSE);
827
+ ExitOnFailure(hr, "failed to set exception edge traversal");
828
+ break;
829
350
-/******************************************************************
351
- AddApplicationException
830
+ // handled by put_EdgeTraversalOptions
831
+ case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP:
832
+ case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER:
833
+ break;
834
+ }
835
+ }
836
+ else if (fUpdateRule)
837
+ {
838
+ hr = pNetFwRule->put_EdgeTraversal(VARIANT_FALSE);
839
+ ExitOnFailure(hr, "failed to remove exception edge traversal");
840
+ }
841
353
-********************************************************************/
354
-static HRESULT AddApplicationException(
355
- __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
356
- __in BOOL fIgnoreFailures
357
- )
358
-{
359
- HRESULT hr = S_OK;
360
- BSTR bstrFile = NULL;
361
- BSTR bstrName = NULL;
362
- INetFwRules* pNetFwRules = NULL;
363
- INetFwRule* pNetFwRule = NULL;
842
+ // enable even when iEnabled == MSI_NULL_INTEGER
843
+ hr = pNetFwRule->put_Enabled(attrs.iEnabled ? VARIANT_TRUE : VARIANT_FALSE);
844
+ ExitOnFailure(hr, "failed to set exception enabled flag");
845
365
- // convert to BSTRs to make COM happy
366
- bstrFile = ::SysAllocString(attrs.pwzProgram);
367
- ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
368
- bstrName = ::SysAllocString(attrs.pwzName);
369
- ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
846
+ if (bstrGrouping && *bstrGrouping)
847
+ {
848
+ hr = pNetFwRule->put_Grouping(bstrGrouping);
849
+ ExitOnFailure(hr, "failed to set exception grouping '%ls'", bstrGrouping);
850
+ }
851
+ else if (fUpdateRule)
852
+ {
853
+ hr = pNetFwRule->put_Grouping(bstrEmpty);
854
+ ExitOnFailure(hr, "failed to remove exception grouping");
855
+ }
856
371
- // get the collection of firewall rules
372
- hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
373
- ExitOnFailure(hr, "failed to get firewall rules object");
374
- if (S_FALSE == hr) // user or package author chose to ignore missing firewall
857
+ if (bstrIcmpTypesAndCodes && *bstrIcmpTypesAndCodes)
858
{
376
- ExitFunction();
859
+ hr = pNetFwRule->put_IcmpTypesAndCodes(bstrIcmpTypesAndCodes);
860
+ ExitOnFailure(hr, "failed to set exception icmp types and codes '%ls'", bstrIcmpTypesAndCodes);
861
}
862
379
- // try to find it (i.e., support reinstall)
380
- hr = pNetFwRules->Item(bstrName, &pNetFwRule);
381
- if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
863
+ hr = GetFwRuleInterfaces(attrs, vInterfaces);
864
+ ExitOnFailure(hr, "failed to prepare exception interfaces '%ls'", attrs.pwzInterfaces);
865
+
866
+ if (attrs.pwzInterfaces && *attrs.pwzInterfaces)
867
{
383
- hr = CreateFwRuleObject(bstrName, attrs, &pNetFwRule);
384
- ExitOnFailure(hr, "failed to create FwRule object");
868
+ hr = pNetFwRule->put_Interfaces(vInterfaces);
869
+ ExitOnFailure(hr, "failed to set exception interfaces '%ls'", attrs.pwzInterfaces);
870
+ }
871
+ else if (fUpdateRule)
872
+ {
873
+ hr = pNetFwRule->put_Interfaces(vInterfaces);
874
+ ExitOnFailure(hr, "failed to remove exception interfaces");
875
+ }
876
386
- // set edge traversal to true
387
- hr = pNetFwRule->put_EdgeTraversal(VARIANT_TRUE);
388
- ExitOnFailure(hr, "failed to set application exception edgetraversal property");
389
-
390
- // set path
391
- hr = pNetFwRule->put_ApplicationName(bstrFile);
392
- ExitOnFailure(hr, "failed to set application name");
393
-
394
- // enable it
395
- hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
396
- ExitOnFailure(hr, "failed to to enable application exception");
397
-
398
- // add it to the list of authorized apps
399
- hr = pNetFwRules->Add(pNetFwRule);
400
- ExitOnFailure(hr, "failed to add app to the authorized apps list");
877
+ if (bstrInterfaceTypes && *bstrInterfaceTypes)
878
+ {
879
+ hr = pNetFwRule->put_InterfaceTypes(bstrInterfaceTypes);
880
+ ExitOnFailure(hr, "failed to set exception interface types '%ls'", bstrInterfaceTypes);
881
}
402
- else
882
+ else if (fUpdateRule)
883
{
404
- // we found an existing app exception (if we succeeded, that is)
405
- ExitOnFailure(hr, "failed trying to find existing app");
406
-
407
- // enable it (just in case it was disabled)
408
- pNetFwRule->put_Enabled(VARIANT_TRUE);
884
+ hr = pNetFwRule->put_InterfaceTypes(bstrEmpty);
885
+ ExitOnFailure(hr, "failed to remove exception interface types");
886
+ }
887
+
888
+ if (bstrLocalAddresses && *bstrLocalAddresses)
889
+ {
890
+ hr = pNetFwRule->put_LocalAddresses(bstrLocalAddresses);
891
+ ExitOnFailure(hr, "failed to set exception local addresses '%ls'", bstrLocalAddresses);
892
+ }
893
+ else if (fUpdateRule)
894
+ {
895
+ hr = pNetFwRule->put_LocalAddresses(bstrEmpty);
896
+ ExitOnFailure(hr, "failed to remove exception local addresses");
897
+ }
898
+
899
+ if (bstrRemotePort && *bstrRemotePort)
900
+ {
901
+ hr = pNetFwRule->put_RemotePorts(bstrRemotePort);
902
+ ExitOnFailure(hr, "failed to set exception remote ports '%ls'", bstrRemotePort);
903
+ }
904
+
905
+ if (bstrServiceName && *bstrServiceName)
906
+ {
907
+ hr = pNetFwRule->put_ServiceName(bstrServiceName);
908
+ ExitOnFailure(hr, "failed to set exception service name '%ls'", bstrServiceName);
909
+ }
910
+ else if (fUpdateRule)
911
+ {
912
+ hr = pNetFwRule->put_ServiceName(NULL);
913
+ ExitOnFailure(hr, "failed to remove exception service name");
914
}
915
916
LExit:
412
- ReleaseBSTR(bstrName);
917
+ ReleaseBSTR(bstrRemoteAddresses);
918
ReleaseBSTR(bstrFile);
414
- ReleaseObject(pNetFwRules);
415
- ReleaseObject(pNetFwRule);
919
+ ReleaseBSTR(bstrPort);
920
+ ReleaseBSTR(bstrDescription);
921
+ ReleaseBSTR(bstrGrouping);
922
+ ReleaseBSTR(bstrIcmpTypesAndCodes);
923
+ ReleaseBSTR(bstrInterfaceTypes);
924
+ ReleaseBSTR(bstrLocalAddresses);
925
+ ReleaseBSTR(bstrRemotePort);
926
+ ReleaseBSTR(bstrServiceName);
927
+ ReleaseVariant(vInterfaces);
928
+ ReleaseObject(pNetFwRule2);
929
417
- return fIgnoreFailures ? S_OK : hr;
930
+ return hr;
931
}
932
420
-/******************************************************************
421
- AddPortException
933
+
934
+/*******************************************************************
935
+ AddFirewallException
936
937
********************************************************************/
424
-static HRESULT AddPortException(
938
+static HRESULT AddFirewallException(
939
__in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
940
__in BOOL fIgnoreFailures
427
- )
941
+)
942
{
943
HRESULT hr = S_OK;
944
BSTR bstrName = NULL;
945
INetFwRules* pNetFwRules = NULL;
946
INetFwRule* pNetFwRule = NULL;
947
948
+ BOOL fIgnoreUpdates = feaIgnoreUpdates == (attrs.iAttributes & feaIgnoreUpdates);
949
+ BOOL fEnableOnUpdate = feaEnableOnUpdate == (attrs.iAttributes & feaEnableOnUpdate);
950
+ BOOL fAddINetFwRule2 = feaAddINetFwRule2 == (attrs.iAttributes & feaAddINetFwRule2);
951
+ BOOL fAddINetFwRule3 = feaAddINetFwRule3 == (attrs.iAttributes & feaAddINetFwRule3);
952
+
953
// convert to BSTRs to make COM happy
954
bstrName = ::SysAllocString(attrs.pwzName);
955
ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
956
957
// get the collection of firewall rules
958
hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
440
- ExitOnFailure(hr, "failed to get firewall rules object");
959
+ ExitOnFailure(hr, "failed to get firewall exception object");
960
if (S_FALSE == hr) // user or package author chose to ignore missing firewall
961
{
962
ExitFunction();
@@ -447,24 +966,56 @@ static HRESULT AddPortException(
966
hr = pNetFwRules->Item(bstrName, &pNetFwRule);
967
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
968
{
450
- hr = CreateFwRuleObject(bstrName, attrs, &pNetFwRule);
451
- ExitOnFailure(hr, "failed to create FwRule object");
969
+ hr = CreateFwRuleObject(bstrName, &pNetFwRule);
970
+ ExitOnFailure(hr, "failed to create FwRule object '%ls'", attrs.pwzName);
971
453
- // enable it
454
- hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
455
- ExitOnFailure(hr, "failed to to enable port exception");
972
+ // set attributes of the new firewall rule
973
+ hr = UpdateFwRuleObject(pNetFwRule, FALSE, attrs);
974
+ ExitOnFailure(hr, "failed to create INetFwRule firewall exception '%ls'", attrs.pwzName);
975
+
976
+ if (fAddINetFwRule2)
977
+ {
978
+ hr = UpdateFwRule2Object(pNetFwRule, FALSE, attrs);
979
+ ExitOnFailure(hr, "failed to create INetFwRule2 firewall exception '%ls'", attrs.pwzName);
980
+ }
981
+
982
+ if (fAddINetFwRule3)
983
+ {
984
+ hr = UpdateFwRule3Object(pNetFwRule, FALSE, attrs);
985
+ ExitOnFailure(hr, "failed to create INetFwRule3 firewall exception '%ls'", attrs.pwzName);
986
+ }
987
457
- // add it to the list of authorized ports
988
hr = pNetFwRules->Add(pNetFwRule);
459
- ExitOnFailure(hr, "failed to add app to the authorized ports list");
989
+ ExitOnFailure(hr, "failed to add firewall exception '%ls' to the list", attrs.pwzName);
990
}
991
else
992
{
463
- // we found an existing port exception (if we succeeded, that is)
464
- ExitOnFailure(hr, "failed trying to find existing port rule");
993
+ // we found an existing firewall rule (if we succeeded, that is)
994
+ ExitOnFailure(hr, "failed trying to find existing firewall exception '%ls'", attrs.pwzName);
995
+
996
+ if (fEnableOnUpdate)
997
+ {
998
+ hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
999
+ ExitOnFailure(hr, "failed to enable existing firewall exception '%ls'", attrs.pwzName);
1000
+ }
1001
+ else if (!fIgnoreUpdates)
1002
+ {
1003
+ // overwrite attributes of the existing firewall rule
1004
+ hr = UpdateFwRuleObject(pNetFwRule, TRUE, attrs);
1005
+ ExitOnFailure(hr, "failed to update INetFwRule firewall exception '%ls'", attrs.pwzName);
1006
466
- // enable it (just in case it was disabled)
467
- pNetFwRule->put_Enabled(VARIANT_TRUE);
1007
+ if (fAddINetFwRule2)
1008
+ {
1009
+ hr = UpdateFwRule2Object(pNetFwRule, TRUE, attrs);
1010
+ ExitOnFailure(hr, "failed to update INetFwRule2 firewall exception '%ls'", attrs.pwzName);
1011
+ }
1012
+
1013
+ if (fAddINetFwRule3)
1014
+ {
1015
+ hr = UpdateFwRule3Object(pNetFwRule, TRUE, attrs);
1016
+ ExitOnFailure(hr, "failed to update INetFwRule3 firewall exception '%ls'", attrs.pwzName);
1017
+ }
1018
+ }
1019
}
1020
1021
LExit:
@@ -475,14 +1026,15 @@ LExit:
1026
return fIgnoreFailures ? S_OK : hr;
1027
}
1028
478
-/******************************************************************
1029
+
1030
+/*******************************************************************
1031
RemoveException - Removes all exception rules with the given name.
1032
1033
********************************************************************/
1034
static HRESULT RemoveException(
1035
__in LPCWSTR wzName,
1036
__in BOOL fIgnoreFailures
485
- )
1037
+)
1038
{
1039
HRESULT hr = S_OK;;
1040
INetFwRules* pNetFwRules = NULL;
@@ -500,7 +1052,7 @@ static HRESULT RemoveException(
1052
}
1053
1054
hr = pNetFwRules->Remove(bstrName);
503
- ExitOnFailure(hr, "failed to remove firewall rule");
1055
+ ExitOnFailure(hr, "failed to remove firewall exception for name %ls", wzName);
1056
1057
LExit:
1058
ReleaseBSTR(bstrName);
@@ -509,20 +1061,20 @@ LExit:
1061
return fIgnoreFailures ? S_OK : hr;
1062
}
1063
512
-/******************************************************************
513
- ExecFirewallExceptions - deferred custom action entry point to
1064
+
1065
+/*******************************************************************
1066
+ ExecFirewallExceptions - deferred custom action entry point to
1067
register and remove firewall exceptions.
1068
1069
********************************************************************/
1070
extern "C" UINT __stdcall ExecFirewallExceptions(
1071
__in MSIHANDLE hInstall
519
- )
1072
+)
1073
{
1074
HRESULT hr = S_OK;
1075
LPWSTR pwz = NULL;
1076
LPWSTR pwzCustomActionData = NULL;
1077
int iTodo = WCA_TODO_UNKNOWN;
525
- int iTarget = fetUnknown;
1078
1079
FIREWALL_EXCEPTION_ATTRIBUTES attrs = { 0 };
1080
@@ -530,7 +1082,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1082
hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
1083
ExitOnFailure(hr, "failed to initialize");
1084
533
- hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
1085
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
1086
ExitOnFailure(hr, "failed to get CustomActionData");
1087
WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);
1088
@@ -569,60 +1121,82 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1121
ExitOnFailure(hr, "failed to read attributes from custom action data");
1122
BOOL fIgnoreFailures = feaIgnoreFailures == (attrs.iAttributes & feaIgnoreFailures);
1123
572
- hr = WcaReadIntegerFromCaData(&pwz, &iTarget);
573
- ExitOnFailure(hr, "failed to read target from custom action data");
1124
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzApplicationName);
1125
+ ExitOnFailure(hr, "failed to read file path from custom action data");
1126
575
- if (iTarget == fetApplication)
576
- {
577
- hr = WcaReadStringFromCaData(&pwz, &attrs.pwzProgram);
578
- ExitOnFailure(hr, "failed to read file path from custom action data");
579
- }
580
-
581
- hr = WcaReadStringFromCaData(&pwz, &attrs.pwzPort);
1127
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalPorts);
1128
ExitOnFailure(hr, "failed to read port from custom action data");
1129
+
1130
hr = WcaReadIntegerFromCaData(&pwz, &attrs.iProtocol);
1131
ExitOnFailure(hr, "failed to read protocol from custom action data");
1132
+
1133
hr = WcaReadStringFromCaData(&pwz, &attrs.pwzDescription);
1134
ExitOnFailure(hr, "failed to read protocol from custom action data");
1135
+
1136
hr = WcaReadIntegerFromCaData(&pwz, &attrs.iDirection);
1137
ExitOnFailure(hr, "failed to read direction from custom action data");
1138
590
- switch (iTarget)
591
- {
592
- case fetPort:
593
- switch (iTodo)
594
- {
595
- case WCA_TODO_INSTALL:
596
- case WCA_TODO_REINSTALL:
597
- WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
598
- hr = AddPortException(attrs, fIgnoreFailures);
599
- ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
600
- break;
1139
+ hr = WcaReadIntegerFromCaData(&pwz, &attrs.iAction);
1140
+ ExitOnFailure(hr, "failed to read action from custom action data");
1141
602
- case WCA_TODO_UNINSTALL:
603
- WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
604
- hr = RemoveException(attrs.pwzName, fIgnoreFailures);
605
- ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
606
- break;
607
- }
608
- break;
1142
+ hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEdgeTraversal);
1143
+ ExitOnFailure(hr, "failed to read edge traversal from custom action data");
1144
610
- case fetApplication:
611
- switch (iTodo)
612
- {
613
- case WCA_TODO_INSTALL:
614
- case WCA_TODO_REINSTALL:
615
- WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls (%ls)", attrs.pwzName, attrs.pwzProgram);
616
- hr = AddApplicationException(attrs, fIgnoreFailures);
617
- ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", attrs.pwzName, attrs.pwzProgram);
618
- break;
1145
+ hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEnabled);
1146
+ ExitOnFailure(hr, "failed to read enabled flag from custom action data");
1147
620
- case WCA_TODO_UNINSTALL:
621
- WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls (%ls)", attrs.pwzName, attrs.pwzProgram);
622
- hr = RemoveException(attrs.pwzName, fIgnoreFailures);
623
- ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", attrs.pwzName, attrs.pwzProgram);
624
- break;
625
- }
1148
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzGrouping);
1149
+ ExitOnFailure(hr, "failed to read grouping from custom action data");
1150
+
1151
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzIcmpTypesAndCodes);
1152
+ ExitOnFailure(hr, "failed to read icmp types and codes from custom action data");
1153
+
1154
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaces);
1155
+ ExitOnFailure(hr, "failed to read interfaces from custom action data");
1156
+
1157
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaceTypes);
1158
+ ExitOnFailure(hr, "failed to read interface types from custom action data");
1159
+
1160
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAddresses);
1161
+ ExitOnFailure(hr, "failed to read local addresses from custom action data");
1162
+
1163
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemotePorts);
1164
+ ExitOnFailure(hr, "failed to read remote port from custom action data");
1165
+
1166
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzServiceName);
1167
+ ExitOnFailure(hr, "failed to read service name from custom action data");
1168
+
1169
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAppPackageId);
1170
+ ExitOnFailure(hr, "failed to read local app package id from custom action data");
1171
+
1172
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserAuthorizedList);
1173
+ ExitOnFailure(hr, "failed to read local user authorized list from custom action data");
1174
+
1175
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserOwner);
1176
+ ExitOnFailure(hr, "failed to read local user owner from custom action data");
1177
+
1178
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteMachineAuthorizedList);
1179
+ ExitOnFailure(hr, "failed to read remote machine authorized list from custom action data");
1180
+
1181
+ hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteUserAuthorizedList);
1182
+ ExitOnFailure(hr, "failed to read remote user authorized list from custom action data");
1183
+
1184
+ hr = WcaReadIntegerFromCaData(&pwz, &attrs.iSecureFlags);
1185
+ ExitOnFailure(hr, "failed to read exception secure flags from custom action data");
1186
+
1187
+ switch (iTodo)
1188
+ {
1189
+ case WCA_TODO_INSTALL:
1190
+ case WCA_TODO_REINSTALL:
1191
+ WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls", attrs.pwzName);
1192
+ hr = AddFirewallException(attrs, fIgnoreFailures);
1193
+ ExitOnFailure(hr, "failed to add/update firewall exception for name '%ls'", attrs.pwzName);
1194
+ break;
1195
+
1196
+ case WCA_TODO_UNINSTALL:
1197
+ WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls", attrs.pwzName);
1198
+ hr = RemoveException(attrs.pwzName, fIgnoreFailures);
1199
+ ExitOnFailure(hr, "failed to remove firewall exception");
1200
break;
1201
}
1202
}
@@ -631,9 +1205,21 @@ LExit:
1205
ReleaseStr(pwzCustomActionData);
1206
ReleaseStr(attrs.pwzName);
1207
ReleaseStr(attrs.pwzRemoteAddresses);
634
- ReleaseStr(attrs.pwzProgram);
635
- ReleaseStr(attrs.pwzPort);
1208
+ ReleaseStr(attrs.pwzApplicationName);
1209
+ ReleaseStr(attrs.pwzLocalPorts);
1210
ReleaseStr(attrs.pwzDescription);
1211
+ ReleaseStr(attrs.pwzGrouping);
1212
+ ReleaseStr(attrs.pwzIcmpTypesAndCodes);
1213
+ ReleaseStr(attrs.pwzInterfaces);
1214
+ ReleaseStr(attrs.pwzInterfaceTypes);
1215
+ ReleaseStr(attrs.pwzLocalAddresses);
1216
+ ReleaseStr(attrs.pwzRemotePorts);
1217
+ ReleaseStr(attrs.pwzServiceName);
1218
+ ReleaseStr(attrs.pwzLocalAppPackageId);
1219
+ ReleaseStr(attrs.pwzLocalUserAuthorizedList);
1220
+ ReleaseStr(attrs.pwzLocalUserOwner);
1221
+ ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
1222
+ ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
1223
::CoUninitialize();
1224
1225
return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+457
-28
@@ -2,6 +2,7 @@
2
3
namespace WixToolsetTest.Firewall
4
{
5
+ using System.Data;
6
using System.IO;
7
using System.Linq;
8
using System.Xml.Linq;
@@ -27,12 +28,27 @@ namespace WixToolsetTest.Firewall
28
"CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
29
"CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
30
"CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
30
- "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
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",
31
+ "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t2\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
32
+ "Wix5FirewallException:fex.BGtyMRGAhxb2hG.49JvWYz7fM0\tLocalScopeExample2\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with local scope property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t[LOCALSCOPE_PROP]\t\t\t\t\t\t\t\t-2147483648",
33
+ "Wix5FirewallException:fex0HTxATWjpC2PCoY6DB7f2D1WaKU\tLocalScopeExample1\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with local scope\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tLocalSubnet\t\t\t\t\t\t\t\t-2147483648",
34
+ "Wix5FirewallException:fex4FeP470wYcFpw.g7fbIKiLnZPzg\tExampleDNSScope\tdns\t356\t17\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
35
+ "Wix5FirewallException:fex4zTcT0Iwu3dUtHIHXD5qfymvpcM\tdefertouser\t\t\t-2147483648\tfw.exe\t8\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDefer to user edge traversal\t1\t-2147483648\t3\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
36
+ "Wix5FirewallException:fex8vMfBplrod4daEz3PqDTeX6olGE\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
37
+ "Wix5FirewallException:fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug\tINetFwRule3 properties\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tINetFwRule3 passed via properties\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t[PROP1]\t[PROP2]\t[PROP3]\t[PROP4]\t[PROP5]\t[PROP6]",
38
+ "Wix5FirewallException:fexArlOkFR7CAwVZ2wk8yNdiREydu0\tRemotePortExample2\t\t\t6\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with remote port property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t[REMOTEPORT_PROP]\t\t\t\t\t\t\t-2147483648",
39
+ "Wix5FirewallException:fexaUTe2tRRcSYrPUTn44DAZhE.40Q\tExamplePort\tLocalSubnet\t42\t6\t\t4\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
40
+ "Wix5FirewallException:fexD6w20c5HfNi4l1vHFj_eet4cC8I\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
41
+ "Wix5FirewallException:fexeD3yox6fMflfRy7sDwSN2CMCS2s\tExampleService\t\t12000\t6\t%windir%\\system32\\svchost.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based service exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tDHCP,WINS\t\tftpsrv\t\t\t\t\t\t-2147483648",
42
+ "Wix5FirewallException:fexeok6aI2_AlclZggec4d8PBLFXLw\tinterface property\t\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE_PROPERTY]\t\t\t\t\t\t\t\t\t\t-2147483648",
43
+ "Wix5FirewallException:fexEPvcf4iexD1mVQdvxm7tD02nZEc\tICMPExample1\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple ICMP rule\t1\t-2147483648\t-2147483648\t-2147483648\t\t4:*,9:*,12:*\t\t\t\t\t\t\t\t\t\t\t-2147483648",
44
+ "Wix5FirewallException:fexfzjTQsWwZkHQpObtl0XaUosfcRk\tGroupingExample1\t\t\t-2147483648\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with grouping\t1\t-2147483648\t-2147483648\t-2147483648\t@yourresources.dll,-1005\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
45
+ "Wix5FirewallException:fexHx2xbwZYzAi0oYp4YGWevJQs5eM\tRemotePortExample1\t*\t\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with remote port\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t34560\t\t\t\t\t\t\t-2147483648",
46
+ "Wix5FirewallException:fexpWUzK53RVnaluW36gSmphPRY8VY\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
47
+ "Wix5FirewallException:fexuanTga5xaaFzr9JsAnUmpCNediw\tICMPExample2\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with ICMP property\t1\t-2147483648\t-2147483648\t-2147483648\t\t[ICMP_PROP]\t\t\t\t\t\t\t\t\t\t\t-2147483648",
48
+ "Wix5FirewallException:fexv60s7u2Dmd1imH5vEFYKPgEWhG4\tinterface nested\t127.0.0.1\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with nested elements\t1\t-2147483648\t-2147483648\t-2147483648\t\t\tWi-Fi|Local Area Connection\t\t\t\t\t\t\t\t\t\t-2147483648",
49
+ "Wix5FirewallException:fexVr6uHcOCak5MHuTLwujjh_oKtbI\tGroupingExample2\t\t8732\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with grouping property\t1\t-2147483648\t-2147483648\t-2147483648\t[GROUPING_PROP]\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
50
+ "Wix5FirewallException:fexwjf4OTFVE9SNiC4goVxBA6ENJBE\tINetFwRule3 values\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple INetFwRule3 values\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\tS-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\tS-1-5-21-1898747406-2352535518-1247798438-1914\t127.0.0.1\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\t3",
51
+ "Wix5FirewallException:ServiceInstall.nested\tExampleNestedService\tLocalSubnet\t3546-7890\t6\t\t1\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception for a windows service\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\tLan,Wireless\t\t\tsvc1\t\t\t\t\t\t-2147483648",
52
}, results);
53
}
54
@@ -51,12 +67,69 @@ namespace WixToolsetTest.Firewall
67
"CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
68
"CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
69
"CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
54
- "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
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",
70
+ "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t2\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
71
+ "Wix5FirewallException:fex.BGtyMRGAhxb2hG.49JvWYz7fM0\tLocalScopeExample2\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with local scope property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t[LOCALSCOPE_PROP]\t\t\t\t\t\t\t\t-2147483648",
72
+ "Wix5FirewallException:fex0HTxATWjpC2PCoY6DB7f2D1WaKU\tLocalScopeExample1\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with local scope\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tLocalSubnet\t\t\t\t\t\t\t\t-2147483648",
73
+ "Wix5FirewallException:fex4FeP470wYcFpw.g7fbIKiLnZPzg\tExampleDNSScope\tdns\t356\t17\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
74
+ "Wix5FirewallException:fex4zTcT0Iwu3dUtHIHXD5qfymvpcM\tdefertouser\t\t\t-2147483648\tfw.exe\t8\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDefer to user edge traversal\t1\t-2147483648\t3\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
75
+ "Wix5FirewallException:fex8vMfBplrod4daEz3PqDTeX6olGE\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
76
+ "Wix5FirewallException:fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug\tINetFwRule3 properties\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tINetFwRule3 passed via properties\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t[PROP1]\t[PROP2]\t[PROP3]\t[PROP4]\t[PROP5]\t[PROP6]",
77
+ "Wix5FirewallException:fexArlOkFR7CAwVZ2wk8yNdiREydu0\tRemotePortExample2\t\t\t6\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with remote port property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t[REMOTEPORT_PROP]\t\t\t\t\t\t\t-2147483648",
78
+ "Wix5FirewallException:fexaUTe2tRRcSYrPUTn44DAZhE.40Q\tExamplePort\tLocalSubnet\t42\t6\t\t4\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
79
+ "Wix5FirewallException:fexD6w20c5HfNi4l1vHFj_eet4cC8I\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
80
+ "Wix5FirewallException:fexeD3yox6fMflfRy7sDwSN2CMCS2s\tExampleService\t\t12000\t6\t%windir%\\system32\\svchost.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based service exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tDHCP,WINS\t\tftpsrv\t\t\t\t\t\t-2147483648",
81
+ "Wix5FirewallException:fexeok6aI2_AlclZggec4d8PBLFXLw\tinterface property\t\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE_PROPERTY]\t\t\t\t\t\t\t\t\t\t-2147483648",
82
+ "Wix5FirewallException:fexEPvcf4iexD1mVQdvxm7tD02nZEc\tICMPExample1\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple ICMP rule\t1\t-2147483648\t-2147483648\t-2147483648\t\t4:*,9:*,12:*\t\t\t\t\t\t\t\t\t\t\t-2147483648",
83
+ "Wix5FirewallException:fexfzjTQsWwZkHQpObtl0XaUosfcRk\tGroupingExample1\t\t\t-2147483648\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with grouping\t1\t-2147483648\t-2147483648\t-2147483648\t@yourresources.dll,-1005\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
84
+ "Wix5FirewallException:fexHx2xbwZYzAi0oYp4YGWevJQs5eM\tRemotePortExample1\t*\t\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with remote port\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t34560\t\t\t\t\t\t\t-2147483648",
85
+ "Wix5FirewallException:fexpWUzK53RVnaluW36gSmphPRY8VY\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
86
+ "Wix5FirewallException:fexuanTga5xaaFzr9JsAnUmpCNediw\tICMPExample2\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with ICMP property\t1\t-2147483648\t-2147483648\t-2147483648\t\t[ICMP_PROP]\t\t\t\t\t\t\t\t\t\t\t-2147483648",
87
+ "Wix5FirewallException:fexv60s7u2Dmd1imH5vEFYKPgEWhG4\tinterface nested\t127.0.0.1\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with nested elements\t1\t-2147483648\t-2147483648\t-2147483648\t\t\tWi-Fi|Local Area Connection\t\t\t\t\t\t\t\t\t\t-2147483648",
88
+ "Wix5FirewallException:fexVr6uHcOCak5MHuTLwujjh_oKtbI\tGroupingExample2\t\t8732\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with grouping property\t1\t-2147483648\t-2147483648\t-2147483648\t[GROUPING_PROP]\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
89
+ "Wix5FirewallException:fexwjf4OTFVE9SNiC4goVxBA6ENJBE\tINetFwRule3 values\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple INetFwRule3 values\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\tS-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\tS-1-5-21-1898747406-2352535518-1247798438-1914\t127.0.0.1\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\t3",
90
+ "Wix5FirewallException:ServiceInstall.nested\tExampleNestedService\tLocalSubnet\t3546-7890\t6\t\t1\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception for a windows service\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\tLan,Wireless\t\t\tsvc1\t\t\t\t\t\t-2147483648",
91
+ }, results);
92
+ }
93
+
94
+ [Fact]
95
+ public void CanBuildWithProperties()
96
+ {
97
+ var folder = TestData.Get(@"TestData\UsingProperties");
98
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
99
+
100
+ var results = build.BuildAndQuery(Build, "Wix5FirewallException", "CustomAction");
101
+ WixAssert.CompareLineByLine(new[]
102
+ {
103
+ "CustomAction:Wix5ExecFirewallExceptionsInstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
104
+ "CustomAction:Wix5ExecFirewallExceptionsUninstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
105
+ "CustomAction:Wix5RollbackFirewallExceptionsInstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
106
+ "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
107
+ "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
108
+ "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
109
+ "Wix5FirewallException:fexRrE4bS.DwUJQMvzX0ALEsx7jrZs\tSingle Nested properties\t[REMOTEADDRESS]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALADDRESS]\t\t\t\t\t\t\t\t-2147483648",
110
+ "Wix5FirewallException:fexvEy1GfdOjHlKcvsguyqK6mvYKyk\t[NAME]\t[REMOTESCOPE]\t[LOCALPORT]\t[PROTOCOL]\t[PROGRAM]\t16\t[PROFILE]\tFirewallComponent\t[DESCRIPTION]\t1\t[ACTION]\t[EDGETRAVERSAL]\t[ENABLED]\t[GROUPING]\t[ICMPTYPES]\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALSCOPE]\t[REMOTEPORT]\t[SERVICE]\t[PACKAGEID]\t[LOCALUSERS]\t[LOCALOWNER]\t[REMOTEMACHINES]\t[REMOTEUSERS]\t[SECUREFLAGS]",
111
+ "Wix5FirewallException:fexWywW3VGiEuG23FOv1YM6h7R6F5Q\tMultiple Nested properties\t[REMOTEADDRESS1],[REMOTEADDRESS2]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE1]|[INTERFACE2]\t[INTERFACETYPE1],[INTERFACETYPE2]\t[LOCALADDRESS1],[LOCALADDRESS2]\t\t\t\t\t\t\t\t-2147483648",
112
+ }, results);
113
+ }
114
+
115
+ [Fact]
116
+ public void CanBuildWithPropertiesUsingFirewallARM64()
117
+ {
118
+ var folder = TestData.Get(@"TestData\UsingProperties");
119
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
120
+
121
+ var results = build.BuildAndQuery(BuildARM64, "Wix5FirewallException", "CustomAction");
122
+ WixAssert.CompareLineByLine(new[]
123
+ {
124
+ "CustomAction:Wix5ExecFirewallExceptionsInstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
125
+ "CustomAction:Wix5ExecFirewallExceptionsUninstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
126
+ "CustomAction:Wix5RollbackFirewallExceptionsInstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
127
+ "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
128
+ "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
129
+ "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
130
+ "Wix5FirewallException:fexRrE4bS.DwUJQMvzX0ALEsx7jrZs\tSingle Nested properties\t[REMOTEADDRESS]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALADDRESS]\t\t\t\t\t\t\t\t-2147483648",
131
+ "Wix5FirewallException:fexvEy1GfdOjHlKcvsguyqK6mvYKyk\t[NAME]\t[REMOTESCOPE]\t[LOCALPORT]\t[PROTOCOL]\t[PROGRAM]\t16\t[PROFILE]\tFirewallComponent\t[DESCRIPTION]\t1\t[ACTION]\t[EDGETRAVERSAL]\t[ENABLED]\t[GROUPING]\t[ICMPTYPES]\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALSCOPE]\t[REMOTEPORT]\t[SERVICE]\t[PACKAGEID]\t[LOCALUSERS]\t[LOCALOWNER]\t[REMOTEMACHINES]\t[REMOTEUSERS]\t[SECUREFLAGS]",
132
+ "Wix5FirewallException:fexWywW3VGiEuG23FOv1YM6h7R6F5Q\tMultiple Nested properties\t[REMOTEADDRESS1],[REMOTEADDRESS2]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE1]|[INTERFACE2]\t[INTERFACETYPE1],[INTERFACETYPE2]\t[LOCALADDRESS1],[LOCALADDRESS2]\t\t\t\t\t\t\t\t-2147483648",
133
}, results);
134
}
135
@@ -83,6 +156,59 @@ namespace WixToolsetTest.Firewall
156
"FirewallException",
157
"FirewallException",
158
"FirewallException",
159
+ "FirewallException",
160
+ "FirewallException",
161
+ "LocalAddress",
162
+ "LocalAddress",
163
+ "FirewallException",
164
+ "RemoteAddress",
165
+ "Interface",
166
+ "Interface",
167
+ "FirewallException",
168
+ "FirewallException",
169
+ "InterfaceType",
170
+ "InterfaceType",
171
+ "FirewallException",
172
+ "FirewallException",
173
+ "FirewallException",
174
+ "FirewallException",
175
+ "FirewallException",
176
+ "FirewallException",
177
+ "FirewallException",
178
+ "FirewallException",
179
+ "FirewallException",
180
+ "FirewallException",
181
+ }, actual.Select(a => a.Name).ToArray());
182
+ }
183
+
184
+ [Fact]
185
+ public void CanRoundtripFirewallExceptionsWithProperties()
186
+ {
187
+ var folder = TestData.Get(@"TestData", "UsingProperties");
188
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
189
+ var output = Path.Combine(folder, "FirewallPropertiesDecompile.xml");
190
+
191
+ build.BuildAndDecompileAndBuild(Build, Decompile, output);
192
+
193
+ var doc = XDocument.Load(output);
194
+ var actual = doc.Descendants()
195
+ .Where(e => e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall")
196
+ .Select(fe => new { Name = fe.Name.LocalName, Attributes = fe.Attributes().Select(a => $"{a.Name.LocalName}={a.Value}").ToArray() })
197
+ .ToArray();
198
+
199
+ WixAssert.CompareLineByLine(new[]
200
+ {
201
+ "FirewallException",
202
+ "FirewallException",
203
+ "FirewallException",
204
+ "RemoteAddress",
205
+ "RemoteAddress",
206
+ "Interface",
207
+ "Interface",
208
+ "InterfaceType",
209
+ "InterfaceType",
210
+ "LocalAddress",
211
+ "LocalAddress",
212
}, actual.Select(a => a.Name).ToArray());
213
}
214
@@ -98,9 +224,8 @@ namespace WixToolsetTest.Firewall
224
"Port=42",
225
"Protocol=tcp",
226
"Program=[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]",
101
- "Profile=all",
227
+ "OnUpdate=DoNothing",
228
"Description=An app-based firewall exception",
103
- "Outbound=no",
229
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
230
}, actual.Attributes);
231
}
@@ -111,12 +236,12 @@ namespace WixToolsetTest.Firewall
236
var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort");
237
WixAssert.CompareLineByLine(new[]
238
{
114
- "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs",
239
+ "Id=fexaUTe2tRRcSYrPUTn44DAZhE.40Q",
240
"Name=ExamplePort",
241
"Scope=localSubnet",
242
"Port=42",
243
"Protocol=tcp",
119
- "Profile=all",
244
+ "OnUpdate=EnableOnly",
245
"Description=A port-based firewall exception",
246
"Outbound=yes",
247
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
@@ -129,14 +254,12 @@ namespace WixToolsetTest.Firewall
254
var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope");
255
WixAssert.CompareLineByLine(new[]
256
{
132
- "Id=fexxY71H2ZBkPalv7uid1Yy4qaA_lA",
257
+ "Id=fex4FeP470wYcFpw.g7fbIKiLnZPzg",
258
"Name=ExampleDNSScope",
259
"Scope=DNS",
260
"Port=356",
261
"Protocol=udp",
137
- "Profile=all",
262
"Description=DNS scope firewall exception",
139
- "Outbound=no",
263
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
264
}, actual.Attributes);
265
}
@@ -147,14 +270,13 @@ namespace WixToolsetTest.Firewall
270
var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope");
271
WixAssert.CompareLineByLine(new[]
272
{
150
- "Id=fex6bkfWwpiRGI.wVFx0T7W4LXIHxU",
273
+ "Id=fexpWUzK53RVnaluW36gSmphPRY8VY",
274
"Name=ExampleDHCPScope",
275
"Scope=DHCP",
276
"Protocol=211",
277
"Program=test.exe",
278
"Profile=public",
279
"Description=DHCP scope firewall exception",
157
- "Outbound=no",
280
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
281
}, actual.Attributes);
282
}
@@ -165,14 +287,13 @@ namespace WixToolsetTest.Firewall
287
var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope");
288
WixAssert.CompareLineByLine(new[]
289
{
168
- "Id=fexXxaXCXXFh.UxO_BjmZxi1B1du_Q",
290
+ "Id=fexD6w20c5HfNi4l1vHFj_eet4cC8I",
291
"Name=ExampleWINSScope",
292
"Scope=WINS",
293
"Port=6573",
294
"Protocol=tcp",
295
"Profile=domain",
296
"Description=WINS scope firewall exception",
175
- "Outbound=no",
297
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
298
}, actual.Attributes);
299
}
@@ -183,18 +304,322 @@ namespace WixToolsetTest.Firewall
304
var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope");
305
WixAssert.CompareLineByLine(new[]
306
{
186
- "Id=fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8",
307
+ "Id=fex8vMfBplrod4daEz3PqDTeX6olGE",
308
"Name=ExampleDefaultGatewayScope",
309
"Scope=defaultGateway",
310
"Port=4432",
311
"Protocol=tcp",
312
"Profile=private",
313
"Description=defaultGateway scope firewall exception",
193
- "Outbound=no",
314
"xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
315
}, actual.Attributes);
316
}
317
318
+ [Fact]
319
+ public void RoundtripAttributesAreCorrectForINetFwRule3Values()
320
+ {
321
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 values");
322
+ WixAssert.CompareLineByLine(new[]
323
+ {
324
+ "Id=fexwjf4OTFVE9SNiC4goVxBA6ENJBE",
325
+ "Name=INetFwRule3 values",
326
+ "Scope=any",
327
+ "Description=Simple INetFwRule3 values",
328
+ "LocalAppPackageId=S-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315",
329
+ "LocalUserAuthorizedList=O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)",
330
+ "LocalUserOwner=S-1-5-21-1898747406-2352535518-1247798438-1914",
331
+ "RemoteMachineAuthorizedList=127.0.0.1",
332
+ "RemoteUserAuthorizedList=O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)",
333
+ "IPSecSecureFlags=NegotiateEncryption",
334
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
335
+ }, actual.Attributes);
336
+ }
337
+
338
+ [Fact]
339
+ public void RoundtripAttributesAreCorrectForINetFwRule3Properties()
340
+ {
341
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 properties");
342
+ WixAssert.CompareLineByLine(new[]
343
+ {
344
+ "Id=fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug",
345
+ "Name=INetFwRule3 properties",
346
+ "Scope=any",
347
+ "Description=INetFwRule3 passed via properties",
348
+ "LocalAppPackageId=[PROP1]",
349
+ "LocalUserAuthorizedList=[PROP2]",
350
+ "LocalUserOwner=[PROP3]",
351
+ "RemoteMachineAuthorizedList=[PROP4]",
352
+ "RemoteUserAuthorizedList=[PROP5]",
353
+ "IPSecSecureFlags=[PROP6]",
354
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
355
+ }, actual.Attributes);
356
+ }
357
+
358
+ [Fact]
359
+ public void RoundtripAttributesAreCorrectForGroupingValue()
360
+ {
361
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample1");
362
+ WixAssert.CompareLineByLine(new[]
363
+ {
364
+ "Id=fexfzjTQsWwZkHQpObtl0XaUosfcRk",
365
+ "Name=GroupingExample1",
366
+ "Program=fw.exe",
367
+ "Description=Simple rule with grouping",
368
+ "Grouping=@yourresources.dll,-1005",
369
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
370
+ }, actual.Attributes);
371
+ }
372
+
373
+ [Fact]
374
+ public void RoundtripAttributesAreCorrectForGroupingProperty()
375
+ {
376
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample2");
377
+ WixAssert.CompareLineByLine(new[]
378
+ {
379
+ "Id=fexVr6uHcOCak5MHuTLwujjh_oKtbI",
380
+ "Name=GroupingExample2",
381
+ "Port=8732",
382
+ "Protocol=tcp",
383
+ "Description=Rule with grouping property",
384
+ "Grouping=[GROUPING_PROP]",
385
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
386
+ }, actual.Attributes);
387
+ }
388
+
389
+ [Fact]
390
+ public void RoundtripAttributesAreCorrectForIcmpValue()
391
+ {
392
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample1");
393
+ WixAssert.CompareLineByLine(new[]
394
+ {
395
+ "Id=fexEPvcf4iexD1mVQdvxm7tD02nZEc",
396
+ "Name=ICMPExample1",
397
+ "Protocol=2",
398
+ "Description=Simple ICMP rule",
399
+ "IcmpTypesAndCodes=4:*,9:*,12:*",
400
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
401
+ }, actual.Attributes);
402
+ }
403
+
404
+ [Fact]
405
+ public void RoundtripAttributesAreCorrectForIcmpProperty()
406
+ {
407
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample2");
408
+ WixAssert.CompareLineByLine(new[]
409
+ {
410
+ "Id=fexuanTga5xaaFzr9JsAnUmpCNediw",
411
+ "Name=ICMPExample2",
412
+ "Protocol=2",
413
+ "Description=Rule with ICMP property",
414
+ "IcmpTypesAndCodes=[ICMP_PROP]",
415
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
416
+ }, actual.Attributes);
417
+ }
418
+
419
+ [Fact]
420
+ public void RoundtripAttributesAreCorrectForLocalScopeValue()
421
+ {
422
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample1");
423
+ WixAssert.CompareLineByLine(new[]
424
+ {
425
+ "Id=fex0HTxATWjpC2PCoY6DB7f2D1WaKU",
426
+ "Name=LocalScopeExample1",
427
+ "Scope=any",
428
+ "Description=Simple rule with local scope",
429
+ "LocalScope=localSubnet",
430
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
431
+ }, actual.Attributes);
432
+ }
433
+
434
+ [Fact]
435
+ public void RoundtripAttributesAreCorrectForLocalScopeProperty()
436
+ {
437
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample2");
438
+ WixAssert.CompareLineByLine(new[]
439
+ {
440
+ "Id=fex.BGtyMRGAhxb2hG.49JvWYz7fM0",
441
+ "Name=LocalScopeExample2",
442
+ "Scope=any",
443
+ "Description=Rule with local scope property",
444
+ "LocalScope=[LOCALSCOPE_PROP]",
445
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
446
+ }, actual.Attributes);
447
+ }
448
+
449
+ [Fact]
450
+ public void RoundtripAttributesAreCorrectForRemotePorts()
451
+ {
452
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample1");
453
+ WixAssert.CompareLineByLine(new[]
454
+ {
455
+ "Id=fexHx2xbwZYzAi0oYp4YGWevJQs5eM",
456
+ "Name=RemotePortExample1",
457
+ "Scope=any",
458
+ "Protocol=tcp",
459
+ "Description=Simple rule with remote port",
460
+ "RemotePort=34560",
461
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
462
+ }, actual.Attributes);
463
+ }
464
+
465
+ [Fact]
466
+ public void RoundtripAttributesAreCorrectForRemotePortsProperty()
467
+ {
468
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample2");
469
+ WixAssert.CompareLineByLine(new[]
470
+ {
471
+ "Id=fexArlOkFR7CAwVZ2wk8yNdiREydu0",
472
+ "Name=RemotePortExample2",
473
+ "Protocol=tcp",
474
+ "Program=fw.exe",
475
+ "Description=Rule with remote port property",
476
+ "RemotePort=[REMOTEPORT_PROP]",
477
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
478
+ }, actual.Attributes);
479
+ }
480
+
481
+ [Fact]
482
+ public void RoundtripAttributesAreCorrectWhenPropertiesAreUsed()
483
+ {
484
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "[NAME]", "UsingProperties");
485
+ WixAssert.CompareLineByLine(new[]
486
+ {
487
+ "Id=fexvEy1GfdOjHlKcvsguyqK6mvYKyk",
488
+ "Name=[NAME]",
489
+ "Scope=[REMOTESCOPE]",
490
+ "Port=[LOCALPORT]",
491
+ "Protocol=[PROTOCOL]",
492
+ "Program=[PROGRAM]",
493
+ "Profile=[PROFILE]",
494
+ "Description=[DESCRIPTION]",
495
+ "Action=[ACTION]",
496
+ "EdgeTraversal=[EDGETRAVERSAL]",
497
+ "Enabled=[ENABLED]",
498
+ "Grouping=[GROUPING]",
499
+ "IcmpTypesAndCodes=[ICMPTYPES]",
500
+ "Interface=[INTERFACE]",
501
+ "InterfaceType=[INTERFACETYPE]",
502
+ "LocalScope=[LOCALSCOPE]",
503
+ "RemotePort=[REMOTEPORT]",
504
+ "Service=[SERVICE]",
505
+ "LocalAppPackageId=[PACKAGEID]",
506
+ "LocalUserAuthorizedList=[LOCALUSERS]",
507
+ "LocalUserOwner=[LOCALOWNER]",
508
+ "RemoteMachineAuthorizedList=[REMOTEMACHINES]",
509
+ "RemoteUserAuthorizedList=[REMOTEUSERS]",
510
+ "IPSecSecureFlags=[SECUREFLAGS]",
511
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
512
+ }, actual.Attributes);
513
+
514
+ var folder = TestData.Get(@"TestData", "UsingProperties");
515
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
516
+ var output = Path.Combine(folder, $"FirewallNothingNested.xml");
517
+
518
+ build.BuildAndDecompileAndBuild(Build, Decompile, output);
519
+
520
+ var doc = XDocument.Load(output);
521
+ var related = doc.Descendants()
522
+ .Where(e =>
523
+ {
524
+ return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
525
+ e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "[NAME]");
526
+ });
527
+
528
+ var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
529
+ Assert.False(nested.Any());
530
+ }
531
+
532
+ [Fact]
533
+ public void RoundtripAttributesAreCorrectWhenNestedPropertiesAreUsed()
534
+ {
535
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Single Nested properties", "UsingProperties");
536
+ WixAssert.CompareLineByLine(new[]
537
+ {
538
+ "Id=fexRrE4bS.DwUJQMvzX0ALEsx7jrZs",
539
+ "Name=Single Nested properties",
540
+ "Scope=[REMOTEADDRESS]",
541
+ "Interface=[INTERFACE]",
542
+ "InterfaceType=[INTERFACETYPE]",
543
+ "LocalScope=[LOCALADDRESS]",
544
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
545
+ }, actual.Attributes);
546
+
547
+ var folder = TestData.Get(@"TestData", "UsingProperties");
548
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
549
+ var output = Path.Combine(folder, $"FirewallSingleNested.xml");
550
+
551
+ build.BuildAndDecompileAndBuild(Build, Decompile, output);
552
+
553
+ var doc = XDocument.Load(output);
554
+ var related = doc.Descendants()
555
+ .Where(e =>
556
+ {
557
+ return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
558
+ e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "Single Nested properties");
559
+ });
560
+
561
+ var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
562
+ Assert.False(nested.Any());
563
+ }
564
+
565
+ [Fact]
566
+ public void RoundtripAttributesAreCorrectWhenMultipleNestedPropertiesAreUsed()
567
+ {
568
+ var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Multiple Nested properties", "UsingProperties");
569
+ WixAssert.CompareLineByLine(new[]
570
+ {
571
+ "Id=fexWywW3VGiEuG23FOv1YM6h7R6F5Q",
572
+ "Name=Multiple Nested properties",
573
+ "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
574
+ }, actual.Attributes);
575
+
576
+ var folder = TestData.Get(@"TestData", "UsingProperties");
577
+ var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
578
+ var output = Path.Combine(folder, $"FirewallMultipleNested.xml");
579
+
580
+ build.BuildAndDecompileAndBuild(Build, Decompile, output);
581
+
582
+ var doc = XDocument.Load(output);
583
+ var related = doc.Descendants()
584
+ .Where(e =>
585
+ {
586
+ return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
587
+ e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "Multiple Nested properties");
588
+ });
589
+
590
+ var interfaces = related.Where(e => e.Name.LocalName == "Interface")
591
+ .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
592
+ WixAssert.CompareLineByLine(new[]
593
+ {
594
+ "[INTERFACE1]",
595
+ "[INTERFACE2]",
596
+ }, interfaces.ToArray());
597
+
598
+ var interfaceTypes = related.Where(e => e.Name.LocalName == "InterfaceType")
599
+ .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
600
+ WixAssert.CompareLineByLine(new[]
601
+ {
602
+ "[INTERFACETYPE1]",
603
+ "[INTERFACETYPE2]",
604
+ }, interfaceTypes.ToArray());
605
+
606
+ var remotes = related.Where(e => e.Name.LocalName == "RemoteAddress")
607
+ .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
608
+ WixAssert.CompareLineByLine(new[]
609
+ {
610
+ "[REMOTEADDRESS1]",
611
+ "[REMOTEADDRESS2]",
612
+ }, remotes.ToArray());
613
+
614
+ var locals = related.Where(e => e.Name.LocalName == "LocalAddress")
615
+ .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
616
+ WixAssert.CompareLineByLine(new[]
617
+ {
618
+ "[LOCALADDRESS1]",
619
+ "[LOCALADDRESS2]",
620
+ }, locals.ToArray());
621
+ }
622
+
623
private static void Build(string[] args)
624
{
625
var result = WixRunner.Execute(args);
@@ -216,15 +641,16 @@ namespace WixToolsetTest.Firewall
641
var result = WixRunner.Execute(args);
642
result.AssertSuccess();
643
}
644
+
645
class AttributeVerifier
646
{
647
public string Name { get; set; }
648
public string[] Attributes { get; set; }
649
}
650
225
- private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName)
651
+ private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName, string path = "UsingFirewall")
652
{
227
- var folder = TestData.Get(@"TestData", "UsingFirewall");
653
+ var folder = TestData.Get(@"TestData", path);
654
var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
655
var output = Path.Combine(folder, $"Firewall{ruleName}.xml");
656
@@ -232,7 +658,10 @@ namespace WixToolsetTest.Firewall
658
659
var doc = XDocument.Load(output);
660
var actual = doc.Descendants()
235
- .Where(e => e.Name.Namespace == nameSpace)
661
+ .Where(e =>
662
+ {
663
+ return e.Name.Namespace == nameSpace && e.Name.LocalName == "FirewallException";
664
+ })
665
.Select(fe => new AttributeVerifier
666
{
667
Name = fe.Attributes().Single(a => a.Name.LocalName == "Name").Value,
src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
+37
-2
@@ -6,16 +6,51 @@
6
<Component>
7
<File Name="fw.exe" Source="example.txt">
8
<Shortcut Id="FwShortcut" Directory="INSTALLFOLDER" Name="Firewall" />
9
- <fw:FirewallException Id="ExampleFirewall" Description="An app-based firewall exception" Name="ExampleApp" Port="42">
9
+ <fw:FirewallException Id="ExampleFirewall" Description="An app-based firewall exception" Name="ExampleApp" Port="42" OnUpdate="DoNothing" >
10
<fw:RemoteAddress Value="*" />
11
</fw:FirewallException>
12
</File>
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" OnUpdate="EnableOnly" />
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" />
19
+
20
+ <fw:FirewallException Description="Defer to user edge traversal" Name="defertouser" Program="fw.exe" EdgeTraversal="DeferToUser" />
21
+ <fw:FirewallException Description="A port-based service exception" Name="ExampleService" Port="12000" Service="ftpsrv" Program="%windir%\system32\svchost.exe" >
22
+ <fw:LocalAddress Value="DHCP"/>
23
+ <fw:LocalAddress Value="WINS"/>
24
+ </fw:FirewallException>
25
+
26
+ <fw:FirewallException Description="Interfaces with nested elements" Name="interface nested" Port="54671" >
27
+ <fw:RemoteAddress Value="127.0.0.1"/>
28
+ <fw:Interface Name="Wi-Fi" />
29
+ <fw:Interface Name="Local Area Connection" />
30
+ </fw:FirewallException>
31
+ <fw:FirewallException Description="Interfaces with property" Name="interface property" Port="54671" Interface="[INTERFACE_PROPERTY]" />
32
+
33
+ <ServiceInstall Name="svc1" Type="ownProcess" Start="disabled" ErrorControl="ignore" >
34
+ <fw:FirewallException Id="ServiceInstall.nested" IgnoreFailure="true" Description="A port-based firewall exception for a windows service" Name="ExampleNestedService" Port="3546-7890" Scope="localSubnet" >
35
+ <fw:InterfaceType Value="Lan" />
36
+ <fw:InterfaceType Value="Wireless" />
37
+ </fw:FirewallException>
38
+ </ServiceInstall>
39
+
40
+ <fw:FirewallException Description="Simple INetFwRule3 values" Name="INetFwRule3 values" Scope="any" LocalAppPackageId="S-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315" LocalUserAuthorizedList="O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)" LocalUserOwner="S-1-5-21-1898747406-2352535518-1247798438-1914" RemoteMachineAuthorizedList="127.0.0.1" RemoteUserAuthorizedList="O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)" IPSecSecureFlags="NegotiateEncryption" />
41
+ <fw:FirewallException Description="INetFwRule3 passed via properties" Name="INetFwRule3 properties" Scope="any" LocalAppPackageId="[PROP1]" LocalUserAuthorizedList="[PROP2]" LocalUserOwner="[PROP3]" RemoteMachineAuthorizedList="[PROP4]" RemoteUserAuthorizedList="[PROP5]" IPSecSecureFlags="[PROP6]" />
42
+
43
+ <fw:FirewallException Description="Simple rule with grouping" Name="GroupingExample1" Program="fw.exe" Grouping="@yourresources.dll,-1005" />
44
+ <fw:FirewallException Description="Rule with grouping property" Name="GroupingExample2" Port="8732" Grouping="[GROUPING_PROP]" />
45
+
46
+ <fw:FirewallException Description="Simple ICMP rule" Name="ICMPExample1" Protocol="2" IcmpTypesAndCodes="4:*,9:*,12:*" />
47
+ <fw:FirewallException Description="Rule with ICMP property" Name="ICMPExample2" Protocol="2" IcmpTypesAndCodes="[ICMP_PROP]" />
48
+
49
+ <fw:FirewallException Description="Simple rule with local scope" Name="LocalScopeExample1" Scope="any" LocalScope="localSubnet" />
50
+ <fw:FirewallException Description="Rule with local scope property" Name="LocalScopeExample2" Scope="any" LocalScope="[LOCALSCOPE_PROP]" />
51
+
52
+ <fw:FirewallException Description="Simple rule with remote port" Name="RemotePortExample1" Scope="any" RemotePort="34560" />
53
+ <fw:FirewallException Description="Rule with remote port property" Name="RemotePortExample2" Program="fw.exe" RemotePort="[REMOTEPORT_PROP]" />
54
</Component>
55
</ComponentGroup>
56
</Fragment>
src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.en-us.wxl
new
+9
@@ -0,0 +1,9 @@
1
+<!--
2
+This file contains the declaration of all the localizable strings.
3
+-->
4
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
5
+
6
+ <String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />
7
+ <String Id="FeatureTitle" Value="MsiPackage" />
8
+
9
+</WixLocalization>
src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.wxs
new
+15
@@ -0,0 +1,15 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="BB4E61B3-EBE5-4DE7-B3E0-8699B5901D2E">
3
+ <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
+
5
+ <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6
+ <ComponentGroupRef Id="ProductComponents" />
7
+ </Feature>
8
+ </Package>
9
+
10
+ <Fragment>
11
+ <StandardDirectory Id="ProgramFilesFolder">
12
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
13
+ </StandardDirectory>
14
+ </Fragment>
15
+</Wix>
src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/PackageComponents.wxs
new
+53
@@ -0,0 +1,53 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
6
+ <Component Id="FirewallComponent" Guid="28DF3387-F30E-4DBE-90E2-D2C760CB4DD9">
7
+ <fw:FirewallException
8
+ Name="[NAME]"
9
+ Port="[LOCALPORT]"
10
+ Protocol="[PROTOCOL]"
11
+ Program="[PROGRAM]"
12
+ Profile="[PROFILE]"
13
+ Description="[DESCRIPTION]"
14
+ Scope="[REMOTESCOPE]"
15
+ Action="[ACTION]"
16
+ EdgeTraversal="[EDGETRAVERSAL]"
17
+ Enabled="[ENABLED]"
18
+ Grouping="[GROUPING]"
19
+ IcmpTypesAndCodes="[ICMPTYPES]"
20
+ Interface="[INTERFACE]"
21
+ InterfaceType="[INTERFACETYPE]"
22
+ LocalScope="[LOCALSCOPE]"
23
+ RemotePort="[REMOTEPORT]"
24
+ Service="[SERVICE]"
25
+ LocalAppPackageId="[PACKAGEID]"
26
+ LocalUserAuthorizedList="[LOCALUSERS]"
27
+ LocalUserOwner="[LOCALOWNER]"
28
+ RemoteMachineAuthorizedList="[REMOTEMACHINES]"
29
+ RemoteUserAuthorizedList="[REMOTEUSERS]"
30
+ IPSecSecureFlags="[SECUREFLAGS]"
31
+ />
32
+
33
+ <fw:FirewallException Name="Single Nested properties" >
34
+ <fw:RemoteAddress Value="[REMOTEADDRESS]" />
35
+ <fw:LocalAddress Value="[LOCALADDRESS]" />
36
+ <fw:InterfaceType Value="[INTERFACETYPE]" />
37
+ <fw:Interface Name="[INTERFACE]" />
38
+ </fw:FirewallException>
39
+
40
+ <fw:FirewallException Name="Multiple Nested properties" >
41
+ <fw:RemoteAddress Value="[REMOTEADDRESS1]" />
42
+ <fw:RemoteAddress Value="[REMOTEADDRESS2]" />
43
+ <fw:LocalAddress Value="[LOCALADDRESS1]" />
44
+ <fw:LocalAddress Value="[LOCALADDRESS2]" />
45
+ <fw:InterfaceType Value="[INTERFACETYPE1]" />
46
+ <fw:InterfaceType Value="[INTERFACETYPE2]" />
47
+ <fw:Interface Name="[INTERFACE1]" />
48
+ <fw:Interface Name="[INTERFACE2]" />
49
+ </fw:FirewallException>
50
+ </Component>
51
+ </ComponentGroup>
52
+ </Fragment>
53
+</Wix>
src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/example.txt
new
+1
@@ -0,0 +1 @@
1
+This is example.txt.
\ No newline at end of file
src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
+2
@@ -5,6 +5,8 @@
5
<PropertyGroup>
6
<TargetFramework>net6.0</TargetFramework>
7
<IsWixTestProject>true</IsWixTestProject>
8
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
9
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
10
</PropertyGroup>
11
12
<ItemGroup>
src/ext/Firewall/wixext/FirewallCompiler.cs
+563
-60
@@ -35,7 +35,7 @@ namespace WixToolset.Firewall
35
switch (element.Name.LocalName)
36
{
37
case "FirewallException":
38
- this.ParseFirewallExceptionElement(intermediate, section, element, fileComponentId, fileId);
38
+ this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, fileComponentId, fileId, null);
39
break;
40
default:
41
this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -48,7 +48,35 @@ namespace WixToolset.Firewall
48
switch (element.Name.LocalName)
49
{
50
case "FirewallException":
51
- this.ParseFirewallExceptionElement(intermediate, section, element, componentId, null);
51
+ this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, componentId, null, null);
52
+ break;
53
+ default:
54
+ this.ParseHelper.UnexpectedElement(parentElement, element);
55
+ break;
56
+ }
57
+ break;
58
+ case "ServiceConfig":
59
+ var serviceConfigName = context["ServiceConfigServiceName"];
60
+ var serviceConfigComponentId = context["ServiceConfigComponentId"];
61
+
62
+ switch (element.Name.LocalName)
63
+ {
64
+ case "FirewallException":
65
+ this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, serviceConfigComponentId, null, serviceConfigName);
66
+ break;
67
+ default:
68
+ this.ParseHelper.UnexpectedElement(parentElement, element);
69
+ break;
70
+ }
71
+ break;
72
+ case "ServiceInstall":
73
+ var serviceInstallName = context["ServiceInstallName"];
74
+ var serviceInstallComponentId = context["ServiceInstallComponentId"];
75
+
76
+ switch (element.Name.LocalName)
77
+ {
78
+ case "FirewallException":
79
+ this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, serviceInstallComponentId, null, serviceInstallName);
80
break;
81
default:
82
this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -64,10 +92,12 @@ namespace WixToolset.Firewall
92
/// <summary>
93
/// Parses a FirewallException element.
94
/// </summary>
95
+ /// <param name="parentElement">The parent element of the one being parsed.</param>
96
/// <param name="element">The element to parse.</param>
97
/// <param name="componentId">Identifier of the component that owns this firewall exception.</param>
98
/// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
70
- private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
99
+ /// <param name="serviceName">The service name of the parent element (null if not nested under ServiceConfig or ServiceInstall).</param>
100
+ private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, string componentId, string fileId, string serviceName)
101
{
102
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
103
Identifier id = null;
@@ -76,12 +106,32 @@ namespace WixToolset.Firewall
106
string file = null;
107
string program = null;
108
string port = null;
79
- int? protocol = null;
80
- int? profile = null;
109
+ string protocol = null;
110
+ string profile = null;
111
string scope = null;
112
string remoteAddresses = null;
113
string description = null;
114
int? direction = null;
115
+ string protocolValue = null;
116
+ string action = null;
117
+ string edgeTraversal = null;
118
+ string enabled = null;
119
+ string grouping = null;
120
+ string icmpTypesAndCodes = null;
121
+ string interfaces = null;
122
+ string interfaceValue = null;
123
+ string interfaceTypes = null;
124
+ string interfaceTypeValue = null;
125
+ string localScope = null;
126
+ string localAddresses = null;
127
+ string remotePort = null;
128
+ string service = null;
129
+ string localAppPackageId = null;
130
+ string localUserAuthorizedList = null;
131
+ string localUserOwner = null;
132
+ string remoteMachineAuthorizedList = null;
133
+ string remoteUserAuthorizedList = null;
134
+ string secureFlags = null;
135
136
foreach (var attrib in element.Attributes())
137
{
@@ -96,9 +146,9 @@ namespace WixToolset.Firewall
146
name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
147
break;
148
case "File":
99
- if (null != fileId)
149
+ if (fileId != null)
150
{
101
- this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File"));
151
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", parentElement.Name.LocalName));
152
}
153
else
154
{
@@ -106,15 +156,31 @@ namespace WixToolset.Firewall
156
}
157
break;
158
case "IgnoreFailure":
109
- if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
159
+ if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes)
160
{
161
attributes |= 0x1; // feaIgnoreFailures
162
}
163
break;
164
+ case "OnUpdate":
165
+ var onupdate = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
166
+ switch (onupdate)
167
+ {
168
+ case "DoNothing":
169
+ attributes |= 0x2; // feaIgnoreUpdates
170
+ break;
171
+ case "EnableOnly":
172
+ attributes |= 0x4; // feaEnableOnUpdate
173
+ break;
174
+
175
+ default:
176
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "OnUpdate", onupdate, "EnableOnly", "DoNothing"));
177
+ break;
178
+ }
179
+ break;
180
case "Program":
115
- if (null != fileId)
181
+ if (fileId != null)
182
{
117
- this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File"));
183
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", parentElement.Name.LocalName));
184
}
185
else
186
{
@@ -125,22 +191,28 @@ namespace WixToolset.Firewall
191
port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
192
break;
193
case "Protocol":
128
- var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
194
+ protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
195
switch (protocolValue)
196
{
197
+ case FirewallConstants.IntegerNotSetString:
198
+ break;
199
+
200
case "tcp":
132
- protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
201
+ protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString();
202
break;
203
case "udp":
135
- protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
204
+ protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP.ToString();
205
break;
206
+
207
default:
138
- int parsedProtocol;
139
- if (!Int32.TryParse(protocolValue, out parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0)
208
+ protocol = protocolValue;
209
+ if (!this.ParseHelper.ContainsProperty(protocolValue))
210
{
141
- this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255"));
211
+ if (!Int32.TryParse(protocolValue, out var parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0)
212
+ {
213
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255"));
214
+ }
215
}
143
- protocol = parsedProtocol;
216
break;
217
}
218
break;
@@ -167,7 +239,11 @@ namespace WixToolset.Firewall
239
remoteAddresses = "DefaultGateway";
240
break;
241
default:
170
- this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
242
+ remoteAddresses = scope;
243
+ if (!this.ParseHelper.ContainsProperty(scope))
244
+ {
245
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
246
+ }
247
break;
248
}
249
break;
@@ -176,19 +252,23 @@ namespace WixToolset.Firewall
252
switch (profileValue)
253
{
254
case "domain":
179
- profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN;
255
+ profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN.ToString();
256
break;
257
case "private":
182
- profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE;
258
+ profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE.ToString();
259
break;
260
case "public":
185
- profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC;
261
+ profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC.ToString();
262
break;
263
case "all":
188
- profile = FirewallConstants.NET_FW_PROFILE2_ALL;
264
+ profile = FirewallConstants.NET_FW_PROFILE2_ALL.ToString();
265
break;
266
default:
191
- this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
267
+ profile = profileValue;
268
+ if (!this.ParseHelper.ContainsProperty(profileValue))
269
+ {
270
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
271
+ }
272
break;
273
}
274
break;
@@ -200,6 +280,196 @@ namespace WixToolset.Firewall
280
? FirewallConstants.NET_FW_RULE_DIR_OUT
281
: FirewallConstants.NET_FW_RULE_DIR_IN;
282
break;
283
+ case "Action":
284
+ action = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
285
+ switch (action)
286
+ {
287
+ case "Block":
288
+ action = "0";
289
+ break;
290
+ case "Allow":
291
+ action = "1";
292
+ break;
293
+
294
+ default:
295
+ if (!this.ParseHelper.ContainsProperty(action))
296
+ {
297
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Action", action, "Allow", "Block"));
298
+ }
299
+ break;
300
+ }
301
+ break;
302
+ case "EdgeTraversal":
303
+ edgeTraversal = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
304
+ switch (edgeTraversal)
305
+ {
306
+ case "Deny":
307
+ edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DENY.ToString();
308
+ break;
309
+ case "Allow":
310
+ edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW.ToString();
311
+ break;
312
+ case "DeferToApp":
313
+ attributes |= 0x8; // feaAddINetFwRule2
314
+ edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP.ToString();
315
+ break;
316
+ case "DeferToUser":
317
+ attributes |= 0x8; // feaAddINetFwRule2
318
+ edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER.ToString();
319
+ break;
320
+
321
+ default:
322
+ if (!this.ParseHelper.ContainsProperty(edgeTraversal))
323
+ {
324
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "EdgeTraversal", edgeTraversal, "Allow", "DeferToApp", "DeferToUser", "Deny"));
325
+ }
326
+ break;
327
+ }
328
+ break;
329
+ case "Enabled":
330
+ enabled = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
331
+ if (!this.ParseHelper.ContainsProperty(enabled))
332
+ {
333
+ switch (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
334
+ {
335
+ case YesNoType.Yes:
336
+ enabled = "1";
337
+ break;
338
+ case YesNoType.No:
339
+ enabled = "0";
340
+ break;
341
+
342
+ default:
343
+ this.Messaging.Write(ErrorMessages.IllegalYesNoValue(sourceLineNumbers, element.Name.LocalName, "Enabled", enabled));
344
+ break;
345
+ }
346
+ }
347
+ break;
348
+ case "Grouping":
349
+ grouping = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
350
+ break;
351
+ case "IcmpTypesAndCodes":
352
+ icmpTypesAndCodes = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
353
+ break;
354
+ case "Interface":
355
+ interfaceValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
356
+ interfaces = interfaceValue;
357
+ break;
358
+ case "InterfaceType":
359
+ interfaceTypeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
360
+ switch (interfaceTypeValue)
361
+ {
362
+ case "RemoteAccess":
363
+ case "Wireless":
364
+ case "Lan":
365
+ case "All":
366
+ break;
367
+
368
+ default:
369
+ if (!this.ParseHelper.ContainsProperty(interfaceTypeValue))
370
+ {
371
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "InterfaceType", interfaceTypeValue, "RemoteAccess", "Wireless", "Lan", "All"));
372
+ }
373
+ break;
374
+ }
375
+ interfaceTypes = interfaceTypeValue;
376
+ break;
377
+ case "LocalScope":
378
+ localScope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
379
+ switch (localScope)
380
+ {
381
+ case "any":
382
+ localAddresses = "*";
383
+ break;
384
+ case "localSubnet":
385
+ localAddresses = "LocalSubnet";
386
+ break;
387
+ case "DNS":
388
+ localAddresses = "dns";
389
+ break;
390
+ case "DHCP":
391
+ localAddresses = "dhcp";
392
+ break;
393
+ case "WINS":
394
+ localAddresses = "wins";
395
+ break;
396
+ case "defaultGateway":
397
+ localAddresses = "DefaultGateway";
398
+ break;
399
+
400
+ default:
401
+ if (!this.ParseHelper.ContainsProperty(localScope))
402
+ {
403
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "LocalScope", localScope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
404
+ }
405
+ else
406
+ {
407
+ localAddresses = localScope;
408
+ }
409
+ break;
410
+ }
411
+ break;
412
+ case "RemotePort":
413
+ remotePort = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
414
+ break;
415
+ case "Service":
416
+ if (serviceName != null)
417
+ {
418
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Service", parentElement.Name.LocalName));
419
+ }
420
+ else
421
+ {
422
+ service = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
423
+ }
424
+ break;
425
+ case "LocalAppPackageId":
426
+ localAppPackageId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
427
+ attributes |= 0x10; // feaAddINetFwRule3
428
+ break;
429
+ case "LocalUserAuthorizedList":
430
+ localUserAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
431
+ attributes |= 0x10; // feaAddINetFwRule3
432
+ break;
433
+ case "LocalUserOwner":
434
+ localUserOwner = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
435
+ attributes |= 0x10; // feaAddINetFwRule3
436
+ break;
437
+ case "RemoteMachineAuthorizedList":
438
+ remoteMachineAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
439
+ attributes |= 0x10; // feaAddINetFwRule3
440
+ break;
441
+ case "RemoteUserAuthorizedList":
442
+ remoteUserAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
443
+ attributes |= 0x10; // feaAddINetFwRule3
444
+ break;
445
+ case "IPSecSecureFlags":
446
+ secureFlags = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
447
+ attributes |= 0x10; // feaAddINetFwRule3
448
+ if (!this.ParseHelper.ContainsProperty(secureFlags))
449
+ {
450
+ switch (secureFlags)
451
+ {
452
+ case "None":
453
+ secureFlags = "0";
454
+ break;
455
+ case "NoEncapsulation":
456
+ secureFlags = "1";
457
+ break;
458
+ case "WithIntegrity":
459
+ secureFlags = "2";
460
+ break;
461
+ case "NegotiateEncryption":
462
+ secureFlags = "3";
463
+ break;
464
+ case "Encrypt":
465
+ secureFlags = "4";
466
+ break;
467
+ default:
468
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "IPSecSecureFlags", secureFlags, "None", "NoEncapsulation", "WithIntegrity", "NegotiateEncryption", "Encrypt"));
469
+ break;
470
+ }
471
+ }
472
+ break;
473
default:
474
this.ParseHelper.UnexpectedAttribute(element, attrib);
475
break;
@@ -211,7 +481,7 @@ namespace WixToolset.Firewall
481
}
482
}
483
214
- // parse RemoteAddress children
484
+ // parse children
485
foreach (var child in element.Elements())
486
{
487
if (this.Namespace == child.Name.Namespace)
@@ -219,7 +489,7 @@ namespace WixToolset.Firewall
489
switch (child.Name.LocalName)
490
{
491
case "RemoteAddress":
222
- if (null != scope)
492
+ if (scope != null)
493
{
494
this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
495
}
@@ -228,6 +498,37 @@ namespace WixToolset.Firewall
498
this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
499
}
500
break;
501
+ case "Interface":
502
+ if (interfaceValue != null)
503
+ {
504
+ this.Messaging.Write(FirewallErrors.IllegalInterfaceWithInterfaceAttribute(sourceLineNumbers));
505
+ }
506
+ else
507
+ {
508
+ this.ParseInterfaceElement(intermediate, section, child, ref interfaces);
509
+ }
510
+ break;
511
+ case "InterfaceType":
512
+ if (interfaceTypeValue != null)
513
+ {
514
+ this.Messaging.Write(FirewallErrors.IllegalInterfaceTypeWithInterfaceTypeAttribute(sourceLineNumbers));
515
+ }
516
+ else
517
+ {
518
+ this.ParseInterfaceTypeElement(intermediate, section, child, ref interfaceTypes);
519
+ }
520
+ break;
521
+ case "LocalAddress":
522
+ if (localScope != null)
523
+ {
524
+ this.Messaging.Write(FirewallErrors.IllegalLocalAddressWithLocalScopeAttribute(sourceLineNumbers));
525
+ }
526
+ else
527
+ {
528
+ this.ParseLocalAddressElement(intermediate, section, child, ref localAddresses);
529
+ }
530
+ break;
531
+
532
default:
533
this.ParseHelper.UnexpectedElement(element, child);
534
break;
@@ -239,54 +540,84 @@ namespace WixToolset.Firewall
540
}
541
}
542
242
- if (null == id)
543
+ if (id == null)
544
{
244
- id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId);
545
+ // firewall rule names are meant to be unique
546
+ id = this.ParseHelper.CreateIdentifier("fex", name, componentId);
547
}
548
549
// Name is required
248
- if (null == name)
550
+ if (name == null)
551
{
552
this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
553
}
554
253
- // Scope or child RemoteAddress(es) are required
254
- if (null == remoteAddresses)
555
+ if (service == null)
556
{
256
- this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress"));
557
+ service = serviceName;
558
}
559
560
// can't have both Program and File
260
- if (null != program && null != file)
561
+ if (program != null && file != null)
562
{
563
this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
564
}
565
265
- // must be nested under File, have File or Program attributes, or have Port attribute
266
- if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port))
566
+ // Defer to user edge traversal setting can only be used in a firewall rule where program path and TCP/UDP protocol are specified with no additional conditions.
567
+ if (edgeTraversal == FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER.ToString())
568
{
268
- this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
269
- }
569
+ if (protocol != null && !(protocol == FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString() || protocol == FirewallConstants.NET_FW_IP_PROTOCOL_UDP.ToString()))
570
+ {
571
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp,udp"));
572
+ }
573
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)
574
+ if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program))
575
{
276
- case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
277
- case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
278
- break;
576
+ this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Program", "EdgeTraversal", "DeferToUser"));
577
+ }
578
280
- default:
281
- this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "Protocol", protocol.Value.ToString()));
282
- break;
579
+ if (port != null)
580
+ {
581
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "EdgeTraversal", "DeferToUser"));
582
+ }
583
+
584
+ if (remotePort != null)
585
+ {
586
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "RemotePort", "EdgeTraversal", "DeferToUser"));
587
+ }
588
+
589
+ if (localScope != null)
590
+ {
591
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "LocalScope", "EdgeTraversal", "DeferToUser"));
592
+ }
593
+
594
+ if (scope != null)
595
+ {
596
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Scope", "EdgeTraversal", "DeferToUser"));
597
+ }
598
+
599
+ if (profile != null)
600
+ {
601
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Profile", "EdgeTraversal", "DeferToUser"));
602
+ }
603
+
604
+ if (service != null)
605
+ {
606
+ if (serviceName != null)
607
+ {
608
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, element.Name.LocalName, "EdgeTraversal", "DeferToUser", parentElement.Name.LocalName));
609
+ }
610
+ else
611
+ {
612
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Service", "EdgeTraversal", "DeferToUser"));
613
+ }
614
}
615
}
616
617
if (!this.Messaging.EncounteredError)
618
{
619
// at this point, File attribute and File parent element are treated the same
289
- if (null != file)
620
+ if (file != null)
621
{
622
fileId = file;
623
}
@@ -295,28 +626,38 @@ namespace WixToolset.Firewall
626
{
627
Name = name,
628
RemoteAddresses = remoteAddresses,
298
- Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
629
ComponentRef = componentId,
630
Description = description,
631
Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
632
+ Action = action ?? FirewallConstants.IntegerNotSetString,
633
+ EdgeTraversal = edgeTraversal ?? FirewallConstants.IntegerNotSetString,
634
+ Enabled = enabled ?? FirewallConstants.IntegerNotSetString,
635
+ Grouping = grouping,
636
+ IcmpTypesAndCodes = icmpTypesAndCodes,
637
+ Interfaces = interfaces,
638
+ InterfaceTypes = interfaceTypes,
639
+ LocalAddresses = localAddresses,
640
+ Port = port,
641
+ Profile = profile ?? FirewallConstants.IntegerNotSetString,
642
+ Protocol = protocol ?? FirewallConstants.IntegerNotSetString,
643
+ RemotePort = remotePort,
644
+ ServiceName = service,
645
+ LocalAppPackageId = localAppPackageId,
646
+ LocalUserAuthorizedList = localUserAuthorizedList,
647
+ LocalUserOwner = localUserOwner,
648
+ RemoteMachineAuthorizedList = remoteMachineAuthorizedList,
649
+ RemoteUserAuthorizedList = remoteUserAuthorizedList,
650
+ SecureFlags = secureFlags ?? FirewallConstants.IntegerNotSetString,
651
});
652
304
- if (!String.IsNullOrEmpty(port))
653
+ if (String.IsNullOrEmpty(protocol))
654
{
306
- symbol.Port = port;
307
-
308
- if (!protocol.HasValue)
655
+ if (!String.IsNullOrEmpty(port) || !String.IsNullOrEmpty(remotePort))
656
{
310
- // default protocol is "TCP"
311
- protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
657
+ symbol.Protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString();
658
}
659
}
660
315
- if (protocol.HasValue)
316
- {
317
- symbol.Protocol = protocol.Value;
318
- }
319
-
661
if (!String.IsNullOrEmpty(fileId))
662
{
663
symbol.Program = $"[#{fileId}]";
@@ -327,7 +668,7 @@ namespace WixToolset.Firewall
668
symbol.Program = program;
669
}
670
330
- if (CompilerConstants.IntegerNotSet != attributes)
671
+ if (attributes != CompilerConstants.IntegerNotSet)
672
{
673
symbol.Attributes = attributes;
674
}
@@ -382,5 +723,167 @@ namespace WixToolset.Firewall
723
}
724
}
725
}
726
+
727
+ /// <summary>
728
+ /// Parses an Interface element
729
+ /// </summary>
730
+ /// <param name="element">The element to parse.</param>
731
+ private void ParseInterfaceElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string interfaces)
732
+ {
733
+ var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
734
+ string name = null;
735
+
736
+ // no attributes
737
+ foreach (var attrib in element.Attributes())
738
+ {
739
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
740
+ {
741
+ switch (attrib.Name.LocalName)
742
+ {
743
+ case "Name":
744
+ name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
745
+ break;
746
+ }
747
+ }
748
+ else
749
+ {
750
+ this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
751
+ }
752
+ }
753
+
754
+ this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
755
+
756
+ if (String.IsNullOrEmpty(name))
757
+ {
758
+ this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
759
+ }
760
+ else
761
+ {
762
+ if (String.IsNullOrEmpty(interfaces))
763
+ {
764
+ interfaces = name;
765
+ }
766
+ else
767
+ {
768
+ interfaces = String.Concat(interfaces, FirewallConstants.FORBIDDEN_FIREWALL_CHAR, name);
769
+ }
770
+ }
771
+ }
772
+
773
+ /// <summary>
774
+ /// Parses an InterfaceType element
775
+ /// </summary>
776
+ /// <param name="element">The element to parse.</param>
777
+ private void ParseInterfaceTypeElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string interfaceTypes)
778
+ {
779
+ var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
780
+ string value = null;
781
+
782
+ // no attributes
783
+ foreach (var attrib in element.Attributes())
784
+ {
785
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
786
+ {
787
+ switch (attrib.Name.LocalName)
788
+ {
789
+ case "Value":
790
+ value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
791
+ break;
792
+ }
793
+ }
794
+ else
795
+ {
796
+ this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
797
+ }
798
+ }
799
+
800
+ this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
801
+
802
+ if (String.IsNullOrEmpty(value))
803
+ {
804
+ this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
805
+ }
806
+ else
807
+ {
808
+ switch (value)
809
+ {
810
+ case "RemoteAccess":
811
+ case "Wireless":
812
+ case "Lan":
813
+ case "All":
814
+ break;
815
+
816
+ default:
817
+ if (!this.ParseHelper.ContainsProperty(value))
818
+ {
819
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Value", value, "RemoteAccess", "Wireless", "Lan", "All"));
820
+ value = null;
821
+ }
822
+ break;
823
+ }
824
+
825
+ if (String.IsNullOrEmpty(interfaceTypes))
826
+ {
827
+ interfaceTypes = value;
828
+ }
829
+ else if (interfaceTypes.Contains("All"))
830
+ {
831
+ if (value != "All")
832
+ {
833
+ this.Messaging.Write(FirewallErrors.IllegalInterfaceTypeWithInterfaceTypeAll(sourceLineNumbers));
834
+ }
835
+ }
836
+ else if(!String.IsNullOrEmpty(value))
837
+ {
838
+ interfaceTypes = String.Concat(interfaceTypes, ",", value);
839
+ }
840
+ }
841
+ }
842
+
843
+ /// <summary>
844
+ /// Parses a RemoteAddress element
845
+ /// </summary>
846
+ /// <param name="element">The element to parse.</param>
847
+ private void ParseLocalAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string localAddresses)
848
+ {
849
+ var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
850
+ string address = null;
851
+
852
+ // no attributes
853
+ foreach (var attrib in element.Attributes())
854
+ {
855
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
856
+ {
857
+ switch (attrib.Name.LocalName)
858
+ {
859
+ case "Value":
860
+ address = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
861
+ break;
862
+ }
863
+ }
864
+ else
865
+ {
866
+ this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
867
+ }
868
+ }
869
+
870
+ this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
871
+
872
+ if (String.IsNullOrEmpty(address))
873
+ {
874
+ this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
875
+ }
876
+ else
877
+ {
878
+ if (String.IsNullOrEmpty(localAddresses))
879
+ {
880
+ localAddresses = address;
881
+ }
882
+ else
883
+ {
884
+ localAddresses = String.Concat(localAddresses, ",", address);
885
+ }
886
+ }
887
+ }
888
}
889
}
src/ext/Firewall/wixext/FirewallConstants.cs
+17
@@ -9,6 +9,11 @@ namespace WixToolset.Firewall
9
internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/firewall";
10
internal static readonly XName FirewallExceptionName = Namespace + "FirewallException";
11
internal static readonly XName RemoteAddressName = Namespace + "RemoteAddress";
12
+ internal static readonly XName InterfaceName = Namespace + "Interface";
13
+ internal static readonly XName InterfaceTypeName = Namespace + "InterfaceType";
14
+ internal static readonly XName LocalAddressName = Namespace + "LocalAddress";
15
+
16
+ internal const string IntegerNotSetString = "-2147483648";
17
18
// from icftypes.h
19
public const int NET_FW_RULE_DIR_IN = 1;
@@ -21,5 +26,17 @@ namespace WixToolset.Firewall
26
public const int NET_FW_PROFILE2_PRIVATE = 0x0002;
27
public const int NET_FW_PROFILE2_PUBLIC = 0x0004;
28
public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF;
29
+
30
+ // from icftypes.h
31
+ public const int NET_FW_EDGE_TRAVERSAL_TYPE_DENY = 0;
32
+ public const int NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW = 1;
33
+ public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP = 2;
34
+ public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER = 3;
35
+
36
+ /// <summary>
37
+ /// Firewall rules are stored in the registry.<br/>
38
+ /// The pipe character is used to split firewall rule attributes, so is not permitted in any of them.
39
+ /// </summary>
40
+ public const char FORBIDDEN_FIREWALL_CHAR = '|';
41
}
42
}
src/ext/Firewall/wixext/FirewallDecompiler.cs
+300
-17
@@ -8,6 +8,8 @@ namespace WixToolset.Firewall
8
using WixToolset.Data;
9
using WixToolset.Data.WindowsInstaller;
10
using WixToolset.Extensibility;
11
+ using WixToolset.Extensibility.Data;
12
+ using WixToolset.Extensibility.Services;
13
14
/// <summary>
15
/// The decompiler for the WiX Toolset Firewall Extension.
@@ -16,6 +18,14 @@ namespace WixToolset.Firewall
18
{
19
public override IReadOnlyCollection<TableDefinition> TableDefinitions => FirewallTableDefinitions.All;
20
21
+ private IParseHelper ParseHelper { get; set; }
22
+
23
+ public override void PreDecompile(IWindowsInstallerDecompileContext context, IWindowsInstallerDecompilerHelper helper)
24
+ {
25
+ base.PreDecompile(context, helper);
26
+ this.ParseHelper = context.ServiceProvider.GetService<IParseHelper>();
27
+ }
28
+
29
/// <summary>
30
/// Called at the beginning of the decompilation of a database.
31
/// </summary>
@@ -32,6 +42,8 @@ namespace WixToolset.Firewall
42
{
43
switch (table.Name)
44
{
45
+ case "WixFirewallException":
46
+ case "Wix4FirewallException":
47
case "Wix5FirewallException":
48
this.DecompileWixFirewallExceptionTable(table);
49
break;
@@ -57,7 +69,7 @@ namespace WixToolset.Firewall
69
/// <param name="table">The table to decompile.</param>
70
private void DecompileWixFirewallExceptionTable(Table table)
71
{
60
- foreach (Row row in table.Rows)
72
+ foreach (var row in table.Rows)
73
{
74
var firewallException = new XElement(FirewallConstants.FirewallExceptionName,
75
new XAttribute("Id", row.FieldAsString(0)),
@@ -90,13 +102,20 @@ namespace WixToolset.Firewall
102
firewallException.Add(new XAttribute("Scope", "defaultGateway"));
103
break;
104
default:
93
- FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
105
+ if (this.ParseHelper.ContainsProperty(addresses[0]))
106
+ {
107
+ firewallException.Add(new XAttribute("Scope", addresses[0]));
108
+ }
109
+ else
110
+ {
111
+ FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
112
+ }
113
break;
114
}
115
}
116
else
117
{
99
- foreach (string address in addresses)
118
+ foreach (var address in addresses)
119
{
120
FirewallDecompiler.AddRemoteAddress(firewallException, address);
121
}
@@ -110,16 +129,19 @@ namespace WixToolset.Firewall
129
130
if (!row.IsColumnEmpty(4))
131
{
113
- switch (Convert.ToInt32(row[4]))
132
+ switch (row.FieldAsString(4))
133
{
115
- case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
134
+ case FirewallConstants.IntegerNotSetString:
135
+ break;
136
+ case "6":
137
firewallException.Add(new XAttribute("Protocol", "tcp"));
138
break;
118
- case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
139
+ case "17":
140
firewallException.Add(new XAttribute("Protocol", "udp"));
141
break;
142
+
143
default:
122
- firewallException.Add(new XAttribute("Protocol", row[4]));
144
+ firewallException.Add(new XAttribute("Protocol", row.FieldAsString(4)));
145
break;
146
}
147
}
@@ -131,26 +153,44 @@ namespace WixToolset.Firewall
153
154
if (!row.IsColumnEmpty(6))
155
{
134
- var attr = Convert.ToInt32(row[6]);
135
- AttributeIfNotNull("IgnoreFailure", (attr & 0x1) == 0x1);
156
+ var attr = row.FieldAsInteger(6);
157
+ if ((attr & 0x1) == 0x1)
158
+ {
159
+ AttributeIfNotNull("IgnoreFailure", true);
160
+ }
161
+
162
+ if ((attr & 0x2) == 0x2)
163
+ {
164
+ firewallException.Add(new XAttribute("OnUpdate", "DoNothing"));
165
+ }
166
+ else if ((attr & 0x4) == 0x4)
167
+ {
168
+ firewallException.Add(new XAttribute("OnUpdate", "EnableOnly"));
169
+ }
170
}
171
172
if (!row.IsColumnEmpty(7))
173
{
140
- switch (Convert.ToInt32(row[7]))
174
+ switch (row.FieldAsString(7))
175
{
142
- case FirewallConstants.NET_FW_PROFILE2_DOMAIN:
176
+ case FirewallConstants.IntegerNotSetString:
177
+ break;
178
+ case "1":
179
firewallException.Add(new XAttribute("Profile", "domain"));
180
break;
145
- case FirewallConstants.NET_FW_PROFILE2_PRIVATE:
181
+ case "2":
182
firewallException.Add(new XAttribute("Profile", "private"));
183
break;
148
- case FirewallConstants.NET_FW_PROFILE2_PUBLIC:
184
+ case "4":
185
firewallException.Add(new XAttribute("Profile", "public"));
186
break;
151
- case FirewallConstants.NET_FW_PROFILE2_ALL:
187
+ case "2147483647":
188
firewallException.Add(new XAttribute("Profile", "all"));
189
break;
190
+
191
+ default:
192
+ firewallException.Add(new XAttribute("Profile", row.FieldAsString(7)));
193
+ break;
194
}
195
}
196
@@ -164,8 +204,6 @@ namespace WixToolset.Firewall
204
switch (Convert.ToInt32(row[10]))
205
{
206
case FirewallConstants.NET_FW_RULE_DIR_IN:
167
-
168
- firewallException.Add(AttributeIfNotNull("Outbound", false));
207
break;
208
case FirewallConstants.NET_FW_RULE_DIR_OUT:
209
firewallException.Add(AttributeIfNotNull("Outbound", true));
@@ -173,6 +211,224 @@ namespace WixToolset.Firewall
211
}
212
}
213
214
+ // Introduced in 5.0.0
215
+ if (row.Fields.Length > 11)
216
+ {
217
+ if (!row.IsColumnEmpty(11))
218
+ {
219
+ var action = row.FieldAsString(11);
220
+ switch (action)
221
+ {
222
+ case FirewallConstants.IntegerNotSetString:
223
+ break;
224
+ case "1":
225
+ firewallException.Add(new XAttribute("Action", "Allow"));
226
+ break;
227
+ case "0":
228
+ firewallException.Add(new XAttribute("Action", "Block"));
229
+ break;
230
+ default:
231
+ firewallException.Add(new XAttribute("Action", action));
232
+ break;
233
+ }
234
+ }
235
+
236
+ if (!row.IsColumnEmpty(12))
237
+ {
238
+ var edgeTraversal = row.FieldAsString(12);
239
+ switch (edgeTraversal)
240
+ {
241
+ case FirewallConstants.IntegerNotSetString:
242
+ break;
243
+ case "0":
244
+ firewallException.Add(new XAttribute("EdgeTraversal", "Deny"));
245
+ break;
246
+ case "1":
247
+ firewallException.Add(new XAttribute("EdgeTraversal", "Allow"));
248
+ break;
249
+ case "2":
250
+ firewallException.Add(new XAttribute("EdgeTraversal", "DeferToApp"));
251
+ break;
252
+ case "3":
253
+ firewallException.Add(new XAttribute("EdgeTraversal", "DeferToUser"));
254
+ break;
255
+ default:
256
+ firewallException.Add(new XAttribute("EdgeTraversal", edgeTraversal));
257
+ break;
258
+ }
259
+ }
260
+
261
+ if (!row.IsColumnEmpty(13))
262
+ {
263
+ var enabled = row.FieldAsString(13);
264
+ switch (enabled)
265
+ {
266
+ case FirewallConstants.IntegerNotSetString:
267
+ break;
268
+ case "1":
269
+ firewallException.Add(new XAttribute("Enabled", "yes"));
270
+ break;
271
+ case "0":
272
+ firewallException.Add(new XAttribute("Enabled", "no"));
273
+ break;
274
+ default:
275
+ firewallException.Add(new XAttribute("Enabled", enabled));
276
+ break;
277
+ }
278
+ }
279
+
280
+ if (!row.IsColumnEmpty(14))
281
+ {
282
+ firewallException.Add(new XAttribute("Grouping", row.FieldAsString(14)));
283
+ }
284
+
285
+ if (!row.IsColumnEmpty(15))
286
+ {
287
+ firewallException.Add(new XAttribute("IcmpTypesAndCodes", row.FieldAsString(15)));
288
+ }
289
+
290
+ if (!row.IsColumnEmpty(16))
291
+ {
292
+ string[] interfaces = row.FieldAsString(16).Split(new[] { FirewallConstants.FORBIDDEN_FIREWALL_CHAR }, StringSplitOptions.RemoveEmptyEntries);
293
+ if (interfaces.Length == 1)
294
+ {
295
+ firewallException.Add(new XAttribute("Interface", interfaces[0]));
296
+ }
297
+ else
298
+ {
299
+ foreach (var interfaceItem in interfaces)
300
+ {
301
+ FirewallDecompiler.AddInterface(firewallException, interfaceItem);
302
+ }
303
+ }
304
+ }
305
+
306
+ if (!row.IsColumnEmpty(17))
307
+ {
308
+ string[] interfaceTypes = row.FieldAsString(17).Split(',');
309
+ if (interfaceTypes.Length == 1)
310
+ {
311
+ firewallException.Add(new XAttribute("InterfaceType", interfaceTypes[0]));
312
+ }
313
+ else
314
+ {
315
+ foreach (var interfaceType in interfaceTypes)
316
+ {
317
+ FirewallDecompiler.AddInterfaceType(firewallException, interfaceType);
318
+ }
319
+ }
320
+ }
321
+
322
+ if (!row.IsColumnEmpty(18))
323
+ {
324
+ string[] addresses = row.FieldAsString(18).Split(',');
325
+ if (addresses.Length == 1)
326
+ {
327
+ switch (addresses[0])
328
+ {
329
+ case "*":
330
+ firewallException.Add(new XAttribute("LocalScope", "any"));
331
+ break;
332
+ case "LocalSubnet":
333
+ firewallException.Add(new XAttribute("LocalScope", "localSubnet"));
334
+ break;
335
+ case "dns":
336
+ firewallException.Add(new XAttribute("LocalScope", "DNS"));
337
+ break;
338
+ case "dhcp":
339
+ firewallException.Add(new XAttribute("LocalScope", "DHCP"));
340
+ break;
341
+ case "wins":
342
+ firewallException.Add(new XAttribute("LocalScope", "WINS"));
343
+ break;
344
+ case "DefaultGateway":
345
+ firewallException.Add(new XAttribute("LocalScope", "defaultGateway"));
346
+ break;
347
+ default:
348
+ if (this.ParseHelper.ContainsProperty(addresses[0]))
349
+ {
350
+ firewallException.Add(new XAttribute("LocalScope", addresses[0]));
351
+ }
352
+ else
353
+ {
354
+ FirewallDecompiler.AddLocalAddress(firewallException, addresses[0]);
355
+ }
356
+ break;
357
+ }
358
+ }
359
+ else
360
+ {
361
+ foreach (var address in addresses)
362
+ {
363
+ FirewallDecompiler.AddLocalAddress(firewallException, address);
364
+ }
365
+ }
366
+ }
367
+
368
+ if (!row.IsColumnEmpty(19))
369
+ {
370
+ firewallException.Add(new XAttribute("RemotePort", row.FieldAsString(19)));
371
+ }
372
+
373
+ if (!row.IsColumnEmpty(20))
374
+ {
375
+ firewallException.Add(new XAttribute("Service", row.FieldAsString(20)));
376
+ }
377
+
378
+ if (!row.IsColumnEmpty(21))
379
+ {
380
+ firewallException.Add(new XAttribute("LocalAppPackageId", row.FieldAsString(21)));
381
+ }
382
+
383
+ if (!row.IsColumnEmpty(22))
384
+ {
385
+ firewallException.Add(new XAttribute("LocalUserAuthorizedList", row.FieldAsString(22)));
386
+ }
387
+
388
+ if (!row.IsColumnEmpty(23))
389
+ {
390
+ firewallException.Add(new XAttribute("LocalUserOwner", row.FieldAsString(23)));
391
+ }
392
+
393
+ if (!row.IsColumnEmpty(24))
394
+ {
395
+ firewallException.Add(new XAttribute("RemoteMachineAuthorizedList", row.FieldAsString(24)));
396
+ }
397
+
398
+ if (!row.IsColumnEmpty(25))
399
+ {
400
+ firewallException.Add(new XAttribute("RemoteUserAuthorizedList", row.FieldAsString(25)));
401
+ }
402
+
403
+ if (!row.IsColumnEmpty(26))
404
+ {
405
+ var secureFlags = row.FieldAsString(26);
406
+ switch (secureFlags)
407
+ {
408
+ case FirewallConstants.IntegerNotSetString:
409
+ break;
410
+ case "0":
411
+ firewallException.Add(new XAttribute("IPSecSecureFlags", "None"));
412
+ break;
413
+ case "1":
414
+ firewallException.Add(new XAttribute("IPSecSecureFlags", "NoEncapsulation"));
415
+ break;
416
+ case "2":
417
+ firewallException.Add(new XAttribute("IPSecSecureFlags", "WithIntegrity"));
418
+ break;
419
+ case "3":
420
+ firewallException.Add(new XAttribute("IPSecSecureFlags", "NegotiateEncryption"));
421
+ break;
422
+ case "4":
423
+ firewallException.Add(new XAttribute("IPSecSecureFlags", "Encrypt"));
424
+ break;
425
+ default:
426
+ firewallException.Add(new XAttribute("IPSecSecureFlags", secureFlags));
427
+ break;
428
+ }
429
+ }
430
+ }
431
+
432
this.DecompilerHelper.IndexElement(row, firewallException);
433
}
434
}
@@ -183,7 +439,34 @@ namespace WixToolset.Firewall
439
new XAttribute("Value", address)
440
);
441
186
- firewallException.AddAfterSelf(remoteAddress);
442
+ firewallException.Add(remoteAddress);
443
+ }
444
+
445
+ private static void AddInterfaceType(XElement firewallException, string type)
446
+ {
447
+ var interfaceType = new XElement(FirewallConstants.InterfaceTypeName,
448
+ new XAttribute("Value", type)
449
+ );
450
+
451
+ firewallException.Add(interfaceType);
452
+ }
453
+
454
+ private static void AddLocalAddress(XElement firewallException, string address)
455
+ {
456
+ var localAddress = new XElement(FirewallConstants.LocalAddressName,
457
+ new XAttribute("Value", address)
458
+ );
459
+
460
+ firewallException.Add(localAddress);
461
+ }
462
+
463
+ private static void AddInterface(XElement firewallException, string value)
464
+ {
465
+ var interfaceName = new XElement(FirewallConstants.InterfaceName,
466
+ new XAttribute("Name", value)
467
+ );
468
+
469
+ firewallException.Add(interfaceName);
470
}
471
472
private static XAttribute AttributeIfNotNull(string name, bool value)
src/ext/Firewall/wixext/FirewallErrors.cs
+23
-6
@@ -12,11 +12,6 @@ namespace WixToolset.Firewall
12
return Message(sourceLineNumbers, Ids.IllegalRemoteAddressWithScopeAttribute, "The RemoteAddress element cannot be specified because its parent FirewallException already specified the Scope attribute. To use RemoteAddress elements, omit the Scope attribute.");
13
}
14
15
- public static Message NoExceptionSpecified(SourceLineNumber sourceLineNumbers)
16
- {
17
- return Message(sourceLineNumbers, Ids.NoExceptionSpecified, "The FirewallException element doesn't identify the target of the firewall exception. To create an application exception, nest the FirewallException element under a File element or provide a value for the File or Program attributes. To create a port exception, provide a value for the Port attribute.");
18
- }
19
-
15
private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
16
{
17
return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
@@ -27,10 +22,32 @@ namespace WixToolset.Firewall
22
return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
23
}
24
25
+ public static Message IllegalInterfaceWithInterfaceAttribute(SourceLineNumber sourceLineNumbers)
26
+ {
27
+ return Message(sourceLineNumbers, Ids.IllegalInterfaceWithInterfaceAttribute, "The Interface element cannot be specified because its parent FirewallException already specified the Interface attribute. To use Interface elements, omit the Interface attribute.");
28
+ }
29
+
30
+ public static Message IllegalInterfaceTypeWithInterfaceTypeAttribute(SourceLineNumber sourceLineNumbers)
31
+ {
32
+ return Message(sourceLineNumbers, Ids.IllegalInterfaceTypeWithInterfaceTypeAttribute, "The InterfaceType element cannot be specified because its parent FirewallException already specified the InterfaceType attribute. To use InterfaceType elements, omit the InterfaceType attribute.");
33
+ }
34
+
35
+ public static Message IllegalInterfaceTypeWithInterfaceTypeAll(SourceLineNumber sourceLineNumbers)
36
+ {
37
+ return Message(sourceLineNumbers, Ids.IllegalInterfaceTypeWithInterfaceTypeAll, "The InterfaceType element cannot be specified because its parent FirewallException contains another InterfaceType element with value 'All'.");
38
+ }
39
+ public static Message IllegalLocalAddressWithLocalScopeAttribute(SourceLineNumber sourceLineNumbers)
40
+ {
41
+ return Message(sourceLineNumbers, Ids.IllegalLocalAddressWithLocalScopeAttribute, "The LocalAddress element cannot be specified because its parent FirewallException already specified the LocalScope attribute. To use LocalAddress elements, omit the LocalScope attribute.");
42
+ }
43
+
44
public enum Ids
45
{
46
IllegalRemoteAddressWithScopeAttribute = 6401,
33
- NoExceptionSpecified = 6403,
47
+ IllegalInterfaceWithInterfaceAttribute = 6402,
48
+ IllegalInterfaceTypeWithInterfaceTypeAttribute = 6404,
49
+ IllegalInterfaceTypeWithInterfaceTypeAll = 6405,
50
+ IllegalLocalAddressWithLocalScopeAttribute = 6406,
51
}
52
}
53
}
src/ext/Firewall/wixext/FirewallTableDefinitions.cs
+22
-6
@@ -13,15 +13,31 @@ namespace WixToolset.Firewall
13
{
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),
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),
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"),
16
+ new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: true, 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, maxValue: 65535, description: "Local Port number.", modularizeType: ColumnModularizeType.Property),
18
+ new ColumnDefinition("Protocol", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 255, description: "Protocol (6=TCP; 17=UDP). https://www.iana.org/assignments/protocol-numbers", 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"),
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)."),
20
+ new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1; IgnoreUpdates=2; EnableOnChange=4; INetFwRule2=8; INetFwRule3=16"),
21
+ new ColumnDefinition("Profile", ColumnType.String, 4, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all).", modularizeType: ColumnModularizeType.Property),
22
new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the firewall configuration.", modularizeType: ColumnModularizeType.Column),
23
new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."),
24
- new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"),
24
+ new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"),
25
+ new ColumnDefinition("Action", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "Action (0=Block; 1=Allow).", modularizeType: ColumnModularizeType.Property),
26
+ new ColumnDefinition("EdgeTraversal", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 3, description: "Edge traversal (0=Deny; 1=Allow; 2=DeferToApp; 3=DeferToUser).", modularizeType: ColumnModularizeType.Property),
27
+ new ColumnDefinition("Enabled", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "Enabled (0=Disabled; 1=Enabled).", modularizeType: ColumnModularizeType.Property),
28
+ new ColumnDefinition("Grouping", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The group to which the rule belongs.", modularizeType: ColumnModularizeType.Property),
29
+ new ColumnDefinition("IcmpTypesAndCodes", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Comma separated list of ICMP types and codes separated by colons.", modularizeType: ColumnModularizeType.Property),
30
+ new ColumnDefinition("Interfaces", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "A list of network interfaces separated by a pipe character.", modularizeType: ColumnModularizeType.Property),
31
+ new ColumnDefinition("InterfaceTypes", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Comma separated list of interface types (combination of Wireless,Lan,RemoteAccess or All).", modularizeType: ColumnModularizeType.Property),
32
+ new ColumnDefinition("LocalAddresses", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Local address to accept incoming connections on.", modularizeType: ColumnModularizeType.Property),
33
+ new ColumnDefinition("RemotePort", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, maxValue: 65535, description: "Remote Port number.", modularizeType: ColumnModularizeType.Property),
34
+ new ColumnDefinition("ServiceName", ColumnType.String, 256, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Windows Service short name.", modularizeType: ColumnModularizeType.Property),
35
+ new ColumnDefinition("LocalAppPackageId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Package identifier or the app container identifier of a process.", modularizeType: ColumnModularizeType.Property),
36
+ new ColumnDefinition("LocalUserAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of authorized local users for an app container.", modularizeType: ColumnModularizeType.Property),
37
+ new ColumnDefinition("LocalUserOwner", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "SID of the user who is the owner of the rule.", modularizeType: ColumnModularizeType.Property),
38
+ new ColumnDefinition("RemoteMachineAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of remote computers which are authorized to access an app container.", modularizeType: ColumnModularizeType.Property),
39
+ new ColumnDefinition("RemoteUserAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of remote users who are authorized to access an app container.", modularizeType: ColumnModularizeType.Property),
40
+ new ColumnDefinition("SecureFlags", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "NET_FW_AUTHENTICATE_TYPE IPsec verification level.", modularizeType: ColumnModularizeType.Property),
41
},
42
symbolIdIsPrimaryKey: true
43
);
src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
+135
-7
@@ -14,13 +14,29 @@ namespace WixToolset.Firewall
14
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Name), IntermediateFieldType.String),
15
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteAddresses), IntermediateFieldType.String),
16
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Port), IntermediateFieldType.String),
17
- new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.Number),
17
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.String),
18
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Program), IntermediateFieldType.String),
19
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Attributes), IntermediateFieldType.Number),
20
- new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.Number),
20
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.String),
21
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ComponentRef), IntermediateFieldType.String),
22
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Description), IntermediateFieldType.String),
23
new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Direction), IntermediateFieldType.Number),
24
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Action), IntermediateFieldType.String),
25
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.EdgeTraversal), IntermediateFieldType.String),
26
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Enabled), IntermediateFieldType.String),
27
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Grouping), IntermediateFieldType.String),
28
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.IcmpTypesAndCodes), IntermediateFieldType.String),
29
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Interfaces), IntermediateFieldType.String),
30
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.InterfaceTypes), IntermediateFieldType.String),
31
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalAddresses), IntermediateFieldType.String),
32
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemotePort), IntermediateFieldType.String),
33
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ServiceName), IntermediateFieldType.String),
34
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalAppPackageId), IntermediateFieldType.String),
35
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalUserAuthorizedList), IntermediateFieldType.String),
36
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalUserOwner), IntermediateFieldType.String),
37
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList), IntermediateFieldType.String),
38
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList), IntermediateFieldType.String),
39
+ new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.SecureFlags), IntermediateFieldType.String),
40
},
41
typeof(WixFirewallExceptionSymbol));
42
}
@@ -42,6 +58,22 @@ namespace WixToolset.Firewall.Symbols
58
ComponentRef,
59
Description,
60
Direction,
61
+ Action,
62
+ EdgeTraversal,
63
+ Enabled,
64
+ Grouping,
65
+ IcmpTypesAndCodes,
66
+ Interfaces,
67
+ InterfaceTypes,
68
+ LocalAddresses,
69
+ RemotePort,
70
+ ServiceName,
71
+ LocalAppPackageId,
72
+ LocalUserAuthorizedList,
73
+ LocalUserOwner,
74
+ RemoteMachineAuthorizedList,
75
+ RemoteUserAuthorizedList,
76
+ SecureFlags,
77
}
78
79
public class WixFirewallExceptionSymbol : IntermediateSymbol
@@ -74,9 +106,9 @@ namespace WixToolset.Firewall.Symbols
106
set => this.Set((int)WixFirewallExceptionSymbolFields.Port, value);
107
}
108
77
- public int? Protocol
109
+ public string Protocol
110
{
79
- get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsNullableNumber();
111
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsString();
112
set => this.Set((int)WixFirewallExceptionSymbolFields.Protocol, value);
113
}
114
@@ -92,9 +124,9 @@ namespace WixToolset.Firewall.Symbols
124
set => this.Set((int)WixFirewallExceptionSymbolFields.Attributes, value);
125
}
126
95
- public int Profile
127
+ public string Profile
128
{
97
- get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsNumber();
129
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsString();
130
set => this.Set((int)WixFirewallExceptionSymbolFields.Profile, value);
131
}
132
@@ -115,5 +147,101 @@ namespace WixToolset.Firewall.Symbols
147
get => this.Fields[(int)WixFirewallExceptionSymbolFields.Direction].AsNumber();
148
set => this.Set((int)WixFirewallExceptionSymbolFields.Direction, value);
149
}
150
+
151
+ public string Action
152
+ {
153
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Action].AsString();
154
+ set => this.Set((int)WixFirewallExceptionSymbolFields.Action, value);
155
+ }
156
+
157
+ public string EdgeTraversal
158
+ {
159
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.EdgeTraversal].AsString();
160
+ set => this.Set((int)WixFirewallExceptionSymbolFields.EdgeTraversal, value);
161
+ }
162
+
163
+ public string Enabled
164
+ {
165
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Enabled].AsString();
166
+ set => this.Set((int)WixFirewallExceptionSymbolFields.Enabled, value);
167
+ }
168
+
169
+ public string Grouping
170
+ {
171
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Grouping].AsString();
172
+ set => this.Set((int)WixFirewallExceptionSymbolFields.Grouping, value);
173
+ }
174
+
175
+ public string IcmpTypesAndCodes
176
+ {
177
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.IcmpTypesAndCodes].AsString();
178
+ set => this.Set((int)WixFirewallExceptionSymbolFields.IcmpTypesAndCodes, value);
179
+ }
180
+
181
+ public string Interfaces
182
+ {
183
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.Interfaces].AsString();
184
+ set => this.Set((int)WixFirewallExceptionSymbolFields.Interfaces, value);
185
+ }
186
+
187
+ public string InterfaceTypes
188
+ {
189
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.InterfaceTypes].AsString();
190
+ set => this.Set((int)WixFirewallExceptionSymbolFields.InterfaceTypes, value);
191
+ }
192
+
193
+ public string LocalAddresses
194
+ {
195
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalAddresses].AsString();
196
+ set => this.Set((int)WixFirewallExceptionSymbolFields.LocalAddresses, value);
197
+ }
198
+
199
+ public string RemotePort
200
+ {
201
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemotePort].AsString();
202
+ set => this.Set((int)WixFirewallExceptionSymbolFields.RemotePort, value);
203
+ }
204
+
205
+ public string ServiceName
206
+ {
207
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.ServiceName].AsString();
208
+ set => this.Set((int)WixFirewallExceptionSymbolFields.ServiceName, value);
209
+ }
210
+
211
+ public string LocalAppPackageId
212
+ {
213
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalAppPackageId].AsString();
214
+ set => this.Set((int)WixFirewallExceptionSymbolFields.LocalAppPackageId, value);
215
+ }
216
+
217
+ public string LocalUserAuthorizedList
218
+ {
219
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalUserAuthorizedList].AsString();
220
+ set => this.Set((int)WixFirewallExceptionSymbolFields.LocalUserAuthorizedList, value);
221
+ }
222
+
223
+ public string LocalUserOwner
224
+ {
225
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalUserOwner].AsString();
226
+ set => this.Set((int)WixFirewallExceptionSymbolFields.LocalUserOwner, value);
227
+ }
228
+
229
+ public string RemoteMachineAuthorizedList
230
+ {
231
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList].AsString();
232
+ set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList, value);
233
+ }
234
+
235
+ public string RemoteUserAuthorizedList
236
+ {
237
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList].AsString();
238
+ set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList, value);
239
+ }
240
+
241
+ public string SecureFlags
242
+ {
243
+ get => this.Fields[(int)WixFirewallExceptionSymbolFields.SecureFlags].AsString();
244
+ set => this.Set((int)WixFirewallExceptionSymbolFields.SecureFlags, value);
245
+ }
246
}
119
-}
\ No newline at end of file
247
+}
src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
+3
-1
@@ -5,9 +5,11 @@
5
<PropertyGroup>
6
<TargetFramework>netstandard2.0</TargetFramework>
7
<RootNamespace>WixToolset.Firewall</RootNamespace>
8
- <Description>WiX Toolset Firewallity Extension</Description>
8
+ <Description>WiX Toolset Firewall Extension</Description>
9
<Title>WiX Toolset Firewall Extension</Title>
10
<DebugType>embedded</DebugType>
11
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
12
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
13
</PropertyGroup>
14
15
<Import Project="..\..\WixExt.props" />
src/ext/Util/wixext/UtilCompiler.cs
+10
-3
@@ -3123,8 +3123,14 @@ namespace WixToolset.Util
3123
// if this element is a child of ServiceInstall then ignore the service name provided.
3124
if ("ServiceInstall" == parentTableName)
3125
{
3126
- // TODO: the ServiceName attribute should not be allowed in this case (the overwriting behavior may confuse users)
3127
- serviceName = parentTableServiceName;
3126
+ if (null == serviceName || parentTableServiceName == serviceName)
3127
+ {
3128
+ serviceName = parentTableServiceName;
3129
+ }
3130
+ else
3131
+ {
3132
+ this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "ServiceName", parentTableName));
3133
+ }
3134
newService = true;
3135
}
3136
else
@@ -3136,7 +3142,8 @@ namespace WixToolset.Util
3142
}
3143
}
3144
3139
- this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
3145
+ var context = new Dictionary<string, string>() { { "ServiceConfigComponentId", componentId }, { "ServiceConfigServiceName", serviceName } };
3146
+ this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element, context);
3147
3148
if (!this.Messaging.EncounteredError)
3149
{
src/internal/SetBuildNumber/Directory.Packages.props.pp
+1
@@ -47,6 +47,7 @@
47
<PackageVersion Include="System.DirectoryServices.AccountManagement" Version="4.7.0" />
48
<PackageVersion Include="System.IO.Compression" Version="4.3.0" />
49
<PackageVersion Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
50
+ <PackageVersion Include="System.Net.NetworkInformation" Version="4.3.0" />
51
<PackageVersion Include="System.Reflection.Metadata" Version="1.6.0" />
52
<PackageVersion Include="System.Security.Principal.Windows" Version="4.7.0" />
53
<PackageVersion Include="System.Text.Encoding.CodePages" Version="4.7.0" />
src/test/burn/WixTestTools/Firewall/RuleDetails.cs
+5
-3
@@ -146,7 +146,9 @@ namespace WixTestTools.Firewall
146
/// This parameter allows the specification of an array of interface LUIDs (locally unique identifiers) supplied as strings.<br/>
147
/// This is commonly used by USB RNDIS (Remote Network Driver Interface Specification) devices to restrict traffic to a specific non-routable interface.<br/>
148
/// Use <b>netsh trace show interfaces</b> to show a list of local interfaces and their LUIDs.<br/>
149
- /// Example: new object[] { "Wi-Fi", "Local Area Connection* 14" }
149
+ /// The interfaces are stored in the registry as GUIDs, but need to be passed to the API as text. eg from the registry<br/>
150
+ /// v2.30|Action=Allow|Active=TRUE|Dir=In|Protocol=6|LPort=23456|IF={423411CD-E627-4A1A-9E1F-C5BE6CD2CC99}|IF={49A98AD0-8379-4079-A445-77066C52E338}|Name=WiXToolset401 Test - 0002|Desc=WiX Toolset firewall exception rule integration test - minimal port properties|<br/>
151
+ /// Example API value: new object[] { "Wi-Fi", "Local Area Connection* 14" }
152
/// </summary>
153
public object[] Interfaces { get; set; }
154
@@ -227,13 +229,13 @@ namespace WixTestTools.Firewall
229
public string LocalUserOwner { get; set; }
230
231
/// <summary>
230
- /// This property is optional. It specifies a list of authorized local users for an app container.<br/>
232
+ /// This property is optional. It specifies a list of authorized local users for an app container (using SDDL).<br/>
233
/// Example: "O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)"
234
/// </summary>
235
public string LocalUserAuthorizedList { get; set; }
236
237
/// <summary>
236
- /// This property is optional. It specifies a list of remote users who are authorized to access an app container.<br/>
238
+ /// This property is optional. It specifies a list of remote users who are authorized to access an app container (using SDDL).<br/>
239
/// </summary>
240
public string RemoteUserAuthorizedList { get; set; }
241
src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/CrossVersionMerge.wixproj
new
+13
@@ -0,0 +1,13 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <SuppressSpecificWarnings>1055;1056</SuppressSpecificWarnings>
5
+ </PropertyGroup>
6
+ <ItemGroup>
7
+ <!-- <ProjectReference Include="..\Module401\Module401.wixproj" /> -->
8
+ <ProjectReference Include="..\ModuleCurrent\ModuleCurrent.wixproj" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <PackageReference Include="WixToolset.Firewall.wixext" />
12
+ </ItemGroup>
13
+</Project>
src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msm
Binary files /dev/null and b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msm differ
src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/package.wxs
new
+35
@@ -0,0 +1,35 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
2
+ <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation"
3
+ UpgradeCode="41B5F815-E7F6-44E0-B92A-AE95DFF683F9" Compressed="yes" Scope="perMachine">
4
+ <MediaTemplate EmbedCab="yes" />
5
+
6
+ <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
7
+
8
+ <Feature Id="ProductFeature" Title="Feature with merged modules">
9
+ <MergeRef Id="TestMsm1" />
10
+ <MergeRef Id="TestMsm2" />
11
+ <ComponentRef Id="FirewallComponent1" />
12
+ </Feature>
13
+ </Package>
14
+
15
+ <Fragment>
16
+ <StandardDirectory Id="ProgramFilesFolder">
17
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage">
18
+ <Merge Id="TestMsm1" Language="1033" SourceFile="Module401.msm" />
19
+ <Merge Id="TestMsm2" Language="1033" SourceFile="ModuleCurrent.msm" />
20
+ </Directory>
21
+ </StandardDirectory>
22
+ </Fragment>
23
+
24
+ <Fragment>
25
+ <Property Id="MSIPORT1" Value="20001" />
26
+ <Property Id="MSIPORT2" Value="20002" />
27
+
28
+ <Component Id="FirewallComponent1" Guid="3E9A6190-3E6B-4BC2-8C84-D89D1549FEBD" Directory="INSTALLFOLDER">
29
+ <File Source="$(sys.SOURCEFILEPATH)">
30
+ <fw:FirewallException Id="FirewallException1" Description="WiX Toolset firewall exception rule integration test - package app" Name="WiXToolset Test - 0026" Scope="any" Port="[MSIPORT1]" />
31
+ </File>
32
+ <fw:FirewallException Id="FirewallException2" Description="WiX Toolset firewall exception rule integration test - package port" Name="WiXToolset Test - 0027" Scope="any" Port="[MSIPORT2]" />
33
+ </Component>
34
+ </Fragment>
35
+</Wix>
src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/FirewallRulesInterfaces.wixproj
new
+13
@@ -0,0 +1,13 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <UpgradeCode>{F153C27F-0236-4A0F-ADB3-50BFC73B4FEA}</UpgradeCode>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <PackageReference Include="WixToolset.Firewall.wixext" />
12
+ </ItemGroup>
13
+</Project>
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/product.wxs
new
+32
@@ -0,0 +1,32 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
5
+ <Fragment>
6
+ <ComponentGroup Id="ProductComponents">
7
+ <ComponentRef Id="FirewallComponent1"/>
8
+ </ComponentGroup>
9
+ </Fragment>
10
+
11
+ <Fragment>
12
+ <Component Id="FirewallComponent1" Guid="08044660-CB5D-4891-8BD5-0CB5BB668D78" Directory="INSTALLFOLDER">
13
+ <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" >
14
+ <fw:FirewallException Id="FirewallException28"
15
+ Description="WiX Toolset firewall exception rule integration test - three interfaces"
16
+ Name="WiXToolset500 Test - 0028" Scope="any" >
17
+ <fw:Interface Name="[INTERFACE1]" />
18
+ <fw:Interface Name="[INTERFACE2]" />
19
+ <fw:Interface Name="[INTERFACE3]" />
20
+ <fw:InterfaceType Value="RemoteAccess" />
21
+ <fw:InterfaceType Value="Lan" />
22
+ <fw:InterfaceType Value="Wireless" />
23
+ </fw:FirewallException>
24
+ </File>
25
+
26
+ <fw:FirewallException Id="FirewallException29"
27
+ Description="WiX Toolset firewall exception rule integration test - one interface"
28
+ Name="WiXToolset500 Test - 0029" Scope="any" Port="29292" Interface="[INTERFACE1]" InterfaceType="[INTERFACETYPE]" >
29
+ </fw:FirewallException>
30
+ </Component>
31
+ </Fragment>
32
+</Wix>
src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/FirewallRulesProperties.wixproj
new
+13
@@ -0,0 +1,13 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <UpgradeCode>{DC2C3CDC-112F-40A8-A7B4-2C7B758F4F94}</UpgradeCode>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <PackageReference Include="WixToolset.Firewall.wixext" />
12
+ </ItemGroup>
13
+</Project>
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/product.wxs
new
+57
@@ -0,0 +1,57 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
5
+ <Fragment>
6
+ <ComponentGroup Id="ProductComponents">
7
+ <ComponentRef Id="FirewallComponent1"/>
8
+ </ComponentGroup>
9
+ </Fragment>
10
+
11
+ <Fragment>
12
+ <Component Id="FirewallComponent1" Guid="A1553D10-BEB7-4E60-A0DC-6F1EEE5A1719" Directory="INSTALLFOLDER">
13
+ <fw:FirewallException
14
+ Name="WiXToolset Test - 0028" OnUpdate="EnableOnly"
15
+ Port="[LOCALPORT]"
16
+ Protocol="[PROTOCOL]"
17
+ Program="[PROGRAM]"
18
+ Profile="[PROFILE]"
19
+ Description="[DESCRIPTION]"
20
+ Scope="[REMOTESCOPE]"
21
+ EdgeTraversal="[EDGETRAVERSAL]"
22
+ Enabled="[ENABLED]"
23
+ Grouping="[GROUPING]"
24
+ IcmpTypesAndCodes="[ICMPTYPES]"
25
+ Interface="[INTERFACE]"
26
+ InterfaceType="[INTERFACETYPE]"
27
+ LocalScope="[LOCALSCOPE]"
28
+ RemotePort="[REMOTEPORT]"
29
+ Service="[SERVICE]"
30
+ LocalAppPackageId="[PACKAGEID]"
31
+ LocalUserAuthorizedList="[LOCALUSERS]"
32
+ LocalUserOwner="[LOCALOWNER]"
33
+ RemoteMachineAuthorizedList="[REMOTEMACHINES]"
34
+ RemoteUserAuthorizedList="[REMOTEUSERS]"
35
+ IPSecSecureFlags="[SECUREFLAGS]"
36
+ />
37
+
38
+ <fw:FirewallException Name="WiXToolset Test - 0029" OnUpdate="DoNothing" >
39
+ <fw:RemoteAddress Value="[REMOTEADDRESS]" />
40
+ <fw:LocalAddress Value="[LOCALADDRESS]" />
41
+ <fw:InterfaceType Value="[INTERFACETYPE]" />
42
+ <fw:Interface Name="[INTERFACE]" />
43
+ </fw:FirewallException>
44
+
45
+ <fw:FirewallException Name="WiXToolset Test - 0030" >
46
+ <fw:RemoteAddress Value="[REMOTEADDRESS1]" />
47
+ <fw:RemoteAddress Value="[REMOTEADDRESS2]" />
48
+ <fw:LocalAddress Value="[LOCALADDRESS1]" />
49
+ <fw:LocalAddress Value="[LOCALADDRESS2]" />
50
+ <fw:InterfaceType Value="[INTERFACETYPE1]" />
51
+ <fw:InterfaceType Value="[INTERFACETYPE2]" />
52
+ <fw:Interface Name="[INTERFACE1]" />
53
+ <fw:Interface Name="[INTERFACE2]" />
54
+ </fw:FirewallException>
55
+ </Component>
56
+ </Fragment>
57
+</Wix>
src/test/msi/TestData/FirewallExtensionTests/Module401/Module401.wixproj
new
+10
@@ -0,0 +1,10 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Module</OutputType>
5
+ <SuppressSpecificWarnings>1072</SuppressSpecificWarnings>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <PackageReference Include="WixToolset.Firewall.wixext"/><!--VersionOverride="4.0.1"-->
9
+ </ItemGroup>
10
+</Project>
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/Module401/data/test.txt
new
+1
@@ -0,0 +1 @@
1
+This is test.txt.
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/Module401/module.wxs
new
+36
@@ -0,0 +1,36 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall" >
2
+ <Module Id="MergeModule1" Language="1033" Version="1.0.0.0" Guid="4B2C61BF-59F5-453B-98E3-3389F681EA00">
3
+ <SummaryInformation Manufacturer="Module 4.0.1 Manufacturer" />
4
+
5
+ <Property Id="MODULE401PORT1" Value="40101" />
6
+ <Property Id="MODULE401PORT2" Value="40102" />
7
+ <Property Id="MODULE401PORT3" Value="40103" />
8
+ <Property Id="MODULE401PORT4" Value="40104" />
9
+
10
+ <Directory Id="MergeRedirectFolder">
11
+ <Component Id="ModuleComponent1" Guid="257F9283-1334-423C-A7E7-FEE848BCD37F">
12
+ <File Id="File1" Name="file1.txt" Source="data/test.txt">
13
+ <fw:FirewallException Id="FirewallException1"
14
+ Description="WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - app"
15
+ Name="WiXToolset401 Test - 0018" Scope="any" Port="[MODULE401PORT1]" />
16
+ </File>
17
+ <fw:FirewallException Id="FirewallException2"
18
+ Description="WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - port"
19
+ Name="WiXToolset401 Test - 0019" Scope="any" Port="[MODULE401PORT2]" />
20
+ </Component>
21
+ </Directory>
22
+
23
+ <Directory Id="NotTheMergeRedirectFolder">
24
+ <Component Id="ModuleComponent2" Guid="48A2D573-0ADB-4010-84E3-96C3D6803E90">
25
+ <File Id="File2" Name="file2.txt" Source="data/test.txt">
26
+ <fw:FirewallException Id="FirewallException3"
27
+ Description="WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - app"
28
+ Name="WiXToolset401 Test - 0020" Scope="any" Port="[MODULE401PORT3]" />
29
+ </File>
30
+ <fw:FirewallException Id="FirewallException4"
31
+ Description="WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - port"
32
+ Name="WiXToolset401 Test - 0021" Scope="any" Port="[MODULE401PORT4]" />
33
+ </Component>
34
+ </Directory>
35
+ </Module>
36
+</Wix>
src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/ModuleCurrent.wixproj
new
+10
@@ -0,0 +1,10 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Module</OutputType>
5
+ <SuppressSpecificWarnings>1072</SuppressSpecificWarnings>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <PackageReference Include="WixToolset.Firewall.wixext" />
9
+ </ItemGroup>
10
+</Project>
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/data/test.txt
new
+1
@@ -0,0 +1 @@
1
+This is test.txt.
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/module.wxs
new
+36
@@ -0,0 +1,36 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall" >
2
+ <Module Id="MergeModule1" Language="1033" Version="1.0.0.0" Guid="44FA5DBE-2413-436E-99B3-A0751D6EB420">
3
+ <SummaryInformation Manufacturer="Example Company - Module Current" />
4
+
5
+ <Property Id="MODULECURRENTPORT1" Value="50001" />
6
+ <Property Id="MODULECURRENTPORT2" Value="50002" />
7
+ <Property Id="MODULECURRENTPORT3" Value="50003" />
8
+ <Property Id="MODULECURRENTPORT4" Value="50004" />
9
+
10
+ <Directory Id="MergeRedirectFolder">
11
+ <Component Id="ModuleComponent1" Guid="EB7B8A63-85C4-4ABB-B9DA-33AECAFE38F7">
12
+ <File Id="File1" Name="file1.txt" Source="data/test.txt">
13
+ <fw:FirewallException Id="FirewallException1"
14
+ Description="WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - app"
15
+ Name="WiXToolset Test - 0022" Scope="any" Port="[MODULECURRENTPORT1]" />
16
+ </File>
17
+ <fw:FirewallException Id="FirewallException2"
18
+ Description="WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - port"
19
+ Name="WiXToolset Test - 0023" Scope="any" Port="[MODULECURRENTPORT2]" />
20
+ </Component>
21
+ </Directory>
22
+
23
+ <Directory Id="NotTheMergeRedirectFolder">
24
+ <Component Id="ModuleComponent2" Guid="0C9DD4FC-5A54-4E96-830D-DDE27B3017B5">
25
+ <File Id="File2" Name="file2.txt" Source="data/test.txt">
26
+ <fw:FirewallException Id="FirewallException3"
27
+ Description="WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - app"
28
+ Name="WiXToolset Test - 0024" Scope="any" Port="[MODULECURRENTPORT3]" />
29
+ </File>
30
+ <fw:FirewallException Id="FirewallException4"
31
+ Description="WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - port"
32
+ Name="WiXToolset Test - 0025" Scope="any" Port="[MODULECURRENTPORT4]" />
33
+ </Component>
34
+ </Directory>
35
+ </Module>
36
+</Wix>
src/test/msi/TestData/FirewallExtensionTests/NestedService/NestedService.wixproj
new
+14
@@ -0,0 +1,14 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <UpgradeCode>{80635798-F904-4C4E-81D8-27A5106F3998}</UpgradeCode>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <PackageReference Include="WixToolset.Firewall.wixext" />
12
+ <PackageReference Include="WixToolset.Util.wixext" />
13
+ </ItemGroup>
14
+</Project>
\ No newline at end of file
src/test/msi/TestData/FirewallExtensionTests/NestedService/product.wxs
new
+25
@@ -0,0 +1,25 @@
1
+<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
5
+ <Fragment>
6
+ <ComponentGroup Id="ProductComponents">
7
+ <ComponentRef Id="FirewallComponent1"/>
8
+ </ComponentGroup>
9
+ </Fragment>
10
+
11
+ <Fragment>
12
+ <Component Id="FirewallComponent1" Guid="FD6E696A-8C42-49BF-B686-0DA5CD4B2C5A" Directory="INSTALLFOLDER" >
13
+ <fw:FirewallException Id="FirewallException1" Description="WiX Toolset firewall exception rule integration test - service property"
14
+ Name="WiXToolset Test - 0031" Service="Spooler"/>
15
+ <util:ServiceConfig ServiceName="Spooler" FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" >
16
+ <fw:FirewallException Id="FirewallException2" Description="WiX Toolset firewall exception rule integration test - ServiceConfig"
17
+ Name="WiXToolset Test - 0032" />
18
+ </util:ServiceConfig>
19
+ <ServiceInstall Name="WixTestFirewallSrv" Type="ownProcess" Start="disabled" ErrorControl="ignore" Vital="no" Arguments="%WINDIR%\System32\spoolsv.exe" >
20
+ <fw:FirewallException Id="FirewallException3" Description="WiX Toolset firewall exception rule integration test - ServiceInstall"
21
+ Name="WiXToolset Test - 0033" />
22
+ </ServiceInstall>
23
+ </Component>
24
+ </Fragment>
25
+</Wix>
src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
+623
-17
@@ -4,6 +4,8 @@ namespace WixToolsetTest.MsiE2E
4
{
5
using System;
6
using System.IO;
7
+ using System.Linq;
8
+ using System.Net.NetworkInformation;
9
using NetFwTypeLib;
10
using WixTestTools;
11
using WixTestTools.Firewall;
@@ -37,8 +39,8 @@ namespace WixToolsetTest.MsiE2E
39
ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
40
Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
41
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
40
- EdgeTraversal = true,
41
- EdgeTraversalOptions = 1,
42
+ EdgeTraversal = false,
43
+ EdgeTraversalOptions = 0,
44
Enabled = true,
45
InterfaceTypes = "All",
46
LocalAddresses = "*",
@@ -124,8 +126,8 @@ namespace WixToolsetTest.MsiE2E
126
ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
127
Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
128
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
127
- EdgeTraversal = true,
128
- EdgeTraversalOptions = 1,
129
+ EdgeTraversal = false,
130
+ EdgeTraversalOptions = 0,
131
Enabled = true,
132
InterfaceTypes = "All",
133
LocalAddresses = "*",
@@ -187,8 +189,8 @@ namespace WixToolsetTest.MsiE2E
189
ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
190
Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
191
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
190
- EdgeTraversal = true,
191
- EdgeTraversalOptions = 1,
192
+ EdgeTraversal = false,
193
+ EdgeTraversalOptions = 0,
194
Enabled = true,
195
InterfaceTypes = "All",
196
LocalAddresses = "*",
@@ -213,8 +215,8 @@ namespace WixToolsetTest.MsiE2E
215
ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("DynamicFirewallRules", "product.wxs")),
216
Description = "WiX Toolset firewall exception rule integration test - dynamic app description 9999",
217
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
216
- EdgeTraversal = true,
217
- EdgeTraversalOptions = 1,
218
+ EdgeTraversal = false,
219
+ EdgeTraversalOptions = 0,
220
Enabled = true,
221
InterfaceTypes = "All",
222
LocalAddresses = "*",
@@ -255,8 +257,8 @@ namespace WixToolsetTest.MsiE2E
257
ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("windir"), "system32", "9999.exe"),
258
Description = "WiX Toolset firewall exception rule integration test - dynamic Name 9999",
259
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
258
- EdgeTraversal = true,
259
- EdgeTraversalOptions = 1,
260
+ EdgeTraversal = false,
261
+ EdgeTraversalOptions = 0,
262
Enabled = true,
263
InterfaceTypes = "All",
264
LocalAddresses = "*",
@@ -285,10 +287,10 @@ namespace WixToolsetTest.MsiE2E
287
var log1 = product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
288
289
Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0006 pipe"));
288
- Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized apps list"));
290
+ Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add firewall exception 'WiXToolset401 Test - 0006 pipe' to the list"));
291
292
Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0007 pipe"));
291
- Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized ports list"));
293
+ Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add firewall exception 'WiXToolset401 Test - 0007 pipe' to the list"));
294
295
var expected = new RuleDetails("WiXToolset401 Test - 0008 removal")
296
{
@@ -296,8 +298,8 @@ namespace WixToolsetTest.MsiE2E
298
ApplicationName = "test.exe",
299
Description = "WiX Toolset firewall exception rule integration test - removal test",
300
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
299
- EdgeTraversal = true,
300
- EdgeTraversalOptions = 1,
301
+ EdgeTraversal = false,
302
+ EdgeTraversalOptions = 0,
303
Enabled = true,
304
InterfaceTypes = "All",
305
LocalPorts = "52390",
@@ -313,7 +315,7 @@ namespace WixToolsetTest.MsiE2E
315
Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0008 removal");
316
317
var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1");
316
- Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall rule"));
318
+ Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall exception for name"));
319
}
320
321
[RuntimeFact]
@@ -370,8 +372,8 @@ namespace WixToolsetTest.MsiE2E
372
ApplicationName = "test.exe",
373
Description = "WiX Toolset firewall exception rule integration test - ports can only be specified if protocol is TCP or UDP",
374
Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
373
- EdgeTraversal = true,
374
- EdgeTraversalOptions = 1,
375
+ EdgeTraversal = false,
376
+ EdgeTraversalOptions = 0,
377
Enabled = true,
378
InterfaceTypes = "All",
379
LocalAddresses = "*",
@@ -532,5 +534,609 @@ namespace WixToolsetTest.MsiE2E
534
Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0016"));
535
Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0017"));
536
}
537
+
538
+ [RuntimeFact]
539
+ public void CanInstallAndUninstallFirewallRulesWithInterfaces()
540
+ {
541
+ var names = NetworkInterface.GetAllNetworkInterfaces()
542
+ .Take(3)
543
+ .Select(ni => ni.Name);
544
+
545
+ var props = names.Select((name, idx) => $"INTERFACE{idx + 1}=\"{name}\"")
546
+ .Concat(new[] { "INTERFACETYPE=Lan" }).ToArray();
547
+
548
+ var product = this.CreatePackageInstaller("FirewallRulesInterfaces");
549
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, props);
550
+
551
+ var expected1 = new RuleDetails("WiXToolset500 Test - 0028")
552
+ {
553
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
554
+ ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRulesInterfaces", "product.wxs")),
555
+ Description = "WiX Toolset firewall exception rule integration test - three interfaces",
556
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
557
+ EdgeTraversal = false,
558
+ EdgeTraversalOptions = 0,
559
+ Enabled = true,
560
+ InterfaceTypes = "Lan,Wireless,RemoteAccess",
561
+ Interfaces = names.ToArray<object>(),
562
+ LocalAddresses = "*",
563
+ Profiles = Int32.MaxValue,
564
+ Protocol = 256,
565
+ RemoteAddresses = "*",
566
+ SecureFlags = 0,
567
+ };
568
+
569
+ Verifier.VerifyFirewallRule("WiXToolset500 Test - 0028", expected1);
570
+
571
+ var expected2 = new RuleDetails("WiXToolset500 Test - 0029")
572
+ {
573
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
574
+ Description = "WiX Toolset firewall exception rule integration test - one interface",
575
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
576
+ EdgeTraversal = false,
577
+ EdgeTraversalOptions = 0,
578
+ Enabled = true,
579
+ InterfaceTypes = "Lan",
580
+ Interfaces = names.Take(1).ToArray<object>(),
581
+ LocalAddresses = "*",
582
+ LocalPorts = "29292",
583
+ Profiles = Int32.MaxValue,
584
+ Protocol = 6,
585
+ RemoteAddresses = "*",
586
+ RemotePorts = "*",
587
+ SecureFlags = 0,
588
+ };
589
+
590
+ Verifier.VerifyFirewallRule("WiXToolset500 Test - 0029", expected2);
591
+
592
+ props = names.Take(1).Select((name, idx) => $"INTERFACE{idx + 2}=\"{name}\"").ToArray();
593
+
594
+ product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, props);
595
+
596
+ var expected3 = new RuleDetails("WiXToolset500 Test - 0028")
597
+ {
598
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
599
+ ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRulesInterfaces", "product.wxs")),
600
+ Description = "WiX Toolset firewall exception rule integration test - three interfaces",
601
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
602
+ EdgeTraversal = false,
603
+ EdgeTraversalOptions = 0,
604
+ Enabled = true,
605
+ InterfaceTypes = "Lan,Wireless,RemoteAccess",
606
+ Interfaces = names.Take(1).ToArray<object>(),
607
+ LocalAddresses = "*",
608
+ Profiles = Int32.MaxValue,
609
+ Protocol = 256,
610
+ RemoteAddresses = "*",
611
+ SecureFlags = 0,
612
+ };
613
+
614
+ Verifier.VerifyFirewallRule("WiXToolset500 Test - 0028", expected3);
615
+
616
+ var expected4 = new RuleDetails("WiXToolset500 Test - 0029")
617
+ {
618
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
619
+ Description = "WiX Toolset firewall exception rule integration test - one interface",
620
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
621
+ EdgeTraversal = false,
622
+ EdgeTraversalOptions = 0,
623
+ Enabled = true,
624
+ InterfaceTypes = "All",
625
+ LocalAddresses = "*",
626
+ LocalPorts = "29292",
627
+ Profiles = Int32.MaxValue,
628
+ Protocol = 6,
629
+ RemoteAddresses = "*",
630
+ RemotePorts = "*",
631
+ SecureFlags = 0,
632
+ };
633
+
634
+ Verifier.VerifyFirewallRule("WiXToolset500 Test - 0029", expected4);
635
+
636
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
637
+
638
+ // verify the firewall exceptions have been removed.
639
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset500 Test - 0028"));
640
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset500 Test - 0029"));
641
+ }
642
+
643
+ [RuntimeFact]
644
+ public void CanInstallAndUninstallFirewallRulesPackagedByDifferentModules()
645
+ {
646
+ var product = this.CreatePackageInstaller("CrossVersionMerge");
647
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
648
+
649
+ // Validate new firewall exception details.
650
+ var expected1 = new RuleDetails("WiXToolset401 Test - 0018")
651
+ {
652
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
653
+ ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file1.txt"),
654
+ Description = "WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - app",
655
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
656
+ EdgeTraversal = true,
657
+ EdgeTraversalOptions = 1,
658
+ Enabled = true,
659
+ InterfaceTypes = "All",
660
+ LocalAddresses = "*",
661
+ LocalPorts = "40101",
662
+ Profiles = Int32.MaxValue,
663
+ Protocol = 6,
664
+ RemoteAddresses = "*",
665
+ RemotePorts = "*",
666
+ SecureFlags = 0,
667
+ };
668
+
669
+ Verifier.VerifyFirewallRule("WiXToolset401 Test - 0018", expected1);
670
+
671
+ var expected2 = new RuleDetails("WiXToolset401 Test - 0019")
672
+ {
673
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
674
+ Description = "WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - port",
675
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
676
+ EdgeTraversal = false,
677
+ EdgeTraversalOptions = 0,
678
+ Enabled = true,
679
+ InterfaceTypes = "All",
680
+ LocalAddresses = "*",
681
+ LocalPorts = "40102",
682
+ Profiles = Int32.MaxValue,
683
+ Protocol = 6,
684
+ RemoteAddresses = "*",
685
+ RemotePorts = "*",
686
+ SecureFlags = 0,
687
+ };
688
+
689
+ Verifier.VerifyFirewallRule("WiXToolset401 Test - 0019", expected2);
690
+
691
+ var expected3 = new RuleDetails("WiXToolset401 Test - 0020")
692
+ {
693
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
694
+ ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file2.txt"),
695
+ Description = "WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - app",
696
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
697
+ EdgeTraversal = true,
698
+ EdgeTraversalOptions = 1,
699
+ Enabled = true,
700
+ InterfaceTypes = "All",
701
+ LocalAddresses = "*",
702
+ LocalPorts = "40103",
703
+ Profiles = Int32.MaxValue,
704
+ Protocol = 6,
705
+ RemoteAddresses = "*",
706
+ RemotePorts = "*",
707
+ SecureFlags = 0,
708
+ };
709
+
710
+ Verifier.VerifyFirewallRule("WiXToolset401 Test - 0020", expected3);
711
+
712
+ var expected4 = new RuleDetails("WiXToolset401 Test - 0021")
713
+ {
714
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
715
+ Description = "WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - port",
716
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
717
+ EdgeTraversal = false,
718
+ EdgeTraversalOptions = 0,
719
+ Enabled = true,
720
+ InterfaceTypes = "All",
721
+ LocalAddresses = "*",
722
+ LocalPorts = "40104",
723
+ Profiles = Int32.MaxValue,
724
+ Protocol = 6,
725
+ RemoteAddresses = "*",
726
+ RemotePorts = "*",
727
+ SecureFlags = 0,
728
+ };
729
+
730
+ Verifier.VerifyFirewallRule("WiXToolset401 Test - 0021", expected4);
731
+
732
+ var expected5 = new RuleDetails("WiXToolset Test - 0022")
733
+ {
734
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
735
+ ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file1.txt"),
736
+ Description = "WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - app",
737
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
738
+ EdgeTraversal = false,
739
+ EdgeTraversalOptions = 0,
740
+ Enabled = true,
741
+ InterfaceTypes = "All",
742
+ LocalAddresses = "*",
743
+ LocalPorts = "50001",
744
+ Profiles = Int32.MaxValue,
745
+ Protocol = 6,
746
+ RemoteAddresses = "*",
747
+ RemotePorts = "*",
748
+ SecureFlags = 0,
749
+ };
750
+
751
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0022", expected5);
752
+
753
+ var expected6 = new RuleDetails("WiXToolset Test - 0023")
754
+ {
755
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
756
+ Description = "WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - port",
757
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
758
+ EdgeTraversal = false,
759
+ EdgeTraversalOptions = 0,
760
+ Enabled = true,
761
+ InterfaceTypes = "All",
762
+ LocalAddresses = "*",
763
+ LocalPorts = "50002",
764
+ Profiles = Int32.MaxValue,
765
+ Protocol = 6,
766
+ RemoteAddresses = "*",
767
+ RemotePorts = "*",
768
+ SecureFlags = 0,
769
+ };
770
+
771
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0023", expected6);
772
+
773
+ var expected7 = new RuleDetails("WiXToolset Test - 0024")
774
+ {
775
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
776
+ ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file2.txt"),
777
+ Description = "WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - app",
778
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
779
+ EdgeTraversal = false,
780
+ EdgeTraversalOptions = 0,
781
+ Enabled = true,
782
+ InterfaceTypes = "All",
783
+ LocalAddresses = "*",
784
+ LocalPorts = "50003",
785
+ Profiles = Int32.MaxValue,
786
+ Protocol = 6,
787
+ RemoteAddresses = "*",
788
+ RemotePorts = "*",
789
+ SecureFlags = 0,
790
+ };
791
+
792
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0024", expected7);
793
+
794
+ var expected8 = new RuleDetails("WiXToolset Test - 0025")
795
+ {
796
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
797
+ Description = "WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - port",
798
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
799
+ EdgeTraversal = false,
800
+ EdgeTraversalOptions = 0,
801
+ Enabled = true,
802
+ InterfaceTypes = "All",
803
+ LocalAddresses = "*",
804
+ LocalPorts = "50004",
805
+ Profiles = Int32.MaxValue,
806
+ Protocol = 6,
807
+ RemoteAddresses = "*",
808
+ RemotePorts = "*",
809
+ SecureFlags = 0,
810
+ };
811
+
812
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0025", expected8);
813
+
814
+ var expected9 = new RuleDetails("WiXToolset Test - 0026")
815
+ {
816
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
817
+ ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "package.wxs"),
818
+ Description = "WiX Toolset firewall exception rule integration test - package app",
819
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
820
+ EdgeTraversal = false,
821
+ EdgeTraversalOptions = 0,
822
+ Enabled = true,
823
+ InterfaceTypes = "All",
824
+ LocalAddresses = "*",
825
+ LocalPorts = "20001",
826
+ Profiles = Int32.MaxValue,
827
+ Protocol = 6,
828
+ RemoteAddresses = "*",
829
+ RemotePorts = "*",
830
+ SecureFlags = 0,
831
+ };
832
+
833
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0026", expected9);
834
+
835
+ var expected10 = new RuleDetails("WiXToolset Test - 0027")
836
+ {
837
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
838
+ Description = "WiX Toolset firewall exception rule integration test - package port",
839
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
840
+ EdgeTraversal = false,
841
+ EdgeTraversalOptions = 0,
842
+ Enabled = true,
843
+ InterfaceTypes = "All",
844
+ LocalAddresses = "*",
845
+ LocalPorts = "20002",
846
+ Profiles = Int32.MaxValue,
847
+ Protocol = 6,
848
+ RemoteAddresses = "*",
849
+ RemotePorts = "*",
850
+ SecureFlags = 0,
851
+ };
852
+
853
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0027", expected10);
854
+
855
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
856
+
857
+ // verify the firewall exceptions have been removed.
858
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0018"));
859
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0019"));
860
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0020"));
861
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0021"));
862
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0022"));
863
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0023"));
864
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0024"));
865
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0025"));
866
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0026"));
867
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0027"));
868
+ }
869
+
870
+ [RuntimeFact]
871
+ public void ServiceNameIsPassedIntoNestedRules()
872
+ {
873
+ var product = this.CreatePackageInstaller("NestedService");
874
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
875
+
876
+ var expected1 = new RuleDetails("WiXToolset Test - 0031")
877
+ {
878
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
879
+ Protocol = 256,
880
+ LocalAddresses = "*",
881
+ RemoteAddresses = "*",
882
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
883
+ Description = "WiX Toolset firewall exception rule integration test - service property",
884
+ EdgeTraversal = false,
885
+ EdgeTraversalOptions = 0,
886
+ Enabled = true,
887
+ InterfaceTypes = "All",
888
+ Profiles = Int32.MaxValue,
889
+ SecureFlags = 0,
890
+ ServiceName = "Spooler",
891
+ };
892
+
893
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0031", expected1);
894
+
895
+ var expected2 = new RuleDetails("WiXToolset Test - 0032")
896
+ {
897
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
898
+ Protocol = 256,
899
+ LocalAddresses = "*",
900
+ RemoteAddresses = "*",
901
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
902
+ Description = "WiX Toolset firewall exception rule integration test - ServiceConfig",
903
+ EdgeTraversal = false,
904
+ EdgeTraversalOptions = 0,
905
+ Enabled = true,
906
+ InterfaceTypes = "All",
907
+ Profiles = Int32.MaxValue,
908
+ SecureFlags = 0,
909
+ ServiceName = "Spooler",
910
+ };
911
+
912
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0032", expected2);
913
+
914
+ var expected3 = new RuleDetails("WiXToolset Test - 0033")
915
+ {
916
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
917
+ Protocol = 256,
918
+ LocalAddresses = "*",
919
+ RemoteAddresses = "*",
920
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
921
+ Description = "WiX Toolset firewall exception rule integration test - ServiceInstall",
922
+ EdgeTraversal = false,
923
+ EdgeTraversalOptions = 0,
924
+ Enabled = true,
925
+ InterfaceTypes = "All",
926
+ Profiles = Int32.MaxValue,
927
+ SecureFlags = 0,
928
+ ServiceName = "WixTestFirewallSrv",
929
+ };
930
+
931
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0033", expected3);
932
+
933
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
934
+
935
+ // verify the firewall exceptions have been removed.
936
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0031"));
937
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0032"));
938
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0033"));
939
+ }
940
+
941
+ [RuntimeFact]
942
+ public void SucceedWhenEnableOnlyFlagIsSet()
943
+ {
944
+ var product = this.CreatePackageInstaller("FirewallRulesProperties");
945
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
946
+
947
+ var expected1 = new RuleDetails("WiXToolset Test - 0028")
948
+ {
949
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
950
+ Protocol = 256,
951
+ LocalAddresses = "*",
952
+ RemoteAddresses = "*",
953
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
954
+ EdgeTraversal = false,
955
+ EdgeTraversalOptions = 0,
956
+ Enabled = true,
957
+ InterfaceTypes = "All",
958
+ Profiles = Int32.MaxValue,
959
+ SecureFlags = 0,
960
+ };
961
+
962
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0028", expected1);
963
+
964
+ Verifier.DisableFirewallRule("WiXToolset Test - 0028");
965
+
966
+ var args = new[]
967
+ {
968
+ "LOCALPORT=3456",
969
+ "PROTOCOL=6",
970
+ "PROGRAM=ShouldBeUnchanged",
971
+ "PROFILE=2",
972
+ "DESCRIPTION=ShouldBeUnchanged",
973
+ "REMOTESCOPE=ShouldBeUnchanged",
974
+ "EDGETRAVERSAL=3",
975
+ "ENABLED=1",
976
+ "GROUPING=ShouldBeUnchanged",
977
+ "ICMPTYPES=ShouldBeUnchanged",
978
+ "INTERFACE=ShouldBeUnchanged",
979
+ "INTERFACETYPE=ShouldBeUnchanged",
980
+ "LOCALSCOPE=ShouldBeUnchanged",
981
+ "REMOTEPORT=60000",
982
+ "SERVICE=ShouldBeUnchanged",
983
+ "PACKAGEID=ShouldBeUnchanged",
984
+ "LOCALUSERS=ShouldBeUnchanged",
985
+ "LOCALOWNER=ShouldBeUnchanged",
986
+ "REMOTEMACHINES=ShouldBeUnchanged",
987
+ "REMOTEUSERS=ShouldBeUnchanged",
988
+ "SECUREFLAGS=15",
989
+ "REMOTEADDRESS=ShouldBeUnchanged",
990
+ "LOCALADDRESS=ShouldBeUnchanged",
991
+ };
992
+
993
+ product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
994
+
995
+ var expected2 = new RuleDetails("WiXToolset Test - 0028")
996
+ {
997
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
998
+ Protocol = 256,
999
+ LocalAddresses = "*",
1000
+ RemoteAddresses = "*",
1001
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1002
+ EdgeTraversal = false,
1003
+ EdgeTraversalOptions = 0,
1004
+ Enabled = true,
1005
+ InterfaceTypes = "All",
1006
+ Profiles = Int32.MaxValue,
1007
+ SecureFlags = 0,
1008
+ };
1009
+
1010
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0028", expected2);
1011
+
1012
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1013
+
1014
+ // verify the firewall exceptions have been removed.
1015
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0028"));
1016
+ }
1017
+
1018
+ [RuntimeFact]
1019
+ public void SucceedWhenDoNothingFlagIsSet()
1020
+ {
1021
+ var product = this.CreatePackageInstaller("FirewallRulesProperties");
1022
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1023
+
1024
+ var expected1 = new RuleDetails("WiXToolset Test - 0029")
1025
+ {
1026
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1027
+ Protocol = 256,
1028
+ LocalAddresses = "*",
1029
+ RemoteAddresses = "*",
1030
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1031
+ EdgeTraversal = false,
1032
+ EdgeTraversalOptions = 0,
1033
+ Enabled = true,
1034
+ InterfaceTypes = "All",
1035
+ Profiles = Int32.MaxValue,
1036
+ SecureFlags = 0,
1037
+ };
1038
+
1039
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0029", expected1);
1040
+ Verifier.DisableFirewallRule("WiXToolset Test - 0029");
1041
+
1042
+ var args = new[]
1043
+ {
1044
+ "INTERFACE=ShouldBeUnchanged",
1045
+ "INTERFACETYPE=ShouldBeUnchanged",
1046
+ "REMOTEADDRESS=ShouldBeUnchanged",
1047
+ "LOCALADDRESS=ShouldBeUnchanged",
1048
+ };
1049
+
1050
+ product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
1051
+
1052
+ var expected2 = new RuleDetails("WiXToolset Test - 0029")
1053
+ {
1054
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1055
+ Protocol = 256,
1056
+ LocalAddresses = "*",
1057
+ RemoteAddresses = "*",
1058
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1059
+ EdgeTraversal = false,
1060
+ EdgeTraversalOptions = 0,
1061
+ Enabled = false, // remains as disabled after the repair
1062
+ InterfaceTypes = "All",
1063
+ Profiles = Int32.MaxValue,
1064
+ SecureFlags = 0,
1065
+ };
1066
+
1067
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0029", expected2);
1068
+
1069
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1070
+
1071
+ // verify the firewall exceptions have been removed.
1072
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0029"));
1073
+ }
1074
+
1075
+ [RuntimeFact]
1076
+ public void SucceedWhenNoFlagIsSet()
1077
+ {
1078
+ var product = this.CreatePackageInstaller("FirewallRulesProperties");
1079
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1080
+
1081
+ var expected1 = new RuleDetails("WiXToolset Test - 0030")
1082
+ {
1083
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1084
+ Protocol = 256,
1085
+ LocalAddresses = "*",
1086
+ RemoteAddresses = "*",
1087
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1088
+ EdgeTraversal = false,
1089
+ EdgeTraversalOptions = 0,
1090
+ Enabled = true,
1091
+ InterfaceTypes = "All",
1092
+ Profiles = Int32.MaxValue,
1093
+ SecureFlags = 0,
1094
+ };
1095
+
1096
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0030", expected1);
1097
+ Verifier.DisableFirewallRule("WiXToolset Test - 0030");
1098
+
1099
+ var names = NetworkInterface.GetAllNetworkInterfaces()
1100
+ .Take(2)
1101
+ .Select(ni => ni.Name);
1102
+
1103
+ var args = names.Select((name, idx) => $"INTERFACE{idx + 1}=\"{name}\"")
1104
+ .Concat(new[]
1105
+ {
1106
+ "INTERFACETYPE1=Wireless",
1107
+ "INTERFACETYPE2=Lan",
1108
+ "REMOTEADDRESS1=DHCP",
1109
+ "REMOTEADDRESS2=LocalSubnet",
1110
+ "LOCALADDRESS1=127.0.0.1",
1111
+ "LOCALADDRESS2=192.168.1.1",
1112
+ })
1113
+ .ToArray();
1114
+
1115
+ product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
1116
+
1117
+ var expected2 = new RuleDetails("WiXToolset Test - 0030")
1118
+ {
1119
+ Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1120
+ Protocol = 256,
1121
+ LocalAddresses = "127.0.0.1/255.255.255.255,192.168.1.1/255.255.255.255",
1122
+ RemoteAddresses = "LocalSubnet,DHCP",
1123
+ Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1124
+ Description = "",
1125
+ EdgeTraversal = false,
1126
+ EdgeTraversalOptions = 0,
1127
+ Enabled = true,
1128
+ Interfaces = names.ToArray(),
1129
+ InterfaceTypes = "Lan,Wireless",
1130
+ Profiles = Int32.MaxValue,
1131
+ SecureFlags = 0,
1132
+ };
1133
+
1134
+ Verifier.VerifyFirewallRule("WiXToolset Test - 0030", expected2);
1135
+
1136
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1137
+
1138
+ // verify the firewall exceptions have been removed.
1139
+ Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0030"));
1140
+ }
1141
}
1142
}
src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
+1
@@ -29,6 +29,7 @@
29
30
<ItemGroup>
31
<PackageReference Include="Microsoft.Win32.Registry" />
32
+ <PackageReference Include="System.Net.NetworkInformation" />
33
<PackageReference Include="System.Security.Principal.Windows" />
34
<PackageReference Include="WixInternal.TestSupport" />
35
<PackageReference Include="WixToolset.Data" />