Skip to content

Commit

Permalink
add firewall extension decompiler, make msi modifications work, add a…
Browse files Browse the repository at this point in the history
…ll attributes
  • Loading branch information
chrisbednarski committed Sep 24, 2023
1 parent 283dd77 commit 39820ef
Show file tree
Hide file tree
Showing 14 changed files with 2,131 additions and 288 deletions.
976 changes: 781 additions & 195 deletions src/ext/Firewall/ca/firewall.cpp

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@
<fw:FirewallException Description="DHCP scope firewall exception" Name="ExampleDHCPScope" Program="test.exe" Protocol="211" Scope="DHCP" Profile="public" />
<fw:FirewallException Description="WINS scope firewall exception" Name="ExampleWINSScope" Port="6573" Scope="WINS" Profile="domain"/>
<fw:FirewallException Description="defaultGateway scope firewall exception" Name="ExampleDefaultGatewayScope" Port="4432" Scope="defaultGateway" Profile="private" />

<fw:FirewallException Description="Defer to user edge traversal" Name="defertouser" Program="fw.exe" EdgeTraversal="DeferToUser" />
<fw:FirewallException Description="A port-based service exception" Name="ExampleService" Port="12000" Service="ftpsrv" Program="%windir%\system32\svchost.exe" >
<fw:LocalAddress Value="DHCP"/>
<fw:LocalAddress Value="WINS"/>
</fw:FirewallException>

<fw:FirewallException Description="Interfaces with nested elements" Name="interface nested" Port="54671" >
<fw:RemoteAddress Value="127.0.0.1"/>
<fw:Interface Name="Wi-Fi" />
<fw:Interface Name="Local Area Connection" />
</fw:FirewallException>
<fw:FirewallException Description="Interfaces with property" Name="interface property" Port="54671" Interface="[INTERFACE_PROPERTY]" />

<ServiceInstall Name="svc1" Type="ownProcess" Start="disabled" ErrorControl="ignore" >
<fw:FirewallException Id="ServiceInstall.nested" IgnoreFailure="true" Description="A port-based firewall exception for a windows service" Name="ExampleNestedService" Port="3546-7890" Scope="localSubnet" >
<fw:InterfaceType Value="Lan" />
<fw:InterfaceType Value="Wireless" />
</fw:FirewallException>
</ServiceInstall>

<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" />
<fw:FirewallException Description="INetFwRule3 passed via properties" Name="INetFwRule3 properties" Scope="any" LocalAppPackageId="[PROP1]" LocalUserAuthorizedList="[PROP2]" LocalUserOwner="[PROP3]" RemoteMachineAuthorizedList="[PROP4]" RemoteUserAuthorizedList="[PROP5]" IPSecSecureFlags="[PROP6]" />

<fw:FirewallException Description="Simple rule with grouping" Name="GroupingExample1" Program="fw.exe" Grouping="@yourresources.dll,-1005" />
<fw:FirewallException Description="Rule with grouping property" Name="GroupingExample2" Port="8732" Grouping="[GROUPING_PROP]" />

<fw:FirewallException Description="Simple ICMP rule" Name="ICMPExample1" Protocol="2" IcmpTypesAndCodes="4:*,9:*,12:*" />
<fw:FirewallException Description="Rule with ICMP property" Name="ICMPExample2" Protocol="2" IcmpTypesAndCodes="[ICMP_PROP]" />

<fw:FirewallException Description="Simple rule with local scope" Name="LocalScopeExample1" Scope="any" LocalScope="localSubnet" />
<fw:FirewallException Description="Rule with local scope property" Name="LocalScopeExample2" Scope="any" LocalScope="[LOCALSCOPE_PROP]" />

<fw:FirewallException Description="Simple rule with remote port" Name="RemotePortExample1" Scope="any" RemotePort="34560" />
<fw:FirewallException Description="Rule with remote port property" Name="RemotePortExample2" Program="fw.exe" RemotePort="[REMOTEPORT_PROP]" />
</Component>
</ComponentGroup>
</Fragment>
Expand Down
567 changes: 531 additions & 36 deletions src/ext/Firewall/wixext/FirewallCompiler.cs

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions src/ext/Firewall/wixext/FirewallConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ static class FirewallConstants
internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/firewall";
internal static readonly XName FirewallExceptionName = Namespace + "FirewallException";
internal static readonly XName RemoteAddressName = Namespace + "RemoteAddress";
internal static readonly XName InterfaceName = Namespace + "Interface";
internal static readonly XName InterfaceTypeName = Namespace + "InterfaceType";
internal static readonly XName LocalAddressName = Namespace + "LocalAddress";

