diff options
author | chris_bednarski <Chris.Bednarski@minfos.com.au> | 2023-08-26 08:31:28 +1000 |
---|---|---|
committer | Bob Arnson <github@bobs.org> | 2023-08-26 17:58:25 -0400 |
commit | b3deb46def7d303a79f4a5eba6a921e45d5f16ef (patch) | |
tree | 3327ffd8525f793a511832172129c904ba062904 /src | |
parent | 537e79d3c8b99e1576db48b19c8071c0922342f2 (diff) | |
download | wix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.tar.gz wix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.tar.bz2 wix-b3deb46def7d303a79f4a5eba6a921e45d5f16ef.zip |
add firewall extension decompiler
Diffstat (limited to 'src')
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 | ||
3 | namespace WixToolsetTest.Firewall | 3 | namespace 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 | ||
3 | namespace WixToolset.Firewall | 3 | namespace 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 | ||
3 | namespace WixToolset.Firewall | 3 | namespace 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 | ||
3 | namespace WixToolset.Firewall | 3 | namespace 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 | } |