Skip to content

Commit

Permalink
Refactoring: Introduced a custom GeoLocation record (to avoid depende…
Browse files Browse the repository at this point in the history
…ncies to Bing Maps where not required).

Improvement: Added country flags in the connections list and in the map.
Refactoring: too many try/catch blocks in ProcessHelper.GetLocalUserOwner - btw there is something weird with it, see comments.
Misc.: Updated the GeoIP DB.
Improvement: the message regarding the missing DB file is now directly displayed over the map.
Refactoring: partly rewrote the Connection constructor regarding the Owner/Path/Filename resolution.
Refactoring: removed both ReasonColor and DirectionColor from LogEntryViewModel to handle them through conditional styling.
UI: added bullet-shaped background for the protocol column. Looks nicer.
  • Loading branch information
wokhan committed Mar 27, 2023
1 parent 3d846c6 commit 684bfae
Show file tree
Hide file tree
Showing 27 changed files with 617 additions and 449 deletions.
3 changes: 3 additions & 0 deletions Common/Net/GeoLocation/GeoLocation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Wokhan.WindowsFirewallNotifier.Common.Net.GeoLocation;

public record GeoLocation(double? Latitude = 0, double? Longitude = 0, string? Continent = null, string? Country = null, string? CountryISOCode = null, string? City = null, int? AccuracyRadius = 0);
2 changes: 1 addition & 1 deletion Common/Net/IP/IPHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ public static IPAddress GetPublicIpAddress()
private const int buffer_size = 32;
private const int max_hops = 30;
private const int ping_timeout = 4000;
public static async Task<IEnumerable<IPAddress>> GetFullRoute(string adr)
public static async Task<IList<IPAddress>> GetFullRoute(string adr)
{
var ret = new List<IPAddress>();

Expand Down
64 changes: 31 additions & 33 deletions Common/Processes/ProcessHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,54 +403,52 @@ public static string GetLocalUserOwner(uint pid)
LogHelper.Warning($"Unable to retrieve process local user owner: process pid={pid} cannot be found!");
return String.Empty;
}

IntPtr hToken = IntPtr.Zero;
IntPtr hTokenInformation = IntPtr.Zero;
try
{
IntPtr hToken;
if (!NativeMethods.OpenProcessToken(hProcess, NativeMethods.TOKEN_QUERY, out hToken))
{
LogHelper.Warning("Unable to retrieve process local user owner: process pid={pid} cannot be opened!");
return String.Empty;
}
try
{
uint dwBufSize = 0;

if (NativeMethods.GetTokenInformation(hToken, NativeMethods.TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, ref dwBufSize))
{
LogHelper.Warning("Unexpected result from call to GetTokenInformation.");
return String.Empty;
}

IntPtr hTokenInformation = Marshal.AllocHGlobal((int)dwBufSize);
try
{
if (!NativeMethods.GetTokenInformation(hToken, NativeMethods.TOKEN_INFORMATION_CLASS.TokenUser, hTokenInformation, dwBufSize, ref dwBufSize))
{
LogHelper.Warning("Unable to retrieve process local user owner: token cannot be opened!");
return String.Empty;
}

string SID;
if (!NativeMethods.ConvertSidToStringSidW(Marshal.PtrToStructure<NativeMethods.TOKEN_USER>(hTokenInformation).User.Sid, out SID))
{
LogHelper.Warning("Unable to retrieve process local user owner: SID cannot be converted!");
return String.Empty;
}
uint dwBufSize = 0;
//TODO: Wait... isn't a negation missing here?!
if (NativeMethods.GetTokenInformation(hToken, NativeMethods.TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, ref dwBufSize))
{
LogHelper.Warning("Unexpected result from call to GetTokenInformation.");
return String.Empty;
}

return SID;
}
finally
{
Marshal.FreeHGlobal(hTokenInformation);
}
hTokenInformation = Marshal.AllocHGlobal((int)dwBufSize);
if (!NativeMethods.GetTokenInformation(hToken, NativeMethods.TOKEN_INFORMATION_CLASS.TokenUser, hTokenInformation, dwBufSize, ref dwBufSize))
{
LogHelper.Warning("Unable to retrieve process local user owner: token cannot be opened!");
return String.Empty;
}
finally

if (!NativeMethods.ConvertSidToStringSidW(Marshal.PtrToStructure<NativeMethods.TOKEN_USER>(hTokenInformation).User.Sid, out string SID))
{
NativeMethods.CloseHandle(hToken);
LogHelper.Warning("Unable to retrieve process local user owner: SID cannot be converted!");
return String.Empty;
}

return SID;
}
finally
{
if (hTokenInformation != IntPtr.Zero)
{
Marshal.FreeHGlobal(hTokenInformation);
}

if (hToken != IntPtr.Zero)
{
NativeMethods.CloseHandle(hToken);
}

NativeMethods.CloseHandle(hProcess);
}
}
Expand Down
94 changes: 31 additions & 63 deletions Common/UI/ViewModels/ConnectionBaseInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace Wokhan.WindowsFirewallNotifier.Common.UI.ViewModels;

