/// <summary> /// Add item to internal query list (asking user whether to allow this connection request), if there is no block rule available. /// </summary> /// <param name="pid"></param> /// <param name="path"></param> /// <param name="target"></param> /// <param name="protocol"></param> /// <param name="targetPort"></param> /// <param name="localPort"></param> /// /// <returns>false if item is blocked and was thus not added to internal query list</returns> internal bool AddItem(CurrentConn conn) { try { var sourcePortAsInt = int.Parse(conn.SourcePort); var existing = Dispatcher.Invoke(() => this.Connections.FirstOrDefault(c => StringComparer.InvariantCultureIgnoreCase.Equals(c.Path, conn.Path) && c.TargetIP == conn.TargetIP && c.TargetPort == conn.TargetPort && (sourcePortAsInt >= IPHelper.GetMaxUserPort() || c.SourcePort == conn.SourcePort) && c.RawProtocol == conn.RawProtocol)); if (existing != null) { LogHelper.Debug("Connection matches an already existing connection request."); if (!existing.LocalPortArray.Contains(sourcePortAsInt)) { existing.LocalPortArray.Add(sourcePortAsInt); //Note: Unfortunately, C# doesn't have a simple List that automatically sorts... :( // TODO: it does with SortedSet. Don't get this comment... // existing.LocalPortArray.Sort(); existing.SourcePort = IPHelper.MergePorts(existing.LocalPortArray); } existing.TentativesCounter++; } else { ServiceInfoResult svcInfo = null; if (Settings.Default.EnableServiceDetection) { svcInfo = ServiceNameResolver.GetServiceInfo(conn.Pid, conn.FileName); } conn.CurrentAppPkgId = ProcessHelper.GetAppPkgId(conn.Pid); conn.CurrentLocalUserOwner = ProcessHelper.GetLocalUserOwner(conn.Pid); conn.CurrentService = svcInfo?.DisplayName; conn.CurrentServiceDesc = svcInfo?.Name; // Check whether this connection is blocked by a rule. var blockingRules = FirewallHelper.GetMatchingRules(conn.Path, conn.CurrentAppPkgId, conn.RawProtocol, conn.TargetIP, conn.TargetPort, conn.SourcePort, conn.CurrentServiceDesc, conn.CurrentLocalUserOwner, blockOnly: true, outgoingOnly: true); if (blockingRules.Any()) { LogHelper.Info("Connection matches a block-rule!"); LogHelper.Debug($"pid: {Process.GetCurrentProcess().Id} GetMatchingRules: {conn.FileName}, {conn.Protocol}, {conn.TargetIP}, {conn.TargetPort}, {conn.SourcePort}, {svcInfo?.Name}"); return(false); } conn.LocalPortArray.Add(sourcePortAsInt); Dispatcher.Invoke(() => this.Connections.Add(conn)); return(true); } } catch (Exception e) { LogHelper.Error("Unable to add the connection to the pool.", e); } return(false); }
private static void SkipAllEntriesFromRules() { for (int i = ((App)Application.Current).Connections.Count - 1; i >= 0; i--) { var c = ((App)Application.Current).Connections[i]; if (FirewallHelper.GetMatchingRules(c.Path, c.CurrentAppPkgId, c.RawProtocol, c.TargetIP, c.TargetPort, c.SourcePort, c.CurrentService, c.CurrentLocalUserOwner, false).Any()) //FIXME: LocalPort may have multiple!) { LogHelper.Debug("Auto-removing a similar connection..."); ((App)Application.Current).Connections.Remove(c); } } }
private void createRule(bool doAllow, bool isTemp) { bool success = false; var activeConn = ((CurrentConn)lstConnections.SelectedItem); if ((!_optionsView.IsProtocolChecked) && (_optionsView.IsLocalPortChecked || _optionsView.IsTargetPortChecked)) { MessageBox.Show(Common.Properties.Resources.MSG_RULE_PROTOCOL_NEEDED, Common.Properties.Resources.MSG_DLG_ERR_TITLE, MessageBoxButton.OK, MessageBoxImage.Error); return; } string[] services = null; if (_optionsView.IsServiceRuleChecked) { if (activeConn.PossibleServices != null && activeConn.PossibleServices.Length > 0) { ServicesForm sf = new ServicesForm(activeConn); if ((bool)sf.ShowDialog()) { services = sf.SelectedServices; } else { return; } } else { services = new[] { activeConn.CurrentService }; } } if (doAllow) { success = createAllowRule(activeConn, services, isTemp); } else { success = createBlockRule(activeConn, services, isTemp); } if (success) { LogHelper.Info("New rule for connection successfully created!"); for (int i = ((App)Application.Current).Connections.Count - 1; i >= 0; i--) { var c = ((App)Application.Current).Connections[i]; string[] svc = new string[0]; if (!String.IsNullOrEmpty(c.CurrentService)) { svc = new[] { c.CurrentService }; } if (FirewallHelper.GetMatchingRules(c.CurrentPath, c.CurrentAppPkgId, c.Protocol, c.Target, c.TargetPort, c.LocalPort, svc, c.CurrentLocalUserOwner, false).Any()) //FIXME: LocalPort may have multiple!) { LogHelper.Debug("Auto-removing a similar connection..."); ((App)Application.Current).Connections.Remove(c); } } if (((App)Application.Current).Connections.Count == 0) { LogHelper.Debug("No connections left; closing notification window."); this.Close(); } } else { MessageBox.Show(Common.Properties.Resources.MSG_RULE_FAILED, Common.Properties.Resources.MSG_DLG_ERR_TITLE, MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// Add item to internal query list (asking user whether to allow this connection request), if there is no block rule available. /// </summary> /// <param name="pid"></param> /// <param name="threadid"></param> /// <param name="path"></param> /// <param name="target"></param> /// <param name="protocol"></param> /// <param name="targetPort"></param> /// <param name="localPort"></param> /// <returns>false if item is blocked and was thus not added to internal query list</returns> internal bool AddItem(int pid, int threadid, string path, string target, int protocol, int targetPort, int localPort) { try { string fileName = System.IO.Path.GetFileName(path); if (path != "System") { path = FileHelper.GetFriendlyPath(path); } //FIXME: Do a proper path compare...? CASE! var existing = this.Connections.FirstOrDefault(c => c.CurrentPath == path && c.Target == target && c.TargetPort == targetPort.ToString() && (localPort >= IPHelper.GetMaxUserPort() || c.LocalPort == localPort.ToString()) && c.Protocol == protocol); if (existing != null) { LogHelper.Debug("Connection matches an already existing connection request."); if (!existing.LocalPortArray.Contains(localPort)) { existing.LocalPortArray.Add(localPort); existing.LocalPortArray.Sort(); //Note: Unfortunately, C# doesn't have a simple List that automatically sorts... :( existing.LocalPort = IPHelper.MergePorts(existing.LocalPortArray); } existing.TentativesCounter++; } else { string[] svc = new string[0]; string[] svcdsc = new string[0]; bool unsure = false; string description = null; if (path == "System") { description = "System"; } else { try { if (File.Exists(path)) { description = FileVersionInfo.GetVersionInfo(path).FileDescription; if (String.IsNullOrWhiteSpace(description)) { description = path.Substring(path.LastIndexOf('\\') + 1); } } else { // TODO: this happens when accessing system32 files from a x86 application i.e. File.Exists always returns false; solution would be to target AnyCPU description = path; } } catch (Exception exc) { LogHelper.Error("Unable to check the file description.", exc); description = path + " (not found)"; } if (Settings.Default.EnableServiceDetection) { ProcessHelper.ServiceInfoResult svcInfo = AsyncTaskRunner.GetServiceInfo(pid, fileName); if (svcInfo != null) { svc = new string[] { svcInfo.Name }; svcdsc = new string[] { svcInfo.DisplayName }; unsure = false; } } } // Check whether this connection has been excluded - exclusion means ignore i.e do not notify if (exclusions != null) { // WARNING: check for regressions LogHelper.Debug("Checking exclusions..."); var exclusion = exclusions.FirstOrDefault(e => e.StartsWith(/*svc ??*/ path, StringComparison.InvariantCulture) || svc != null && svc.All(s => e.StartsWith(s, StringComparison.InvariantCulture))); if (exclusion != null) { string[] esplit = exclusion.Split(';'); if (esplit.Length == 1 || (String.IsNullOrEmpty(esplit[1]) || esplit[1] == localPort.ToString()) && (String.IsNullOrEmpty(esplit[2]) || esplit[2] == target) && (String.IsNullOrEmpty(esplit[3]) || esplit[3] == targetPort.ToString()) ) { LogHelper.Info($"Connection is excluded: {exclusion}"); return(false); } } } // Check whether this connection is blocked by a rule. var blockingRules = FirewallHelper.GetMatchingRules(path, ProcessHelper.getAppPkgId(pid), protocol, target, targetPort.ToString(), localPort.ToString(), unsure ? svc : svc.Take(1), ProcessHelper.getLocalUserOwner(pid), blockOnly: true, outgoingOnly: true); if (blockingRules.Any()) { LogHelper.Info("Connection matches a block-rule!"); StringBuilder sb = new StringBuilder(); sb.Append("Blocked by: "); foreach (FirewallHelper.Rule s in blockingRules) { sb.Append(s.Name + ": " + s.ApplicationName + ", " + s.Description + ", " + s.ActionStr + ", " + s.ServiceName + ", " + s.Enabled); } LogHelper.Debug("pid: " + Process.GetCurrentProcess().Id + " GetMatchingRules: " + path + ", " + protocol + ", " + target + ", " + targetPort + ", " + localPort + ", " + String.Join(",", svc)); return(false); } FileVersionInfo fileinfo = null; try { fileinfo = FileVersionInfo.GetVersionInfo(path); } catch (FileNotFoundException) { } var conn = new CurrentConn { Description = description, CurrentAppPkgId = ProcessHelper.getAppPkgId(pid), CurrentLocalUserOwner = ProcessHelper.getLocalUserOwner(pid), ProductName = fileinfo != null ? fileinfo.ProductName : String.Empty, Company = fileinfo != null ? fileinfo.CompanyName : String.Empty, CurrentPath = path, Protocol = protocol, TargetPort = targetPort.ToString(), RuleName = String.Format(Common.Properties.Resources.RULE_NAME_FORMAT, unsure || String.IsNullOrEmpty(svcdsc.FirstOrDefault()) ? description : svcdsc.FirstOrDefault()), Target = target, LocalPort = localPort.ToString() }; conn.LocalPortArray.Add(localPort); if (unsure) { //LogHelper.Debug("Adding services (unsure): " + String.Join(",", svc)); conn.PossibleServices = svc; conn.PossibleServicesDesc = svcdsc; } else { //LogHelper.Debug("Adding services: " + svc.FirstOrDefault()); conn.CurrentService = svc.FirstOrDefault(); conn.CurrentServiceDesc = svcdsc.FirstOrDefault(); } ResolveHostForConnection(conn); this.Connections.Add(conn); return(true); } } catch (Exception e) { LogHelper.Error("Unable to add the connection to the pool.", e); } return(false); }
public static void GetService(int pid, int threadid, string path, int protocol, int localport, string target, int remoteport, out string[] svc, out string[] svcdsc, out bool unsure) { // Try to lookup details about connection to localport. //@wokhan: how is this supposed to work since connection is blocked by firewall?? LogHelper.Info("Trying to retrieve service name through connection information."); var ret = IPHelper.GetOwner(pid, localport); if (ret != null && !String.IsNullOrEmpty(ret.ModuleName)) { // Returns the owner only if it's indeed a service. string ServiceDesc = getServiceDesc(ret.ModuleName); if (String.IsNullOrEmpty(ServiceDesc)) { LogHelper.Debug("But no service description matches..."); svc = new string[0]; svcdsc = new string[0]; unsure = false; } else { svc = new[] { ret.ModuleName }; svcdsc = new[] { getServiceDesc(ret.ModuleName) }; unsure = false; LogHelper.Debug("Identified service as: " + String.Join(",", svcdsc)); } return; } // Try to retrieve the module name from the calling thread id. LogHelper.Info("Trying to retrieve service name through thread information."); if (threadid != 0) { Process p; try { p = Process.GetProcessById(pid); } catch (ArgumentException) { p = null; } if (p != null) { var thread = p.Threads.Cast <ProcessThread>().SingleOrDefault(t => t.Id == threadid); if (thread == null) { LogHelper.Debug("The thread " + threadid + " has not been found for PID " + pid); } else { var thaddr = thread.StartAddress.ToInt64(); var module = p.Modules.Cast <ProcessModule>().FirstOrDefault(m => thaddr >= (m.BaseAddress.ToInt64() + m.ModuleMemorySize)); if (module == null) { LogHelper.Debug("The thread has been found, but no module matches."); } else { LogHelper.Debug("The thread has been found for module " + module.ModuleName); string ServiceDesc = getServiceDesc(module.ModuleName); if (String.IsNullOrEmpty(ServiceDesc)) { LogHelper.Debug("But no service description matches..."); svc = new string[0]; svcdsc = new string[0]; unsure = false; } else { svc = new[] { module.ModuleName }; svcdsc = new[] { ServiceDesc }; unsure = false; LogHelper.Debug("Identified service as: " + String.Join(",", svcdsc)); } return; } } } } LogHelper.Info("Trying to retrieve service name through process information."); string[] svcs = GetAllServices(pid); //int protocol = (int)Enum.Parse(typeof(NET_FW_IP_PROTOCOL_), protocolStr); if (svcs == null) { LogHelper.Debug("No services running in process " + pid.ToString() + " found!"); svc = new string[0]; svcdsc = new string[0]; unsure = false; return; } //Only one service? Then we've probably found our guy! if (svcs.Length == 1) { svc = svcs; svcdsc = svcs.Select(s => getServiceDesc(s)).ToArray(); unsure = true; LogHelper.Debug("Identified service as: " + String.Join(",", svcdsc)); return; } svc = new string[0]; // And if it still fails, fall backs to the most ugly way ever I am not able to get rid of :-P // Retrieves corresponding existing rules LogHelper.Info("Trying to retrieve service name through rule information."); int profile = FirewallHelper.GetCurrentProfile(); var cRules = FirewallHelper.GetMatchingRules(path, getAppPkgId(pid), protocol, target, remoteport.ToString(), localport.ToString(), svc, getLocalUserOwner(pid), false, false) .Select(r => r.ServiceName) .Distinct() .ToList(); // Trying to guess the corresponding service if not found with the previous method and if not already filtered svcs = svcs.Except(cRules, StringComparer.CurrentCultureIgnoreCase) .ToArray(); LogHelper.Debug("Excluding " + String.Join(",", cRules) + " // Remains " + String.Join(",", svcs)); if (svcs.Length > 0) { svc = svcs; svcdsc = svcs.Select(s => getServiceDesc(s)).ToArray(); unsure = true; LogHelper.Debug("Identified service as: " + String.Join(",", svcdsc) + " (unsure)"); } else { svcdsc = new string[0]; unsure = false; LogHelper.Debug("No service found!" + String.Join(",", svcdsc)); } return; }