/// <summary> /// Creates a boolean expression expressing the conditions under which the given packet /// variables match this specific packet. /// </summary> /// <param name="ctx">The Z3 context.</param> /// <param name="packet">The packet variables over which to form an expression.</param> /// <returns>A boolean expression.</returns> public BoolExpr Matches(Context ctx, WindowsFirewallPacketVariables packet) { var conjuncts = new List <BoolExpr>(); if (this.SourceAddress != null) { conjuncts.Add(ctx.MkEq(packet.SourceAddress, AddressRange.AddressToBitVecExpr(ctx, this.SourceAddress))); } if (this.SourcePort != null) { conjuncts.Add(ctx.MkEq(packet.SourcePort, PortRange.PortToBitVecExpr(ctx, (int)this.SourcePort))); } if (this.DestinationPort != null) { conjuncts.Add(ctx.MkEq(packet.DestinationPort, PortRange.PortToBitVecExpr(ctx, (int)this.DestinationPort))); } if (this.Protocol != null) { conjuncts.Add(ctx.MkEq(packet.Protocol, NetworkProtocol.ProtocolToBitVecExpr(ctx, (int)this.Protocol))); } return(ctx.MkAnd(conjuncts.ToArray())); }
/// <summary> /// Returns the list of rules matching a packet. /// </summary> /// <param name="ctx">The Z3 context.</param> /// <param name="packetVariables">The packet variables over which an expression is created.</param> /// <param name="model">A specific binding of the packet variables.</param> /// <returns>A list of rules matching the packet variable binding.</returns> public IEnumerable <WindowsFirewallRule> GetMatches(Context ctx, WindowsFirewallPacketVariables packetVariables, Model model) { return(from rule in this.Rules where rule.Enabled where model.Eval(rule.Matches(ctx, packetVariables)).IsTrue select rule); }
/// <summary> /// Checks equivalence of two <see cref="WindowsFirewall"/> instances. /// </summary> /// <param name="f1">First firewall.</param> /// <param name="f2">Second firewall.</param> /// <returns>A report detailing firewall differences, if any.</returns> public static IEnumerable <WindowsFirewallInconsistency> CheckEquivalence(WindowsFirewall f1, WindowsFirewall f2) { var pastInconsistencies = new List <WindowsFirewallPacket>(); using (var ctx = new Context()) { while (true) { Solver s = ctx.MkSolver(); var packetVars = new WindowsFirewallPacketVariables(ctx); BoolExpr firewallInequivalence = ctx.MkNot(ctx.MkIff(f1.Allows(ctx, packetVars), f2.Allows(ctx, packetVars))); BoolExpr matchesPastInconsistency = ctx.MkOr(pastInconsistencies.Select(p => p.Matches(ctx, packetVars)).ToArray()); s.Assert(ctx.MkAnd(firewallInequivalence, ctx.MkNot(matchesPastInconsistency))); if (Status.UNSATISFIABLE == s.Check()) { break; } Model m = s.Model; var packet = new WindowsFirewallPacket(m); pastInconsistencies.Add(packet); var inconsistency = new WindowsFirewallInconsistency { Packet = packet, Firewalls = Tuple.Create(f1, f2), Allowed = Tuple.Create(m.Eval(f1.Allows(ctx, packetVars)).IsTrue, m.Eval(f2.Allows(ctx, packetVars)).IsTrue), RuleMatches = Tuple.Create(f1.GetMatches(ctx, packetVars, m).ToList(), f2.GetMatches(ctx, packetVars, m).ToList()) }; yield return(inconsistency); } } }
/// <summary> /// Builds a boolean expression over free variables which is true only if the /// variables, once bound, represent a packet accepted by this firewall. /// This firewall accepts a packet if it matches zero block rules. If the /// <see cref="WindowsFirewall.BlockByDefault"/> setting is true, packets matching /// zero allow rules are blocked; otherwise, they are allowed. /// </summary> /// <param name="ctx">The Z3 context.</param> /// <param name="packet">The packet to process through this firewall.</param> /// <returns>A Z3 boolean expression.</returns> public BoolExpr Allows(Context ctx, WindowsFirewallPacketVariables packet) { IEnumerable <BoolExpr> blockRules = from rule in this.Rules where rule.Enabled where !rule.Allow select rule.Matches(ctx, packet); BoolExpr hasBlockRuleMatch = ctx.MkOr(blockRules.ToArray()); if (!this.BlockByDefault) { return(ctx.MkNot(hasBlockRuleMatch)); } IEnumerable <BoolExpr> allowRules = from rule in this.Rules where rule.Enabled where rule.Allow select rule.Matches(ctx, packet); BoolExpr hasAllowRuleMatch = ctx.MkOr(allowRules.ToArray()); return(ctx.MkAnd(hasAllowRuleMatch, ctx.MkNot(hasBlockRuleMatch))); }
/// <summary> /// Builds a boolean expression over free variables which is true only if the /// variables, once bound, represent a packet matching this rule. /// </summary> /// <param name="ctx">The Z3 context.</param> /// <param name="packet">The packet to match against this rule.</param> /// <returns>A Z3 boolean expression.</returns> public BoolExpr Matches(Context ctx, WindowsFirewallPacketVariables packet) { BoolExpr[] conjuncts = { this.RemoteAddresses.Contains(ctx, packet.SourceAddress), this.RemotePorts.Contains(ctx, packet.SourcePort), this.LocalPorts.Contains(ctx, packet.DestinationPort), this.Protocol.Matches(ctx, packet.Protocol) }; return ctx.MkAnd(conjuncts); }