public class ConnectionBaseInfo : ObservableObject
public abstract class ConnectionBaseInfo : ObservableObject
{
public DateTime CreationTime { get; init; }

Expand All @@ -27,105 +27,73 @@ public BitmapSource? Icon
set => this.SetValue(ref _icon, value, OnPropertyChanged);
}

public string? Path { get; protected set; }
public string? FileName { get; protected set; }


protected string? description;
public string? Description
{
get => this.GetOrSetValueAsync(() => SetFileInformation(nameof(description)), ref description, OnPropertyChanged);
protected set => this.SetValue(ref description, value, OnPropertyChanged);
}

protected string? productName;
public string? ProductName
{
get => this.GetOrSetValueAsync(() => SetFileInformation(nameof(productName)), ref productName, OnPropertyChanged);
protected set => this.SetValue(ref productName, value, OnPropertyChanged);
}

protected string? company;
public string? Company
private string? _targetHostName;
public string? TargetHostName
{
get => this.GetOrSetValueAsync(() => SetFileInformation(nameof(company)), ref company, OnPropertyChanged);
protected set => this.SetValue(ref company, value, OnPropertyChanged);
get => this.GetOrSetValueAsync(() => ResolvedIPInformation.ResolveIpAddressAsync(TargetIP), ref _targetHostName, OnPropertyChanged);
protected set => this.SetValue(ref _targetHostName, value, OnPropertyChanged);
}

public string? Path { get; protected set; }
public string? FileName { get; protected set; }
public string? Description { get; protected set; }
public string? ProductName { get; protected set; }
public string? Company { get; protected set; }
public string? ServiceName { get; protected set; }
public string? ServiceDisplayName { get; protected set; }
public string? SourceIP { get; protected set; }
public string? SourcePort { get; set; }
public string? TargetIP { get; protected set; }
public string? TargetPort { get; protected set; }

private string? _targetHostName;
public string? TargetHostName
{
get => this.GetOrSetValueAsync(() => ResolvedIPInformation.ResolveIpAddressAsync(TargetIP), ref _targetHostName, OnPropertyChanged);
protected set => this.SetValue(ref _targetHostName, value, OnPropertyChanged);
}

public int RawProtocol { get; protected set; }
public string? Protocol { get; protected set; }
public string? Direction { get; protected set; }

private bool fileInfoResolutionTriggered;

private string? SetFileInformation(string fieldName)
protected void SetProductInfo()
{
if (fileInfoResolutionTriggered)
// Setting default values
Description = Path;
ProductName = "?";
Company = "?";

if (Path is null or "-")
{
return null;
return;
}

fileInfoResolutionTriggered = true;

if (Path == "System")
else if (Path == "System")
{
description = "System";
productName = "System";
company = String.Empty;
Description = "System";
ProductName = "System";
Company = String.Empty;
}
// TODO: To check if stil applies => File.Exists returns false when accessing system32 files from a x86 application; solution would be to target AnyCPU
else if (File.Exists(Path))
{
try
{
var fileinfo = FileVersionInfo.GetVersionInfo(Path);

productName = fileinfo.ProductName ?? String.Empty;
company = fileinfo.CompanyName ?? String.Empty;
ProductName = fileinfo.ProductName ?? String.Empty;
Company = fileinfo.CompanyName ?? String.Empty;

if (string.IsNullOrWhiteSpace(fileinfo.FileDescription))
{
description = FileName;
Description = FileName;
}
else
{
description = fileinfo.FileDescription;
Description = fileinfo.FileDescription;
}
}
catch (Exception exc)
{
LogHelper.Error("Unable to check the file description.", exc);
description = Path;
productName = "?";
company = "?";
Description = Path;
ProductName = "?";
Company = "?";
}
}
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;
productName = "?";
company = "?";
}

