aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchris_bednarski <Chris.Bednarski@minfos.com.au>2023-08-26 08:31:28 +1000
committerBob Arnson <github@bobs.org>2023-08-26 17:58:25 -0400
commitb3deb46def7d303a79f4a5eba6a921e45d5f16ef (patch)
tree3327ffd8525f793a511832172129c904ba062904 /src
parent537e79d3c8b99e1576db48b19c8071c0922342f2 (diff)
downloadwix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.tar.gz
wix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.tar.bz2
wix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.zip
add firewall extension decompiler
Diffstat (limited to 'src')
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs59
-rw-r--r--src/ext/Firewall/wixext/FirewallCompiler.cs2
-rw-r--r--src/ext/Firewall/wixext/FirewallConstants.cs8
-rw-r--r--src/ext/Firewall/wixext/FirewallDecompiler.cs173
-rw-r--r--src/ext/Firewall/wixext/FirewallExtensionFactory.cs3
5 files changed, 164 insertions, 81 deletions
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index b89afaf7..06a877f6 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -2,9 +2,11 @@
2 2
3namespace WixToolsetTest.Firewall 3namespace WixToolsetTest.Firewall
4{ 4{
5 using System.IO;
5 using System.Linq; 6 using System.Linq;
6 using WixInternal.TestSupport; 7 using System.Xml.Linq;
7 using WixInternal.Core.TestPackage; 8 using WixInternal.Core.TestPackage;
9 using WixInternal.TestSupport;
8 using WixToolset.Firewall; 10 using WixToolset.Firewall;
9 using Xunit; 11 using Xunit;
10 12
@@ -50,6 +52,55 @@ namespace WixToolsetTest.Firewall
50 }, results); 52 }, results);
51 } 53 }
52 54
55 [Fact]
56 public void CanRoundtripFirewallExceptions()
57 {
58 var folder = TestData.Get(@"TestData", "UsingFirewall");
59 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
60 var output = Path.Combine(folder, "FirewallExceptionDecompile.xml");
61
62 build.BuildAndDecompileAndBuild(Build, Decompile, output);
63
64 var doc = XDocument.Load(output);
65 var actual = doc.Descendants()
66 .Where(e => e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall")
67 .Select(fe => new { Name = fe.Name.LocalName, Attributes = fe.Attributes().Select(a => $"{a.Name.LocalName}={a.Value}").ToArray() })
68 .ToArray();
69
70 WixAssert.CompareLineByLine(new[]
71 {
72 "FirewallException",
73 "FirewallException",
74 }, actual.Select(a => a.Name).ToArray());
75
76 WixAssert.CompareLineByLine(new[]
77 {
78 "Id=ExampleFirewall",
79 "Name=ExampleApp",
80 "Scope=any",
81 "Port=42",
82 "Protocol=tcp",
83 "Program=[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]",
84 "Profile=all",
85 "Description=An app-based firewall exception",
86 "Outbound=no",
87 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
88 }, actual[0].Attributes);
89
90 WixAssert.CompareLineByLine(new[]
91 {
92 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs",
93 "Name=ExamplePort",
94 "Scope=localSubnet",
95 "Port=42",
96 "Protocol=tcp",
97 "Profile=all",
98 "Description=A port-based firewall exception",
99 "Outbound=yes",
100 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
101 }, actual[1].Attributes);
102 }
103
53 private static void Build(string[] args) 104 private static void Build(string[] args)
54 { 105 {
55 var result = WixRunner.Execute(args); 106 var result = WixRunner.Execute(args);
@@ -65,5 +116,11 @@ namespace WixToolsetTest.Firewall
65 var result = WixRunner.Execute(newArgs.ToArray()); 116 var result = WixRunner.Execute(newArgs.ToArray());
66 result.AssertSuccess(); 117 result.AssertSuccess();
67 } 118 }
119
120 private static void Decompile(string[] args)
121 {
122 var result = WixRunner.Execute(args);
123 result.AssertSuccess();
124 }
68 } 125 }
69} 126}
diff --git a/src/ext/Firewall/wixext/FirewallCompiler.cs b/src/ext/Firewall/wixext/FirewallCompiler.cs
index cbe82d37..19ee0b6d 100644
--- a/src/ext/Firewall/wixext/FirewallCompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallCompiler.cs
@@ -15,7 +15,7 @@ namespace WixToolset.Firewall
15 /// </summary> 15 /// </summary>
16 public sealed class FirewallCompiler : BaseCompilerExtension 16 public sealed class FirewallCompiler : BaseCompilerExtension
17 { 17 {
18 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/firewall"; 18 public override XNamespace Namespace => FirewallConstants.Namespace;
19 19
20 /// <summary> 20 /// <summary>
21 /// Processes an element for the Compiler. 21 /// Processes an element for the Compiler.
diff --git a/src/ext/Firewall/wixext/FirewallConstants.cs b/src/ext/Firewall/wixext/FirewallConstants.cs
index 7bb12ba4..5ecfe032 100644
--- a/src/ext/Firewall/wixext/FirewallConstants.cs
+++ b/src/ext/Firewall/wixext/FirewallConstants.cs
@@ -2,12 +2,14 @@
2 2
3namespace WixToolset.Firewall 3namespace WixToolset.Firewall
4{ 4{
5 using System; 5 using System.Xml.Linq;
6 using System.Collections.Generic;
7 using System.Text;
8 6
9 static class FirewallConstants 7 static class FirewallConstants
10 { 8 {
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
11 // from icftypes.h 13 // from icftypes.h
12 public const int NET_FW_RULE_DIR_IN = 1; 14 public const int NET_FW_RULE_DIR_IN = 1;
13 public const int NET_FW_RULE_DIR_OUT = 2; 15 public const int NET_FW_RULE_DIR_OUT = 2;
diff --git a/src/ext/Firewall/wixext/FirewallDecompiler.cs b/src/ext/Firewall/wixext/FirewallDecompiler.cs
index c9478de1..69f2c3f4 100644
--- a/src/ext/Firewall/wixext/FirewallDecompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallDecompiler.cs
@@ -2,54 +2,53 @@
2 2
3namespace WixToolset.Firewall 3namespace WixToolset.Firewall
4{ 4{
5#if TODO_CONSIDER_DECOMPILER
6 using System; 5 using System;
7 using System.Collections; 6 using System.Collections.Generic;
8 using System.Diagnostics; 7 using System.Xml.Linq;
9 using System.Globalization;
10 using WixToolset.Data; 8 using WixToolset.Data;
9 using WixToolset.Data.WindowsInstaller;
11 using WixToolset.Extensibility; 10 using WixToolset.Extensibility;
12 using Firewall = WixToolset.Extensions.Serialize.Firewall;
13 using Wix = WixToolset.Data.Serialize;
14 11
15 /// <summary> 12 /// <summary>
16 /// The decompiler for the WiX Toolset Firewall Extension. 13 /// The decompiler for the WiX Toolset Firewall Extension.
17 /// </summary> 14 /// </summary>
18 public sealed class FirewallDecompiler : DecompilerExtension 15 public sealed class FirewallDecompiler : BaseWindowsInstallerDecompilerExtension
19 { 16 {
20 /// <summary> 17 public override IReadOnlyCollection<TableDefinition> TableDefinitions => FirewallTableDefinitions.All;
21 /// Creates a decompiler for Firewall Extension.
22 /// </summary>
23 public FirewallDecompiler()
24 {
25 this.TableDefinitions = FirewallExtensionData.GetExtensionTableDefinitions();
26 }
27 18
28 /// <summary> 19 /// <summary>
29 /// Get the extensions library to be removed. 20 /// Called at the beginning of the decompilation of a database.
30 /// </summary> 21 /// </summary>
31 /// <param name="tableDefinitions">Table definitions for library.</param> 22 /// <param name="tables">The collection of all tables.</param>
32 /// <returns>Library to remove from decompiled output.</returns> 23 public override void PreDecompileTables(TableIndexedCollection tables)
33 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
34 { 24 {
35 return FirewallExtensionData.GetExtensionLibrary(tableDefinitions);
36 } 25 }
37 26
38 /// <summary> 27 /// <summary>
39 /// Decompiles an extension table. 28 /// Decompiles an extension table.
40 /// </summary> 29 /// </summary>
41 /// <param name="table">The table to decompile.</param> 30 /// <param name="table">The table to decompile.</param>
42 public override void DecompileTable(Table table) 31 public override bool TryDecompileTable(Table table)
43 { 32 {
44 switch (table.Name) 33 switch (table.Name)
45 { 34 {
46 case "WixFirewallException": 35 case "Wix4FirewallException":
47 this.DecompileWixFirewallExceptionTable(table); 36 this.DecompileWixFirewallExceptionTable(table);
48 break; 37 break;
49 default: 38 default:
50 base.DecompileTable(table); 39 return false;
51 break;
52 } 40 }
41
42 return true;
43 }
44
45 /// <summary>
46 /// Finalize decompilation.
47 /// </summary>
48 /// <param name="tables">The collection of all tables.</param>
49 public override void PostDecompileTables(TableIndexedCollection tables)
50 {
51 this.FinalizeFirewallExceptionTable(tables);
53 } 52 }
54 53
55 /// <summary> 54 /// <summary>
@@ -60,38 +59,42 @@ namespace WixToolset.Firewall
60 { 59 {
61 foreach (Row row in table.Rows) 60 foreach (Row row in table.Rows)
62 { 61 {
63 Firewall.FirewallException fire = new Firewall.FirewallException(); 62 var firewallException = new XElement(FirewallConstants.FirewallExceptionName,
64 fire.Id = (string)row[0]; 63 new XAttribute("Id", row.FieldAsString(0)),
65 fire.Name = (string)row[1]; 64 new XAttribute("Name", row.FieldAsString(1))
65 );
66 66
67 string[] addresses = ((string)row[2]).Split(','); 67 if (!row.IsColumnEmpty(2))
68 if (1 == addresses.Length)
69 { 68 {
70 // special-case the Scope attribute values 69 string[] addresses = ((string)row[2]).Split(',');
71 if ("*" == addresses[0]) 70 if (addresses.Length == 1)
72 { 71 {
73 fire.Scope = Firewall.FirewallException.ScopeType.any; 72 // special-case the Scope attribute values
74 } 73 if (addresses[0] == "*")
75 else if ("LocalSubnet" == addresses[0]) 74 {
76 { 75 firewallException.Add(new XAttribute("Scope", "any"));
77 fire.Scope = Firewall.FirewallException.ScopeType.localSubnet; 76 }
77 else if (addresses[0] == "LocalSubnet")
78 {
79 firewallException.Add(new XAttribute("Scope", "localSubnet"));
80 }
81 else
82 {
83 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
84 }
78 } 85 }
79 else 86 else
80 { 87 {
81 FirewallDecompiler.AddRemoteAddress(fire, addresses[0]); 88 foreach (string address in addresses)
82 } 89 {
83 } 90 FirewallDecompiler.AddRemoteAddress(firewallException, address);
84 else 91 }
85 {
86 foreach (string address in addresses)
87 {
88 FirewallDecompiler.AddRemoteAddress(fire, address);
89 } 92 }
90 } 93 }
91 94
92 if (!row.IsColumnEmpty(3)) 95 if (!row.IsColumnEmpty(3))
93 { 96 {
94 fire.Port = (string)row[3]; 97 firewallException.Add(new XAttribute("Port", row.FieldAsString(3)));
95 } 98 }
96 99
97 if (!row.IsColumnEmpty(4)) 100 if (!row.IsColumnEmpty(4))
@@ -99,26 +102,23 @@ namespace WixToolset.Firewall
99 switch (Convert.ToInt32(row[4])) 102 switch (Convert.ToInt32(row[4]))
100 { 103 {
101 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP: 104 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
102 fire.Protocol = Firewall.FirewallException.ProtocolType.tcp; 105 firewallException.Add(new XAttribute("Protocol", "tcp"));
103 break; 106 break;
104 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: 107 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
105 fire.Protocol = Firewall.FirewallException.ProtocolType.udp; 108 firewallException.Add(new XAttribute("Protocol", "udp"));
106 break; 109 break;
107 } 110 }
108 } 111 }
109 112
110 if (!row.IsColumnEmpty(5)) 113 if (!row.IsColumnEmpty(5))
111 { 114 {
112 fire.Program = (string)row[5]; 115 firewallException.Add(new XAttribute("Program", row.FieldAsString(5)));
113 } 116 }
114 117
115 if (!row.IsColumnEmpty(6)) 118 if (!row.IsColumnEmpty(6))
116 { 119 {
117 int attr = Convert.ToInt32(row[6]); 120 var attr = Convert.ToInt32(row[6]);
118 if (0x1 == (attr & 0x1)) // feaIgnoreFailures 121 AttributeIfNotNull("IgnoreFailure", (attr & 0x1) == 0x1);
119 {
120 fire.IgnoreFailure = Firewall.YesNoType.yes;
121 }
122 } 122 }
123 123
124 if (!row.IsColumnEmpty(7)) 124 if (!row.IsColumnEmpty(7))
@@ -126,24 +126,23 @@ namespace WixToolset.Firewall
126 switch (Convert.ToInt32(row[7])) 126 switch (Convert.ToInt32(row[7]))
127 { 127 {
128 case FirewallConstants.NET_FW_PROFILE2_DOMAIN: 128 case FirewallConstants.NET_FW_PROFILE2_DOMAIN:
129 fire.Profile = Firewall.FirewallException.ProfileType.domain; 129 firewallException.Add(new XAttribute("Profile", "domain"));
130 break; 130 break;
131 case FirewallConstants.NET_FW_PROFILE2_PRIVATE: 131 case FirewallConstants.NET_FW_PROFILE2_PRIVATE:
132 fire.Profile = Firewall.FirewallException.ProfileType.@private; 132 firewallException.Add(new XAttribute("Profile", "private"));
133 break; 133 break;
134 case FirewallConstants.NET_FW_PROFILE2_PUBLIC: 134 case FirewallConstants.NET_FW_PROFILE2_PUBLIC:
135 fire.Profile = Firewall.FirewallException.ProfileType.@public; 135 firewallException.Add(new XAttribute("Profile", "public"));
136 break; 136 break;
137 case FirewallConstants.NET_FW_PROFILE2_ALL: 137 case FirewallConstants.NET_FW_PROFILE2_ALL:
138 fire.Profile = Firewall.FirewallException.ProfileType.all; 138 firewallException.Add(new XAttribute("Profile", "all"));
139 break; 139 break;
140 } 140 }
141 } 141 }
142 142
143 // Description column is new in v3.6 143 if (!row.IsColumnEmpty(9))
144 if (9 < row.Fields.Length && !row.IsColumnEmpty(9))
145 { 144 {
146 fire.Description = (string)row[9]; 145 firewallException.Add(new XAttribute("Description", row.FieldAsString(9)));
147 } 146 }
148 147
149 if (!row.IsColumnEmpty(10)) 148 if (!row.IsColumnEmpty(10))
@@ -151,32 +150,56 @@ namespace WixToolset.Firewall
151 switch (Convert.ToInt32(row[10])) 150 switch (Convert.ToInt32(row[10]))
152 { 151 {
153 case FirewallConstants.NET_FW_RULE_DIR_IN: 152 case FirewallConstants.NET_FW_RULE_DIR_IN:
154 fire.Direction = Firewall.FirewallException.DirectionType.@in; 153
154 firewallException.Add(AttributeIfNotNull("Outbound", false));
155 break; 155 break;
156 case FirewallConstants.NET_FW_RULE_DIR_OUT: 156 case FirewallConstants.NET_FW_RULE_DIR_OUT:
157 fire.Direction = Firewall.FirewallException.DirectionType.@out; 157 firewallException.Add(AttributeIfNotNull("Outbound", true));
158 break; 158 break;
159 } 159 }
160 } 160 }
161 161
162 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]); 162 this.DecompilerHelper.IndexElement(row, firewallException);
163 if (null != component)
164 {
165 component.AddChild(fire);
166 }
167 else
168 {
169 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component"));
170 }
171 } 163 }
172 } 164 }
173 165
174 private static void AddRemoteAddress(Firewall.FirewallException fire, string address) 166 private static void AddRemoteAddress(XElement firewallException, string address)
167 {
168 var remoteAddress = new XElement(FirewallConstants.RemoteAddressName,
169 new XAttribute("Value", address)
170 );
171
172 firewallException.AddAfterSelf(remoteAddress);
173 }
174
175 private static XAttribute AttributeIfNotNull(string name, bool value)
176 {
177 return new XAttribute(name, value ? "yes" : "no");
178 }
179
180 /// <summary>
181 /// Finalize the FirewallException table.
182 /// </summary>
183 /// <param name="tables">Collection of all tables.</param>
184 private void FinalizeFirewallExceptionTable(TableIndexedCollection tables)
175 { 185 {
176 Firewall.RemoteAddress remote = new Firewall.RemoteAddress(); 186 if (tables.TryGetTable("Wix4FirewallException", out var firewallExceptionTable))
177 remote.Content = address; 187 {
178 fire.AddChild(remote); 188 foreach (var row in firewallExceptionTable.Rows)
189 {
190 var xmlConfig = this.DecompilerHelper.GetIndexedElement(row);
191
192 var componentId = row.FieldAsString(8);
193 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
194 {
195 component.Add(xmlConfig);
196 }
197 else
198 {
199 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, firewallExceptionTable.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
200 }
201 }
202 }
179 } 203 }
180 } 204 }
181#endif
182} 205}
diff --git a/src/ext/Firewall/wixext/FirewallExtensionFactory.cs b/src/ext/Firewall/wixext/FirewallExtensionFactory.cs
index 279b322a..8ce6f4ba 100644
--- a/src/ext/Firewall/wixext/FirewallExtensionFactory.cs
+++ b/src/ext/Firewall/wixext/FirewallExtensionFactory.cs
@@ -1,4 +1,4 @@
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. 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 2
3namespace WixToolset.Firewall 3namespace WixToolset.Firewall
4{ 4{
@@ -13,6 +13,7 @@ namespace WixToolset.Firewall
13 typeof(FirewallCompiler), 13 typeof(FirewallCompiler),
14 typeof(FirewallExtensionData), 14 typeof(FirewallExtensionData),
15 typeof(FirewallWindowsInstallerBackendBinderExtension), 15 typeof(FirewallWindowsInstallerBackendBinderExtension),
16 typeof(FirewallDecompiler),
16 }; 17 };
17 } 18 }
18} 19}