mirror of https://github.com/dahall/Vanara.git
972 lines
46 KiB
C#
972 lines
46 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Security.AccessControl;
|
|
using System.Security.Principal;
|
|
using System.ServiceProcess;
|
|
using Vanara.Extensions;
|
|
using Vanara.InteropServices;
|
|
using Vanara.PInvoke;
|
|
using static Vanara.PInvoke.FirewallApi;
|
|
|
|
namespace Vanara.Network;
|
|
|
|
/// <summary>Specifies the conditions under which edge traversal traffic is allowed.</summary>
|
|
/// <remarks>
|
|
/// In order for Windows Firewall to dynamically allow edge traversal traffic, the application must use the IPV6_PROTECTION_LEVEL socket
|
|
/// option on the listening socket and set it to <c>PROTECTION_LEVEL_UNRESTRICTED</c> only in the cases where edge traversal traffic should
|
|
/// be allowed. The Windows Firewall rule added for the application must then set its edge traversal option to
|
|
/// <c>DeferToApp</c> or <c>DeferToUser</c>.
|
|
/// </remarks>
|
|
public enum EdgeTraversalType
|
|
{
|
|
/// <summary>Edge traversal traffic is always blocked.This is the same as setting the EdgeTraversal property using INetFwRule to VARIANT_FALSE.</summary>
|
|
Deny = NET_FW_EDGE_TRAVERSAL_TYPE.NET_FW_EDGE_TRAVERSAL_TYPE_DENY,
|
|
|
|
/// <summary>Edge traversal traffic is always allowed.This is the same as setting the EdgeTraversal property using INetFwRule to VARIANT_TRUE.</summary>
|
|
Allow = NET_FW_EDGE_TRAVERSAL_TYPE.NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW,
|
|
|
|
/// <summary>
|
|
/// Edge traversal traffic is allowed when the application sets the IPV6_PROTECTION_LEVEL socket option to PROTECTION_LEVEL_UNRESTRICTED.
|
|
/// Otherwise, it is blocked.
|
|
/// </summary>
|
|
DeferToApp = NET_FW_EDGE_TRAVERSAL_TYPE.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP,
|
|
|
|
/// <summary>
|
|
/// The user is prompted whether to allow edge traversal traffic when the application sets the IPV6_PROTECTION_LEVEL socket option to
|
|
/// PROTECTION_LEVEL_UNRESTRICTED. If the user chooses to allow edge traversal traffic, the rule is modified to defer to the
|
|
/// application's settings.If the application has not set the IPV6_PROTECTION_LEVEL socket option to PROTECTION_LEVEL_UNRESTRICTED, edge
|
|
/// traversal traffic is blocked.In order to use this option, the firewall rule must have both the application path and protocol scopes
|
|
/// specified. This option cannot be used if port(s) are defined.
|
|
/// </summary>
|
|
DeferToUser = NET_FW_EDGE_TRAVERSAL_TYPE.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER,
|
|
}
|
|
|
|
/// <summary>Specifies the action for a rule or default setting.</summary>
|
|
public enum FirewallAction
|
|
{
|
|
/// <summary>Block traffic.</summary>
|
|
Block = NET_FW_ACTION.NET_FW_ACTION_BLOCK,
|
|
|
|
/// <summary>Allow traffic.</summary>
|
|
Allow = NET_FW_ACTION.NET_FW_ACTION_ALLOW,
|
|
|
|
/// <summary>Maximum traffic.</summary>
|
|
Max = NET_FW_ACTION.NET_FW_ACTION_MAX,
|
|
}
|
|
|
|
/// <summary>Specifies the type of authentication which must occur in order for traffic to be allowed.</summary>
|
|
public enum FirewallAuthenticateType
|
|
{
|
|
/// <summary>No security check is performed.</summary>
|
|
None = NET_FW_AUTHENTICATE_TYPE.NET_FW_AUTHENTICATE_NONE,
|
|
|
|
/// <summary>
|
|
/// The traffic is allowed if it is IPsec-protected with authentication and no encapsulation protection. This means that the peer is
|
|
/// authenticated, but there is no integrity protection on the data.
|
|
/// </summary>
|
|
NoEncapsulation = NET_FW_AUTHENTICATE_TYPE.NET_FW_AUTHENTICATE_NO_ENCAPSULATION,
|
|
|
|
/// <summary>The traffic is allowed if it is IPsec-protected with authentication and integrity protection.</summary>
|
|
WithIntegrity = NET_FW_AUTHENTICATE_TYPE.NET_FW_AUTHENTICATE_WITH_INTEGRITY,
|
|
|
|
/// <summary>
|
|
/// The traffic is allowed if its is IPsec-protected with authentication and integrity protection. In addition, negotiation of encryption
|
|
/// protections on subsequent packets is requested.
|
|
/// </summary>
|
|
NegotiateEncryption = NET_FW_AUTHENTICATE_TYPE.NET_FW_AUTHENTICATE_AND_NEGOTIATE_ENCRYPTION,
|
|
|
|
/// <summary>
|
|
/// The traffic is allowed if it is IPsec-protected with authentication, integrity and encryption protection since the very first packet.
|
|
/// </summary>
|
|
Encrypt = NET_FW_AUTHENTICATE_TYPE.NET_FW_AUTHENTICATE_AND_ENCRYPT,
|
|
}
|
|
|
|
/// <summary>Specifies the effect of modifications to the current policy.</summary>
|
|
public enum FirewallPolicyModifyState
|
|
{
|
|
/// <summary>Changing or adding a firewall rule or firewall group to the current profile will take effect.</summary>
|
|
Ok = NET_FW_MODIFY_STATE.NET_FW_MODIFY_STATE_OK,
|
|
|
|
/// <summary>
|
|
/// Changing or adding a firewall rule or firewall group to the current profile will not take effect because the profile is
|
|
/// controlled by the group policy.
|
|
/// </summary>
|
|
OverrideGroupPolicy = NET_FW_MODIFY_STATE.NET_FW_MODIFY_STATE_GP_OVERRIDE,
|
|
|
|
/// <summary>
|
|
/// Changing or adding a firewall rule or firewall group to the current profile will not take effect because unsolicited inbound
|
|
/// traffic is not allowed.
|
|
/// </summary>
|
|
InboundBlocked = NET_FW_MODIFY_STATE.NET_FW_MODIFY_STATE_INBOUND_BLOCKED,
|
|
}
|
|
|
|
/// <summary>Specifies the type of profile.</summary>
|
|
[Flags]
|
|
public enum FirewallProfileType
|
|
{
|
|
/// <summary/>
|
|
All = NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_ALL,
|
|
|
|
/// <summary>Profile type is domain.</summary>
|
|
Domain = NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_DOMAIN,
|
|
|
|
/// <summary>Profile type is private. This profile type is used for home and other private network types.</summary>
|
|
Private = NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_PRIVATE,
|
|
|
|
/// <summary>Profile type is public. This profile type is used for public Internet access points.</summary>
|
|
Public = NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_PUBLIC,
|
|
}
|
|
|
|
/// <summary>Specifies the direction of traffic to which a rule applies.</summary>
|
|
public enum RuleDirection
|
|
{
|
|
/// <summary>The rule applies to inbound traffic.</summary>
|
|
In = NET_FW_RULE_DIRECTION.NET_FW_RULE_DIR_IN,
|
|
|
|
/// <summary>The rule applies to outbound traffic.</summary>
|
|
Out = NET_FW_RULE_DIRECTION.NET_FW_RULE_DIR_OUT,
|
|
}
|
|
|
|
/// <summary>Specifies the interface types to which a rule applies.</summary>
|
|
[Flags]
|
|
public enum RuleInterfaceType
|
|
{
|
|
/// <summary>All interfaces</summary>
|
|
All = 0,
|
|
|
|
/// <summary>Local area network interfaces.</summary>
|
|
Lan = 1,
|
|
|
|
/// <summary>Remote access interfaces.</summary>
|
|
RemoteAccess = 2,
|
|
|
|
/// <summary>Wireless interfaces.</summary>
|
|
Wireless = 4,
|
|
}
|
|
|
|
/// <summary>Wrapper for Windows Firewall interface methods (i.e. <see cref="INetFwPolicy2"/>).</summary>
|
|
public static class WindowsFirewall
|
|
{
|
|
private static readonly ComReleaser<INetFwPolicy2> pPol = ComReleaserFactory.Create(new INetFwPolicy2());
|
|
private static FirewallProfile? dom, priv, pub;
|
|
private static FirewallRules? rules, svcRules;
|
|
|
|
static WindowsFirewall()
|
|
{
|
|
if (!PInvokeClient.WindowsVista.IsPlatformSupported())
|
|
throw new PlatformNotSupportedException("Windows Firewall requires Windows Vista or later.");
|
|
}
|
|
|
|
/// <summary>Gets the firewall profile for the active domain.</summary>
|
|
/// <value>The domain profile.</value>
|
|
public static FirewallProfile DomainProfile => dom ??= new FirewallProfile(pPol.Item, NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_DOMAIN);
|
|
|
|
/// <summary>
|
|
/// <para>
|
|
/// The LocalPolicyModifyState attribute determines if adding or setting a rule or group of rules will take effect in the current
|
|
/// firewall profile.
|
|
/// </para>
|
|
/// <para>This property is read-only.</para>
|
|
/// </summary>
|
|
public static FirewallPolicyModifyState LocalPolicyModifyState => (FirewallPolicyModifyState)pPol.Item.LocalPolicyModifyState;
|
|
|
|
/// <summary>Gets the firewall profile for the private network. This profile type is used for home and other private network types.</summary>
|
|
/// <value>The private profile.</value>
|
|
public static FirewallProfile PrivateProfile => priv ??= new FirewallProfile(pPol.Item, NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_PRIVATE);
|
|
|
|
/// <summary>Gets the firewall profile for the public network. This profile type is used for public Internet access points.</summary>
|
|
/// <value>The public profile.</value>
|
|
public static FirewallProfile PublicProfile => pub ??= new FirewallProfile(pPol.Item, NET_FW_PROFILE_TYPE2.NET_FW_PROFILE2_PUBLIC);
|
|
|
|
/// <summary>
|
|
/// <para>Retrieves the collection of firewall rules.</para>
|
|
/// <para>This property is read-only.</para>
|
|
/// </summary>
|
|
public static FirewallRules Rules => rules ??= new FirewallRules(pPol.Item.Rules);
|
|
|
|
/// <summary>Retrieves the collection of Windows Service Hardening networking rules.</summary>
|
|
public static FirewallRules ServiceHardeningRules => svcRules ??= new FirewallRules(pPol.Item.ServiceRestriction.Rules);
|
|
|
|
/// <summary>
|
|
/// <para>Retrieves the interface used to access the Windows Service Hardening store.</para>
|
|
/// <para>This property is read-only.</para>
|
|
/// </summary>
|
|
public static INetFwServiceRestriction ServiceRestriction => pPol.Item.ServiceRestriction;
|
|
|
|
/// <summary>
|
|
/// The <c>get_IsRuleGroupCurrentlyEnabled</c> method determines whether a specified group of firewall rules are enabled or disabled for
|
|
/// the current profile.
|
|
/// </summary>
|
|
/// <param name="group">
|
|
/// A string that was used to group rules together. It can be the group name or an indirect string to the group name in the form of
|
|
/// "@C:\Program Files\Contoso Storefront\StorefrontRes.dll,-1234". Rules belonging to this group would be queried.
|
|
/// </param>
|
|
/// <returns>
|
|
/// <para>
|
|
/// This call returns a boolean enable status which indicates whether the group of rules identified by the group parameter are enabled or
|
|
/// disabled. If this value is set to true ( <c>VARIANT_TRUE</c>), the group of rules is enabled; otherwise, the group is disabled.
|
|
/// </para>
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// When indirect strings in the form of "@C:\Program Files\Contoso Storefront\StorefrontRes.dll,-1234" are passed as parameters to the
|
|
/// Windows Firewall with Advanced Security APIs, they should be specified by a full path. The file should have a secure access that
|
|
/// permits the Local Service account read access to allow the Windows Firewall Service to read the strings. To avoid non-privileged
|
|
/// security principals from modifying the strings, the DLLs should only allow write access to the Administrator account.
|
|
/// </remarks>
|
|
public static bool IsRuleGroupEnabled(string group) => pPol.Item.IsRuleGroupCurrentlyEnabled[group];
|
|
|
|
/// <summary>Indicates whether service restriction rules are enabled to limit traffic to the resources specified by the firewall rules.</summary>
|
|
/// <param name="serviceName">Name of the service being queried concerning service restriction state.</param>
|
|
/// <param name="appName">Name of the application being queried concerning service restriction state.</param>
|
|
/// <returns>
|
|
/// Indicates whether service restriction rules are in place to restrict the specified service. If <see langword="true"/>, service is
|
|
/// restricted. Otherwise, service is not restricted to the resources specified by firewall rules.
|
|
/// </returns>
|
|
public static bool IsServiceRestricted(string serviceName, string appName) => pPol.Item.ServiceRestriction.ServiceRestricted(serviceName, appName);
|
|
|
|
/// <summary>The <c>RestoreLocalFirewallDefaults</c> method restores the local firewall configuration to its default state.</summary>
|
|
public static void RestoreLocalFirewallDefaults() => pPol.Item.RestoreLocalFirewallDefaults();
|
|
|
|
/// <summary>The <c>RestrictService</c> method turns service restriction on or off for a given service.</summary>
|
|
/// <param name="serviceName">Name of the service for which service restriction is being turned on or off.</param>
|
|
/// <param name="appName">Name of the application for which service restriction is being turned on or off.</param>
|
|
/// <param name="restrictService">
|
|
/// Indicates whether service restriction is being turned on or off. If this value is <see langword="true"/>, the service will be
|
|
/// restricted when sending or receiving network traffic. The Windows Service Hardening rules collection can contain rules which can
|
|
/// allow this service specific inbound or outbound network access per specific requirements. If <see langword="false"/>, the service is
|
|
/// not restricted by Windows Service Hardening.
|
|
/// </param>
|
|
/// <param name="serviceSidRestricted">
|
|
/// Indicates the type of service SID for the specified service. If this value is <see langword="true"/>, the service SID will be
|
|
/// restricted. Otherwise, it will be unrestricted.
|
|
/// </param>
|
|
/// <remarks>When adding rules, note that there may be a small time lag before the newly-added rule is applied.</remarks>
|
|
public static void RestrictService(string serviceName, string appName, bool restrictService, bool serviceSidRestricted) =>
|
|
pPol.Item.ServiceRestriction.RestrictService(serviceName, appName, restrictService, serviceSidRestricted);
|
|
}
|
|
|
|
/// <summary>Represents a profile of the Windows Firewall.</summary>
|
|
public class FirewallProfile
|
|
{
|
|
private readonly INetFwPolicy2 iPol;
|
|
private readonly NET_FW_PROFILE_TYPE2 type;
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="FirewallProfile"/> class with the specified type.</summary>
|
|
/// <param name="type">The profile type.</param>
|
|
public FirewallProfile(FirewallProfileType type) : this(new(), (NET_FW_PROFILE_TYPE2)type) { }
|
|
|
|
internal FirewallProfile(INetFwPolicy2 item, NET_FW_PROFILE_TYPE2 type)
|
|
{
|
|
iPol = item;
|
|
this.type = type;
|
|
}
|
|
|
|
private FirewallProfile() => throw new NotSupportedException();
|
|
|
|
/// <summary>
|
|
/// <para>Indicates whether the firewall should not allow inbound traffic.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// All interfaces are firewall-enabled. This means that all the exceptions (such as GloballyOpenPorts, Applications, or
|
|
/// Services) which are specified in the profile are ignored and only locally-initiated traffic is allowed.
|
|
/// </para>
|
|
/// </remarks>
|
|
public bool BlockAllInboundTraffic { get => iPol.BlockAllInboundTraffic[type]; set => iPol.BlockAllInboundTraffic[type] = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the default action for inbound traffic. These settings are Block by default.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <value>The default inbound action.</value>
|
|
/// <remarks>
|
|
/// All interfaces are firewall-enabled. This means that all the exceptions (such as GloballyOpenPorts, Applications, or
|
|
/// Services) which are specified in the profile, are ignored And only locally-initiated traffic is allowed.
|
|
/// </remarks>
|
|
public FirewallAction DefaultInboundAction { get => (FirewallAction)iPol.DefaultInboundAction[type]; set => iPol.DefaultInboundAction[type] = (NET_FW_ACTION)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the default action for outbound traffic. These settings are Allow by default.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <value>The default outbound action.</value>
|
|
/// <remarks>
|
|
/// All interfaces are firewall-enabled. This means that all the exceptions (such as GloballyOpenPorts, Applications, or
|
|
/// Services) which are specified in the profile are ignored And only locally-initiated traffic is allowed.
|
|
/// </remarks>
|
|
public FirewallAction DefaultOutboundAction { get => (FirewallAction)iPol.DefaultOutboundAction[type]; set => iPol.DefaultOutboundAction[type] = (NET_FW_ACTION)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Indicates whether a firewall is enabled locally (the effective result may differ due to group policy settings).</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public bool Enabled { get => iPol.FirewallEnabled[type]; set => iPol.FirewallEnabled[type] = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies a list of interfaces on which firewall settings are excluded.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <value>The excluded interfaces.</value>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// An excluded interface is an interface to which the firewall is not applicable. The firewall is not applicable to any traffic received
|
|
/// from or sent to an excluded interface. An empty list indicates that there are no excluded interfaces.
|
|
/// </para>
|
|
/// </remarks>
|
|
public string[]? ExcludedInterfaces
|
|
{
|
|
get => iPol.ExcludedInterfaces[type] is null ? null : (string[]?)Array.ConvertAll((object[])iPol.ExcludedInterfaces[type], o => o.ToString());
|
|
set => iPol.ExcludedInterfaces[type] = value is null || value.Length == 0 ? null : Array.ConvertAll(value, s => (object)s);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether interactive firewall notifications are disabled.
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public bool NotificationsDisabled { get => iPol.NotificationsDisabled[type]; set => iPol.NotificationsDisabled[type] = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Indicates whether the firewall should not allow unicast responses to multicast And broadcast traffic.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>If a computer sends a broadcast packet, a unicast response is allowed for three seconds. Use this property to change this behavior.</para>
|
|
/// </remarks>
|
|
public bool UnicastResponsesToMulticastBroadcastDisabled { get => iPol.UnicastResponsesToMulticastBroadcastDisabled[type]; set => iPol.UnicastResponsesToMulticastBroadcastDisabled[type] = value; }
|
|
|
|
/// <summary>The <c>IsRuleGroupEnabled</c> method determines whether a specified group of firewall rules are enabled or disabled.</summary>
|
|
/// <param name="group">
|
|
/// A string that was used to group rules together. It can be the group name or an indirect string to the group name in the form of
|
|
/// "@yourresourcedll.dll,-23255". Rules belonging to this group would be queried.
|
|
/// </param>
|
|
/// <returns>
|
|
/// This call returns a boolean enable status which indicates whether the group of rules identified by the group parameter are enabled or
|
|
/// disabled. If this value is set to true (VARIANT_TRUE), the group of rules is enabled; otherwise, the group is disabled.
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// When indirect strings in the form of "@yourresourcedll.dll,-23255" are passed as parameters to the Windows Firewall with Advanced
|
|
/// Security APIs, they should either be placed under the System32 Windows directory or specified by a full path. Further the file should
|
|
/// have a secure access that permits the Local Service account read access to allow the Windows Firewall Service to read the strings. To
|
|
/// avoid non-privileged security principals from modifying the strings, the DLLs should only allow write access to the Administrator account.
|
|
/// </remarks>
|
|
public bool IsRuleGroupEnabled(string group) => iPol.IsRuleGroupEnabled(type, group);
|
|
}
|
|
|
|
/// <summary>Provides access to the properties of a firewall rule.</summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Each time you change a property of a rule, Windows Firewall commits the rule and verifies it for correctness. As a result, when you edit
|
|
/// a rule, you must perform the steps in a specific order. For example, if you add an ICMP rule, you must first set the protocol to ICMP,
|
|
/// then add the rule. If these steps are taken in the opposite order, an error occurs and the change is lost.
|
|
/// </para>
|
|
/// <para>
|
|
/// If you are editing a TCP port rule and converting it into an ICMP rule, first delete the port, change protocol from TCP to ICMP, and then
|
|
/// add the rule.
|
|
/// </para>
|
|
/// <para>
|
|
/// In order to retrieve and modify existing rules, instances of this interface must be retrieved through INetFwRules. All configuration
|
|
/// changes take place immediately.
|
|
/// </para>
|
|
/// <para>When accessing the properties of a rule, keep in mind that there may be a small time lag before a newly-added rule is applied.</para>
|
|
/// <para>Properties are used to create firewall rules. Many of the properties can be used in order to create very specific firewall rules.</para>
|
|
/// <list type="table">
|
|
/// <listheader>
|
|
/// <term>Property</term>
|
|
/// <term>Type and format</term>
|
|
/// <term>Constraints</term>
|
|
/// </listheader>
|
|
/// <rule>
|
|
/// <term>Name</term>
|
|
/// <term>Clear text string.</term>
|
|
/// <term>Required. The string must not contain a "|" and it must not be "all".</term>
|
|
/// </rule><rule>
|
|
/// <term>Description</term>
|
|
/// <term>Clear text string.</term>
|
|
/// <term>Optional. The string must not contain a "|".</term>
|
|
/// </rule><rule>
|
|
/// <term>Grouping</term>
|
|
/// <term>String in the format "@<dll name>, <resource string identifier>".</term>
|
|
/// <term>Required.</term>
|
|
/// </rule><rule>
|
|
/// <term>Enabled</term>
|
|
/// <term>Boolean (VARIANT_BOOLEAN).</term>
|
|
/// <term>Optional. Defaults to false (VARIANT_FALSE) if nothing is specified.</term>
|
|
/// </rule><rule>
|
|
/// <term>ApplicationName</term>
|
|
/// <term>Clear text string.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>ServiceName</term>
|
|
/// <term>Clear text string.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>LocalPorts</term>
|
|
/// <term>Clear text string containing a list of port numbers. "RPC" is an acceptable value.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>RemotePorts</term>
|
|
/// <term>Clear text string containing a list of port numbers.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>LocalAddresses</term>
|
|
/// <term>Clear text string containing a list of IPv4 and IPv6 addresses separated by commas. Range values and"*"are acceptable in this list.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>RemoteAddresses</term>
|
|
/// <term>Clear text string containing a list of IPv4 and IPv6 addresses separated by commas. Range values and"*"are acceptable in this list.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>Protocol</term>
|
|
/// <term>Number.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>put_Profiles</term>
|
|
/// <term>
|
|
/// String value in the format "type, code". Multiple types and codes can be included in the string by separating each pair with a ";".
|
|
/// </term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>Interfaces</term>
|
|
/// <term>Array of strings containing the friendly names of interfaces.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>InterfaceTypes</term>
|
|
/// <term>
|
|
/// String value. Multiple interface types can be included in the string by separating each value with a ",". Acceptable values are
|
|
/// "RemoteAccess", "Wireless", "Lan", and "All".
|
|
/// </term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>Direction</term>
|
|
/// <term>Enumeration.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>Action</term>
|
|
/// <term>Enumeration.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>EdgeTraversal</term>
|
|
/// <term>Boolean (VARIANT_BOOLEAN).</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule><rule>
|
|
/// <term>Profiles</term>
|
|
/// <term>Enumeration.</term>
|
|
/// <term>Optional.</term>
|
|
/// </rule>
|
|
/// </list>
|
|
/// <para>For additional information on each property, please see the corresponding topic.</para>
|
|
/// </remarks>
|
|
/// <seealso cref="INamedEntity"/>
|
|
public class FirewallRule : INamedEntity, IEquatable<FirewallRule>
|
|
{
|
|
internal readonly INetFwRule iRule;
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="FirewallRule"/> class.</summary>
|
|
/// <param name="name">The friendly name for the rule.</param>
|
|
/// <param name="group">The group name for the rule.</param>
|
|
/// <param name="allow">If set to <see langword="true"/>, this is an allow rule; otherwise a blocking rule.</param>
|
|
/// <param name="in">If set to <see langword="true"/>, the direction is in; otherwise it is out.</param>
|
|
/// <param name="description">The optional description.</param>
|
|
public FirewallRule(string name, string? group, bool allow = true, bool @in = true, string? description = null)
|
|
{
|
|
iRule = new INetFwRule();
|
|
Name = name;
|
|
Grouping = group;
|
|
Action = (FirewallAction)(allow ? NET_FW_ACTION.NET_FW_ACTION_ALLOW : NET_FW_ACTION.NET_FW_ACTION_BLOCK);
|
|
Direction = (RuleDirection)(@in ? NET_FW_RULE_DIRECTION.NET_FW_RULE_DIR_IN : NET_FW_RULE_DIRECTION.NET_FW_RULE_DIR_OUT);
|
|
Description = description;
|
|
}
|
|
|
|
internal FirewallRule(INetFwRule netFwRule) => iRule = netFwRule;
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the action for a rule or default setting.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public FirewallAction Action { get => (FirewallAction)iRule.Action; set => iRule.Action = (NET_FW_ACTION)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the friendly name of the application to which this rule applies.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(null)]
|
|
public string? ApplicationName { get => iRule.ApplicationName; set => iRule.ApplicationName = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the description of this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional. The string must not contain the "|" character.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(null)]
|
|
public string? Description { get => iRule.Description; set => iRule.Description = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the direction of traffic for which the rule applies.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional. If this property is not specified, the default value is <c>in</c>.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(NET_FW_RULE_DIRECTION.NET_FW_RULE_DIR_IN)]
|
|
public RuleDirection Direction { get => (RuleDirection)iRule.Direction; set => iRule.Direction = (NET_FW_RULE_DIRECTION)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Indicates whether edge traversal is enabled or disabled for this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The EdgeTraversal property indicates that specific inbound traffic is allowed to tunnel through NATs and other edge devices using the
|
|
/// Teredo tunneling technology. In order for this setting to work correctly, the application or service with the inbound firewall rule
|
|
/// needs to support IPv6. The primary application of this setting allows listeners on the host to be globally addressable through a
|
|
/// Teredo IPv6 address.
|
|
/// </para>
|
|
/// <para>New rules have the EdgeTraversal property disabled by default.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(false)]
|
|
public bool EdgeTraversal { get => iRule.EdgeTraversal; set => iRule.EdgeTraversal = value; }
|
|
|
|
/// <summary>
|
|
/// <para>This property can be used to access the edge properties of a firewall rule defined by NET_FW_EDGE_TRAVERSAL_TYPE.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public EdgeTraversalType EdgeTraversalOptions { get => (EdgeTraversalType)iRule2.EdgeTraversalOptions; set => iRule2.EdgeTraversalOptions = (NET_FW_EDGE_TRAVERSAL_TYPE)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Enables or disables a rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional. A new rule is disabled by default.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public bool Enabled { get => iRule.Enabled; set => iRule.Enabled = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the group to which an individual rule belongs.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>
|
|
/// Using the Grouping property is highly recommended, as it groups multiple rules into a single line in the Windows Firewall control
|
|
/// panel. This allows the user to enable or disable multiple rules with a single click. The Grouping property can also be specified
|
|
/// using indirect strings. In this case, a group description can also be specified that will appear in the rule group properties in the
|
|
/// Windows Firewall control panel. For example, if the group string is specified by an indirect string at index 1005
|
|
/// ("@yourresources.dll,-1005"), the group description can be specified at a resource string higher by 10000 "@youresources.dll,-11005."
|
|
/// </para>
|
|
/// <para>
|
|
/// When indirect strings in the form of "h" are passed as parameters to the Windows Firewall with Advanced Security APIs, they should
|
|
/// either be placed under the System32 Windows directory or specified by a full path. Further, the file should have a secure access that
|
|
/// permits the Local Service account read access to allow the Windows Firewall Service to read the strings. To avoid non-privileged
|
|
/// security principals from modifying the strings, the DLLs should only allow write access to the Administrator account.
|
|
/// </para>
|
|
/// </remarks>
|
|
public Windows.Shell.IndirectString? Grouping { get => iRule.Grouping is null ? null : new(iRule.Grouping); set => iRule.Grouping = value?.RawValue; }
|
|
|
|
// <summary> <para>Specifies the list of ICMP types and codes for this rule.</para> <para>This property is read/write.</para> </summary>
|
|
// <remarks> <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
// <para> The icmpTypesAndCodes parameter is a list of ICMP types and codes separated by semicolon. "*" indicates all ICMP types and
|
|
// codes. </para> </remarks>
|
|
public (byte icmpType, ushort icmpCode)[]? IcmpTypesAndCodes
|
|
{
|
|
get
|
|
{
|
|
if (iRule.IcmpTypesAndCodes == "*")
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[]? s = iRule.IcmpTypesAndCodes.FromDelim(';');
|
|
return s is null ? null : Array.ConvertAll(s, StrToPair);
|
|
|
|
static (byte icmpType, ushort icmpCode) StrToPair(string input)
|
|
{
|
|
System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(input, @"(\d{1,3})\:(\d{1,3}|\*)");
|
|
return !m.Success
|
|
? throw new InvalidCastException($"Unable to parse ICMP type and code: {input}")
|
|
: ((byte icmpType, ushort icmpCode))(byte.Parse(m.Groups[1].Value), m.Groups[2].Value == "*" ? (ushort)0x100 : ushort.Parse(m.Groups[2].Value));
|
|
}
|
|
}
|
|
|
|
set => iRule.IcmpTypesAndCodes = value is null ? null : Array.ConvertAll(value, p => $"{p.icmpType}:{p.icmpCode}").ToDelim(';');
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of interfaces for which the rule applies.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional. The interfaces in the list are represented by their friendly name.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public string[]? InterfaceNames
|
|
{
|
|
get => iRule.Interfaces is null ? null : (string[]?)Array.ConvertAll((object[])iRule.Interfaces, o => o.ToString());
|
|
set => iRule.Interfaces = value is null || value.Length == 0 ? null : Array.ConvertAll(value, s => (object)s);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of interfaces for which the rule applies.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional. The interfaces in the list are represented by their friendly name.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public System.Net.NetworkInformation.NetworkInterface[]? Interfaces
|
|
{
|
|
get
|
|
{
|
|
if (iRule.Interfaces is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[] ifList = iRule.GetInterfaces();
|
|
return System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces().Where(i => ifList.Contains(i.Name)).ToArray();
|
|
}
|
|
|
|
set => iRule.Interfaces = value is null || value.Length == 0 ? null : Array.ConvertAll(value, i => (object)i.Name);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of interface types for which the rule applies.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(0)]
|
|
public RuleInterfaceType InterfaceTypes
|
|
{
|
|
get => (RuleInterfaceType)Enum.Parse(typeof(RuleInterfaceType), iRule.InterfaceTypes ?? "All");
|
|
set => iRule.InterfaceTypes = value.ToString().Replace(" ", "");
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of local addresses for this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>
|
|
/// The localAddrs parameter consists of one or more comma-delimited tokens specifying the local addresses from which the application can
|
|
/// listen for traffic. "*" is the default value. Valid tokens include:
|
|
/// </para>
|
|
/// <list type="bullet"><rule>
|
|
/// <term>"*" indicates any local address. If present, this must be the only token included.</term>
|
|
/// </rule><rule>
|
|
/// <term>"Defaultgateway"</term>
|
|
/// </rule><rule>
|
|
/// <term>"DHCP"</term>
|
|
/// </rule><rule>
|
|
/// <term>"WINS"</term>
|
|
/// </rule><rule>
|
|
/// <term>"LocalSubnet" indicates any local address on the local subnet. This token is not case-sensitive.</term>
|
|
/// </rule><rule>
|
|
/// <term>
|
|
/// A subnet can be specified using either the subnet mask or network prefix notation. If neither a subnet mask not a network prefix is
|
|
/// specified, the subnet mask defaults to 255.255.255.255.
|
|
/// </term>
|
|
/// </rule><rule>
|
|
/// <term>A valid IPv6 address.</term>
|
|
/// </rule><rule>
|
|
/// <term>An IPv4 address range in the format of "start address - end address" with no spaces included.</term>
|
|
/// </rule><rule>
|
|
/// <term>An IPv6 address range in the format of "start address - end address" with no spaces included.</term>
|
|
/// </rule>
|
|
/// </list>
|
|
/// </remarks>
|
|
public string[]? LocalAddresses { get => iRule.LocalAddresses.FromDelim(','); set => iRule.LocalAddresses = value.ToDelim(','); }
|
|
|
|
/// <summary>
|
|
/// <para>
|
|
/// Specifies the package identifier or the app container identifier of a process, whether from a Windows Store app or a desktop app.
|
|
/// </para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public string LocalAppPackageId { get => iRule3.LocalAppPackageId; set => iRule3.LocalAppPackageId = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of local ports for this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>The Protocol property must be set before the <c>LocalPorts</c> property or an error will be returned.</para>
|
|
/// </remarks>
|
|
public string[]? LocalPorts { get => iRule.LocalPorts.FromDelim(','); set => iRule.LocalPorts = value.ToDelim(','); }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies a list of authorized local users for an app container.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public RawSecurityDescriptor? LocalUserAuthorizedList
|
|
{
|
|
get => iRule3.LocalUserAuthorizedList.ToSD();
|
|
set => iRule3.LocalUserAuthorizedList = value.FromSD();
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the user security identifier (SID) of the user who is the owner of the rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If this rule does not specify <c>localUserConditions</c>, all the traffic that this rule matches must be destined to or originated
|
|
/// from this user.
|
|
/// </remarks>
|
|
public SecurityIdentifier? LocalUserOwner
|
|
{
|
|
get => iRule3.LocalUserOwner is null ? null : new(iRule3.LocalUserOwner);
|
|
set => iRule3.LocalUserOwner = value?.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the friendly name of this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is required. The string must not contain the "|" character.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public string Name { get => iRule.Name; set => iRule.Name = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the profiles to which the rule belongs.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
[DefaultValue(FirewallProfileType.All)]
|
|
public FirewallProfileType Profiles { get => (FirewallProfileType)iRule.Profiles; set => iRule.Profiles = (NET_FW_PROFILE_TYPE2)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the IP protocol of this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>The <c>Protocol</c> property must be set before the LocalPorts or RemotePorts properties or an error will be returned.</para>
|
|
/// <para>A list of protocol numbers is available at the IANA website.</para>
|
|
/// </remarks>
|
|
[DefaultValue(256)]
|
|
public int Protocol { get => iRule.Protocol; set => iRule.Protocol = value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of remote addresses for this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>
|
|
/// The remoteAddrs parameter consists of one or more comma-delimited tokens specifying the remote addresses from which the application
|
|
/// can listen for traffic. The default value is "*". Valid tokens include:
|
|
/// </para>
|
|
/// <list type="bullet"><rule>
|
|
/// <term>"*" indicates any remote address. If present, this must be the only token included.</term>
|
|
/// </rule><rule>
|
|
/// <term>"Defaultgateway"</term>
|
|
/// </rule><rule>
|
|
/// <term>"DHCP"</term>
|
|
/// </rule><rule>
|
|
/// <term>"DNS"</term>
|
|
/// </rule><rule>
|
|
/// <term>"WINS"</term>
|
|
/// </rule><rule>
|
|
/// <term>"LocalSubnet" indicates any local address on the local subnet. This token is not case-sensitive.</term>
|
|
/// </rule><rule>
|
|
/// <term>
|
|
/// A subnet can be specified using either the subnet mask or network prefix notation. If neither a subnet mask not a network prefix is
|
|
/// specified, the subnet mask defaults to 255.255.255.255.
|
|
/// </term>
|
|
/// </rule><rule>
|
|
/// <term>A valid IPv6 address.</term>
|
|
/// </rule><rule>
|
|
/// <term>An IPv4 address range in the format of "start address - end address" with no spaces included.</term>
|
|
/// </rule><rule>
|
|
/// <term>An IPv6 address range in the format of "start address - end address" with no spaces included.</term>
|
|
/// </rule>
|
|
/// </list>
|
|
/// </remarks>
|
|
public string[]? RemoteAddresses { get => iRule.RemoteAddresses.FromDelim(','); set => iRule.RemoteAddresses = value.ToDelim(','); }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies a list of remote computers which are authorized to access an app container.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public RawSecurityDescriptor? RemoteMachineAuthorizedList { get => iRule3.RemoteMachineAuthorizedList.ToSD(); set => iRule3.RemoteMachineAuthorizedList = value.FromSD(); }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the list of remote ports for this rule.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>This property is optional.</para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// <para>The Protocol property must be set before the <c>RemotePorts</c> property or an error will be returned.</para>
|
|
/// </remarks>
|
|
public string[]? RemotePorts { get => iRule.RemotePorts.FromDelim(','); set => iRule.RemotePorts = value.ToDelim(','); }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies a list of remote users who are authorized to access an app container.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public RawSecurityDescriptor? RemoteUserAuthorizedList { get => iRule3.RemoteUserAuthorizedList.ToSD(); set => iRule3.RemoteUserAuthorizedList = value.FromSD(); }
|
|
|
|
/// <summary>
|
|
/// <para>
|
|
/// Specifies which firewall verifications of security levels provided by IPsec must be guaranteed to allow the collection. The allowed
|
|
/// values must correspond to those of the NET_FW_AUTHENTICATE_TYPE enumeration.
|
|
/// </para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
public FirewallAuthenticateType SecureFlags { get => (FirewallAuthenticateType)iRule3.SecureFlags; set => iRule3.SecureFlags = (NET_FW_AUTHENTICATE_TYPE)value; }
|
|
|
|
/// <summary>
|
|
/// <para>Specifies the service name property of the application.</para>
|
|
/// <para>This property is read/write.</para>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This property is optional. A serviceName value of "*" indicates that a service, not an application, must be sending or receiving traffic.
|
|
/// </para>
|
|
/// <para>Also see the restrictions on changing properties described in the Remarks section of the <see cref="FirewallRule"/> class.</para>
|
|
/// </remarks>
|
|
public string ServiceName { get => iRule.serviceName; set => iRule.serviceName = value; }
|
|
|
|
private INetFwRule2 iRule2 => iRule as INetFwRule2 ?? throw new NotSupportedException();
|
|
private INetFwRule3 iRule3 => iRule as INetFwRule3 ?? throw new NotSupportedException();
|
|
|
|
/// <inheritdoc/>
|
|
public bool Equals(FirewallRule other) => Equals(other.Name, Name) &&
|
|
Equals(other.Profiles, Profiles) &&
|
|
Equals(other.Direction, Direction) &&
|
|
Equals(other.Enabled, Enabled) &&
|
|
Equals(other.Action, Action) &&
|
|
Equals(other.ApplicationName, ApplicationName);
|
|
}
|
|
|
|
/// <summary>Represents the rules for the Windows Firewall.</summary>
|
|
/// <seealso cref="IReadOnlyList{T}"/>
|
|
/// <seealso cref="ICollection{T}"/>
|
|
public class FirewallRules : IReadOnlyList<FirewallRule>, ICollection<FirewallRule>
|
|
{
|
|
private readonly INetFwRules iRules;
|
|
|
|
internal FirewallRules(INetFwRules rules) => iRules = rules;
|
|
|
|
private FirewallRules() => throw new NotSupportedException();
|
|
|
|
/// <inheritdoc/>
|
|
public int Count => iRules.Count;
|
|
|
|
/// <inheritdoc/>
|
|
bool ICollection<FirewallRule>.IsReadOnly => false;
|
|
|
|
/// <summary>Gets the <see cref="FirewallRule"/> with the specified name.</summary>
|
|
/// <value>The <see cref="FirewallRule"/>.</value>
|
|
/// <param name="name">The name of the rule to retrieve.</param>
|
|
/// <returns>The element with the specified name.</returns>
|
|
public FirewallRule this[string name] => new(iRules.Item(name));
|
|
|
|
/// <inheritdoc/>
|
|
public FirewallRule this[int index] => this.ToArray()[index];
|
|
|
|
/// <summary>The <c>Add</c> method adds a new rule to the collection.</summary>
|
|
/// <param name="rule">Rule to be added to the collection.</param>
|
|
/// <remarks>
|
|
/// <para>If a rule with the same rule identifier as the one being submitted already exists, the existing rule is overwritten.</para>
|
|
/// <para>Adding a firewall rule with a LocalAppPackageId specified can lead to unexpected behavior and is not supported.</para>
|
|
/// </remarks>
|
|
public void Add(FirewallRule rule) => iRules.Add(rule.iRule);
|
|
|
|
/// <inheritdoc/>
|
|
public void Clear()
|
|
{
|
|
IEnumerator enumerator = iRules.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
iRules.Remove(((INetFwRule)enumerator.Current).Name);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public bool Contains(FirewallRule item) => ((IEnumerable<FirewallRule>)this).Contains(item);
|
|
|
|
/// <inheritdoc/>
|
|
public void CopyTo(FirewallRule[] array, int arrayIndex) => Array.Copy(this.ToArray(), 0, array, arrayIndex, Count);
|
|
|
|
/// <inheritdoc/>
|
|
public IEnumerator<FirewallRule> GetEnumerator()
|
|
{
|
|
IEnumerator enumerator = iRules.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
yield return new FirewallRule((INetFwRule)enumerator.Current);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public int IndexOf(FirewallRule item) => this.Select((value, index) => new { value, index })
|
|
.Where(pair => Equals(pair.value, item))
|
|
.Select(pair => pair.index + 1)
|
|
.FirstOrDefault() - 1;
|
|
|
|
/// <inheritdoc/>
|
|
public bool Remove(FirewallRule item) => Remove(item.Name);
|
|
|
|
/// <summary>The <c>Remove</c> method removes a rule from the collection.</summary>
|
|
/// <param name="name">Name of the rule to remove from the collection.</param>
|
|
/// <remarks>If a rule specified by the name parameter does not exist in the collection, the <c>Remove</c> method has no effect.</remarks>
|
|
public bool Remove(string name)
|
|
{
|
|
try { iRules.Remove(name); return true; } catch { return false; }
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public void RemoveAt(int index) => Remove(this[index].Name);
|
|
|
|
/// <inheritdoc/>
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
|
|
internal static class FwExt
|
|
{
|
|
public static string[]? FromDelim(this string? list, char sep) => string.IsNullOrEmpty(list) ? null : list?.Split(new char[] { sep }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
public static string? FromSD(this RawSecurityDescriptor? sd) => sd?.GetSddlForm(AccessControlSections.Owner | AccessControlSections.Access);
|
|
|
|
public static string? ToDelim(this string[]? list, char sep) => list is null || list.Length == 0 ? null : string.Join(sep.ToString(), list);
|
|
|
|
public static RawSecurityDescriptor? ToSD(this string? sddl) => sddl is null ? null : new(sddl);
|
|
} |