/// <summary> /// Handles the process of inspecting a new TCP connection, seeking the user's decision on /// what to do with the connection, and then applying that decision in code in such a way as /// to cause the packet filtering loop to apply the user's decision. /// </summary> /// <param name="connInfo"> /// The state of the appropriate TCP table at the time of the new connectio. /// </param> /// <param name="tcpHeader"> /// The TCP header from the first packet in the new connection/flow. /// </param> /// <param name="isIpv6"> /// Whether or not this is from an IPV6 connection. /// </param> private unsafe void HandleNewTcpConnection(ITcpConnectionInfo connInfo, TcpHeader *tcpHeader, bool isIpv6) { if (tcpHeader == null) { } if (connInfo != null && connInfo.OwnerPid == m_thisPid) { // This is our process. switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); } break; } } else { FirewallResponse response = null; if (connInfo == null || connInfo.OwnerPid == 4 || connInfo.OwnerPid == 0) { var firewallRequest = new FirewallRequest("SYSTEM", tcpHeader->SrcPort, tcpHeader->DstPort, connInfo == null ? 0L : connInfo.OwnerPid); response = ConfirmDenyFirewallAccess?.Invoke(firewallRequest); } else { if (IsInternalIp(connInfo.RemoteAddress)) { response = new FirewallResponse(FirewallAction.DontFilterApplication); m_logger.Info("Don't filter internal IPs."); } else { // No need to null check here, because the above IF catches whenever connInfo // is null. var procPath = connInfo.OwnerProcessPath.Length > 0 ? connInfo.OwnerProcessPath : "SYSTEM"; var firewallRequest = new FirewallRequest(procPath, tcpHeader->SrcPort, tcpHeader->DstPort, connInfo.OwnerPid); response = ConfirmDenyFirewallAccess?.Invoke(firewallRequest); } } if (response == null) { // The user couldn't be bothered to give us an answer, so just go ahead and // let the packet through. switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (byte)FirewallAction.DontFilterApplication); Volatile.Write(ref m_v6EncryptionHints[tcpHeader->SrcPort], (tcpHeader->DstPort == m_httpsStandardPort || tcpHeader->DstPort == m_httpsAltPort)); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (byte)FirewallAction.DontFilterApplication); Volatile.Write(ref m_v4EncryptionHints[tcpHeader->SrcPort], (tcpHeader->DstPort == m_httpsStandardPort || tcpHeader->DstPort == m_httpsAltPort)); } break; } } else { switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (byte)response.Action); Volatile.Write(ref m_v6EncryptionHints[tcpHeader->SrcPort], response.EncryptedHint ?? (tcpHeader->DstPort == m_httpsStandardPort || tcpHeader->DstPort == m_httpsAltPort)); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (byte)response.Action); Volatile.Write(ref m_v4EncryptionHints[tcpHeader->SrcPort], response.EncryptedHint ?? (tcpHeader->DstPort == m_httpsStandardPort || tcpHeader->DstPort == m_httpsAltPort)); } break; } } } }
/// <summary> /// Handles the process of inspecting a new TCP connection, seeking the user's decision on /// what to do with the connection, and then applying that decision in code in such a way as /// to cause the packet filtering loop to apply the user's decision. /// </summary> /// <param name="connInfo"> /// The state of the appropriate TCP table at the time of the new connectio. /// </param> /// <param name="tcpHeader"> /// The TCP header from the first packet in the new connection/flow. /// </param> /// <param name="isIpv6"> /// Whether or not this is from an IPV6 connection. /// </param> private void HandleNewTcpConnection(ITcpConnectionInfo connInfo, WINDIVERT_TCPHDR *tcpHeader, bool isIpv6) { if (tcpHeader != null) { Console.WriteLine(nameof(HandleNewTcpConnection)); if (connInfo != null && connInfo.OwnerPid == m_thisPid) { LoggerProxy.Default.Info(string.Format("Connection from local:{0} -> remote:{1} outbound is our process.", tcpHeader->SrcPort, tcpHeader->DstPort)); // This is our process. switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); } break; } } else { FirewallResponse response = null; if (connInfo == null || connInfo.OwnerPid == 4 || connInfo.OwnerPid == 0) { var firewallRequest = new FirewallRequest("SYSTEM", tcpHeader->SrcPort, tcpHeader->DstPort); response = ConfirmDenyFirewallAccess?.Invoke(firewallRequest); } else { // No need to null check here, because the above IF catches whenever connInfo // is null. var procPath = connInfo.OwnerProcessPath.Length > 0 ? connInfo.OwnerProcessPath : "SYSTEM"; var firewallRequest = new FirewallRequest(procPath, tcpHeader->SrcPort, tcpHeader->DstPort); response = ConfirmDenyFirewallAccess?.Invoke(firewallRequest); } if (response == null) { LoggerProxy.Default.Info("NO RESPONSE"); // The user couldn't be bothered to give us an answer, so just go ahead and // let the packet through. switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); Volatile.Write(ref m_v6EncryptionHints[tcpHeader->SrcPort], (tcpHeader->DstPort == s_httpsStandardPort || tcpHeader->DstPort == s_httpsAltPort)); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); Volatile.Write(ref m_v4EncryptionHints[tcpHeader->SrcPort], (tcpHeader->DstPort == s_httpsStandardPort || tcpHeader->DstPort == s_httpsAltPort)); } break; } } else { LoggerProxy.Default.Info("RESPONSE"); switch (isIpv6) { case true: { Volatile.Write(ref m_v6ShouldFilter[tcpHeader->SrcPort], (int)response.Action); Volatile.Write(ref m_v6EncryptionHints[tcpHeader->SrcPort], response.EncryptedHint ?? (tcpHeader->DstPort == s_httpsStandardPort || tcpHeader->DstPort == s_httpsAltPort)); } break; case false: { Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (int)response.Action); Volatile.Write(ref m_v4EncryptionHints[tcpHeader->SrcPort], response.EncryptedHint ?? (tcpHeader->DstPort == s_httpsStandardPort || tcpHeader->DstPort == s_httpsAltPort)); } break; } } } } else { LoggerProxy.Default.Info("How on earth do we not have a valid TCP header."); // Somehow we fail to have even a valid TCP header here. Let the connection go // through, but warn. LoggerProxy.Default.Warn("TCP header was a null pointer. Allowing packet."); Volatile.Write(ref m_v4ShouldFilter[tcpHeader->SrcPort], (int)FirewallAction.DontFilterApplication); } }