// from icftypes.h
public const int NET_FW_RULE_DIR_IN = 1;
Expand All @@ -21,5 +24,17 @@ static class FirewallConstants
public const int NET_FW_PROFILE2_PRIVATE = 0x0002;
public const int NET_FW_PROFILE2_PUBLIC = 0x0004;
public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF;

// from icftypes.h
public const int NET_FW_EDGE_TRAVERSAL_TYPE_DENY = 0;
public const int NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW = 1;
public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP = 2;
public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER = 3;

/// <summary>
/// Firewall rules are stored in the registry.<br/>
/// The pipe character is used to split firewall rule attributes, so is not permitted in any of them.
/// </summary>
public const char FORBIDDEN_FIREWALL_CHAR = '|';
}
}
263 changes: 258 additions & 5 deletions src/ext/Firewall/wixext/FirewallDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public override bool TryDecompileTable(Table table)
{
switch (table.Name)
{
case "WixFirewallException":
case "Wix4FirewallException":
case "Wix5FirewallException":
this.DecompileWixFirewallExceptionTable(table);
break;
Expand All @@ -57,7 +59,7 @@ public override void PostDecompileTables(TableIndexedCollection tables)
/// <param name="table">The table to decompile.</param>
private void DecompileWixFirewallExceptionTable(Table table)
{
foreach (Row row in table.Rows)
foreach (var row in table.Rows)
{
var firewallException = new XElement(FirewallConstants.FirewallExceptionName,
new XAttribute("Id", row.FieldAsString(0)),
Expand Down Expand Up @@ -96,7 +98,7 @@ private void DecompileWixFirewallExceptionTable(Table table)
}
else
{
foreach (string address in addresses)
foreach (var address in addresses)
{
FirewallDecompiler.AddRemoteAddress(firewallException, address);
}
Expand Down Expand Up @@ -131,8 +133,21 @@ private void DecompileWixFirewallExceptionTable(Table table)

if (!row.IsColumnEmpty(6))
{
var attr = Convert.ToInt32(row[6]);
AttributeIfNotNull("IgnoreFailure", (attr & 0x1) == 0x1);
var attr = row.FieldAsInteger(6);
if ((attr & 0x1) == 0x1)
{
AttributeIfNotNull("IgnoreFailure", true);
}

if ((attr & 0x2) == 0x2)
{
AttributeIfNotNull("IgnoreUpdates", true);
}

if ((attr & 0x4) == 0x4)
{
AttributeIfNotNull("EnableOnChange", true);
}
}

if (!row.IsColumnEmpty(7))
Expand Down Expand Up @@ -173,6 +188,217 @@ private void DecompileWixFirewallExceptionTable(Table table)
}
}

// Introduced in 5.0.0
if (row.Fields.Length > 11)
{
if (!row.IsColumnEmpty(11))
{
var action = row.FieldAsString(11);
switch (action)
{
case "-2147483648":
break;
case "1":
firewallException.Add(new XAttribute("Action", "Allow"));
break;
case "0":
firewallException.Add(new XAttribute("Action", "Block"));
break;
default:
firewallException.Add(new XAttribute("Action", action));
break;
}
}

if (!row.IsColumnEmpty(12))
{
var edgeTraversal = row.FieldAsString(12);
switch (edgeTraversal)
{
case "-2147483648":
break;
case "0":
firewallException.Add(new XAttribute("EdgeTraversal", "Deny"));
break;
case "1":
firewallException.Add(new XAttribute("EdgeTraversal", "Allow"));
break;
case "2":
firewallException.Add(new XAttribute("EdgeTraversal", "DeferToApp"));
break;
case "3":
firewallException.Add(new XAttribute("EdgeTraversal", "DeferToUser"));
break;
default:
firewallException.Add(new XAttribute("EdgeTraversal", edgeTraversal));
break;
}
}

if (!row.IsColumnEmpty(13))
{
var enabled = row.FieldAsString(13);
switch (enabled)
{
case "-2147483648":
break;
case "1":
firewallException.Add(new XAttribute("Enabled", "yes"));
break;
case "0":
firewallException.Add(new XAttribute("Enabled", "no"));
break;
default:
firewallException.Add(new XAttribute("Enabled", enabled));
break;
}
}

if (!row.IsColumnEmpty(14))
{
firewallException.Add(new XAttribute("Grouping", row.FieldAsString(14)));
}

if (!row.IsColumnEmpty(15))
{
firewallException.Add(new XAttribute("IcmpTypesAndCodes", row.FieldAsString(15)));
}

if (!row.IsColumnEmpty(16))
{
string[] interfaces = row.FieldAsString(16).Split(new[] { FirewallConstants.FORBIDDEN_FIREWALL_CHAR }, StringSplitOptions.RemoveEmptyEntries);
if (interfaces.Length == 1)
{
firewallException.Add(new XAttribute("Interface", interfaces[0]));
}
else
{
foreach (var interfaceItem in interfaces)
{
FirewallDecompiler.AddInterface(firewallException, interfaceItem);
}
}
}

if (!row.IsColumnEmpty(17))
{
string[] interfaceTypes = row.FieldAsString(17).Split(',');
if (interfaceTypes.Length == 1)
{
firewallException.Add(new XAttribute("InterfaceType", interfaceTypes[0]));
}
else
{
foreach (var interfaceType in interfaceTypes)
{
FirewallDecompiler.AddInterfaceType(firewallException, interfaceType);
}
}
}

if (!row.IsColumnEmpty(18))
{
string[] addresses = row.FieldAsString(18).Split(',');
if (addresses.Length == 1)
{
switch (addresses[0])
{
case "*":
firewallException.Add(new XAttribute("LocalScope", "any"));
break;
case "LocalSubnet":
firewallException.Add(new XAttribute("LocalScope", "localSubnet"));
break;
case "dns":
firewallException.Add(new XAttribute("LocalScope", "DNS"));
break;
case "dhcp":
firewallException.Add(new XAttribute("LocalScope", "DHCP"));
break;
case "wins":
firewallException.Add(new XAttribute("LocalScope", "WINS"));
break;
case "DefaultGateway":
firewallException.Add(new XAttribute("LocalScope", "defaultGateway"));
break;
default:
FirewallDecompiler.AddLocalAddress(firewallException, addresses[0]);
break;
}
}
else
{
foreach (var address in addresses)
{
FirewallDecompiler.AddLocalAddress(firewallException, address);
}
}
}

if (!row.IsColumnEmpty(19))
{
firewallException.Add(new XAttribute("RemotePort", row.FieldAsString(19)));
}

if (!row.IsColumnEmpty(20))
{
firewallException.Add(new XAttribute("Service", row.FieldAsString(20)));
}

if (!row.IsColumnEmpty(21))
{
firewallException.Add(new XAttribute("LocalAppPackageId", row.FieldAsString(21)));
}

if (!row.IsColumnEmpty(22))
{
firewallException.Add(new XAttribute("LocalUserAuthorizedList", row.FieldAsString(22)));
}

if (!row.IsColumnEmpty(23))
{
firewallException.Add(new XAttribute("LocalUserOwner", row.FieldAsString(23)));
}

if (!row.IsColumnEmpty(24))
{
firewallException.Add(new XAttribute("RemoteMachineAuthorizedList", row.FieldAsString(24)));
}

if (!row.IsColumnEmpty(25))
{
firewallException.Add(new XAttribute("RemoteUserAuthorizedList", row.FieldAsString(25)));
}

if (!row.IsColumnEmpty(26))
{
var secureFlags = row.FieldAsString(26);
switch (secureFlags)
{
case "-2147483648":
break;
case "0":
firewallException.Add(new XAttribute("IPSecSecureFlags", "None"));
break;
case "1":
firewallException.Add(new XAttribute("IPSecSecureFlags", "NoEncapsulation"));
break;
case "2":
firewallException.Add(new XAttribute("IPSecSecureFlags", "WithIntegrity"));
break;
case "3":
firewallException.Add(new XAttribute("IPSecSecureFlags", "NegotiateEncryption"));
break;
case "4":
firewallException.Add(new XAttribute("IPSecSecureFlags", "Encrypt"));
break;
default:
firewallException.Add(new XAttribute("IPSecSecureFlags", secureFlags));
break;
}
}
}

this.DecompilerHelper.IndexElement(row, firewallException);
}
}
Expand All @@ -183,7 +409,34 @@ private static void AddRemoteAddress(XElement firewallException, string address)
new XAttribute("Value", address)
);

firewallException.AddAfterSelf(remoteAddress);
firewallException.Add(remoteAddress);
}

private static void AddInterfaceType(XElement firewallException, string type)
{
var interfaceType = new XElement(FirewallConstants.InterfaceTypeName,
new XAttribute("Value", type)
);

firewallException.Add(interfaceType);
}

private static void AddLocalAddress(XElement firewallException, string address)
{
var localAddress = new XElement(FirewallConstants.LocalAddressName,
new XAttribute("Value", address)
);

firewallException.Add(localAddress);
}

private static void AddInterface(XElement firewallException, string value)
{
var interfaceName = new XElement(FirewallConstants.InterfaceName,
new XAttribute("Name", value)
);

firewallException.Add(interfaceName);
}

private static XAttribute AttributeIfNotNull(string name, bool value)
Expand Down
Loading

0 comments on commit 39820ef

Please sign in to comment.