return fieldName switch
{
nameof(description) => description,
nameof(productName) => productName,
nameof(company) => company,
_ => String.Empty,
};
}
}
36 changes: 14 additions & 22 deletions Common/UI/ViewModels/LogEntryViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Windows.Media;

using Wokhan.ComponentModel.Extensions;
using Wokhan.WindowsFirewallNotifier.Common.IO.Files;
Expand All @@ -24,11 +23,8 @@ public class LogEntryViewModel : ConnectionBaseInfo
public FilterResult? MatchingFilter => this.GetOrSetValueAsync(() => NetshHelper.FindMatchingFilterInfo(int.Parse(FilterId)), ref _matchingFilter, OnPropertyChanged);
public string? Reason { get; protected set; }
public string? Message { get; protected set; }
public bool IsAllowed { get; private set; }

//TODO: should be in the XAML as conditionally triggered style
public SolidColorBrush? ReasonColor { get; protected set; }

public SolidColorBrush? DirectionColor { get; protected set; }

public static bool TryCreateFromEventLogEntry<T>(EventLogEntry entry, int index, out T? view) where T : LogEntryViewModel, new()
{
Expand All @@ -46,28 +42,24 @@ public class LogEntryViewModel : ConnectionBaseInfo
var protocol = int.Parse(GetReplacementString(entry, 7));

var path = GetReplacementString(entry, 1);
if (path == "-")
{
path = "System";
}
else
{
path = PathResolver.ResolvePath(path);
}
path = (path == "-" ? "System" : PathResolver.ResolvePath(path));

var fileName = System.IO.Path.GetFileName(path);

// try to get the servicename from pid (works only if service is running)
var serviceName = ServiceNameResolver.GetServicName(pid);
//TODO: set this as optional according to the EnableServiceResolution settings (have to check impacts first)
var serviceName = ServiceNameResolver.GetServiceInfo(pid, fileName);

var le = new T()
{
Index = index,
Id = entry.Index,
Pid = pid,
CreationTime = entry.TimeGenerated,
Path = (path == "-" ? "System" : path),
Path = path,
FileName = fileName,
ServiceName = serviceName,
ServiceName = serviceName?.Name,
ServiceDisplayName = serviceName?.DisplayName,
SourceIP = GetReplacementString(entry, 3),
SourcePort = GetReplacementString(entry, 4),
TargetIP = GetReplacementString(entry, 5),
Expand All @@ -80,8 +72,9 @@ public class LogEntryViewModel : ConnectionBaseInfo
Message = entry.Message
};

le.ReasonColor = le.Reason.StartsWith("Block") ? Brushes.OrangeRed : Brushes.Blue;
le.DirectionColor = le.Direction.StartsWith("In") ? Brushes.OrangeRed : Brushes.Black;
le.IsAllowed = !le.Reason.StartsWith("Block");

le.SetProductInfo();

view = le;

Expand All @@ -90,11 +83,10 @@ public class LogEntryViewModel : ConnectionBaseInfo
catch (Exception ex)
{
LogHelper.Error("Cannot parse eventlog entry: eventID=" + entry.InstanceId.ToString(), ex);
}

view = null;

return false;
view = null;
return false;
}
}

private static string? GetReplacementString(EventLogEntry entry, int i)
Expand Down
2 changes: 1 addition & 1 deletion Console/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ResourceDictionary Source="pack://application:,,,/Wokhan.WindowsFirewallNotifier.Common;component/UI/Themes/Light.xaml" />
<ResourceDictionary Source="Resources/Images.xaml" />
</ResourceDictionary.MergedDictionaries>

<BindingConverters:BooleanNegateConverter x:Key="booleanNegator" />
<BindingConverters:UnitFormatConverter x:Key="unitFormatter" />
<BindingConverters:ObjectToBoolConverter x:Key="objectToBool" />
Expand Down
1 change: 1 addition & 0 deletions Console/Console.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="CountryFlag.Wpf" Version="1.0.0" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-beta.701" />
<PackageReference Include="MaxMind.Db" Version="4.0.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="5.1.0" />
Expand Down
Loading

0 comments on commit 684bfae

Please sign in to comment.