Skip to content

Commit

Permalink
Feature/ui (#76)
Browse files Browse the repository at this point in the history
* Prevent iterating over the same ienumerable set twice

* Trim and lower the username before doing the distinct operation as it's trimmed and lowered on the server side anyway.

* Ensure that the entry returned by the username checker actually has the same username, not just the same domain.

* For a username breach, if all entities with that username have been updated more rencently than the breach, skip that breach.

* Display the breach description and the compromised data classs on the BreachEntriesDialog for each entry.

* Added a combined breach checker that runs through all the breach checkers and returns all results at once.
  • Loading branch information
SlightlyMadGargoyle authored and andrew-schofield committed Feb 1, 2019
1 parent f17a409 commit 0c1ba7a
Show file tree
Hide file tree
Showing 13 changed files with 255 additions and 17 deletions.
16 changes: 16 additions & 0 deletions HaveIBeenPwned/BreachCheckers/BreachedEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ public string BreachUsername
}
}

public string Description
{
get
{
return breach.Description;
}
}

public string[] DataClasses
{
get
{
return breach.DataClasses;
}
}

public BreachedEntry(PwEntry entry, IBreach breach)
{
Entry = entry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ public DateTime BreachDate
}
}

public string[] DataClasses
{
get
{
return new[] { "Potential Private Data Leak" };
}
}

public string Description
{
get
{
return "Cloudbleed is a security bug discovered affecting Cloudflare's reverse proxies which could leak private information such as HTTP cookies, authentication tokens, HTTP POST bodies, and other sensitive data.";
}
}

public string Title
{
get
Expand Down
60 changes: 60 additions & 0 deletions HaveIBeenPwned/BreachCheckers/CombinedChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using KeePassLib;
using System.Net.Http;
using Newtonsoft.Json;
using KeePass.Plugins;
using System.Threading.Tasks;
using System.Drawing;
using KeePassExtensions;
using System.Threading;

namespace HaveIBeenPwned.BreachCheckers
{
public class CombinedChecker : BaseChecker
{
BaseChecker[] checkers;

public CombinedChecker(HttpClient httpClient, IPluginHost pluginHost)
: base(httpClient, pluginHost)
{
checkers = new BaseChecker[]
{
new CloudbleedSite.CloudbleedSiteChecker(httpClient, pluginHost),
new HaveIBeenPwnedSite.HaveIBeenPwnedSiteChecker(httpClient, pluginHost),
new HaveIBeenPwnedPassword.HaveIBeenPwnedPasswordChecker(httpClient, pluginHost),
new HaveIBeenPwnedUsername.HaveIBeenPwnedUsernameChecker(httpClient, pluginHost)
};
}

public override Image BreachLogo
{
get { return Resources.hibp.ToBitmap(); }
}

public override string BreachTitle
{
get { return "Combined Checker"; }
}

public async override Task<List<BreachedEntry>> CheckGroup(PwGroup group, bool expireEntries, bool oldEntriesOnly, bool ignoreDeleted, bool ignoreExpired, IProgress<ProgressItem> progressIndicator, Func<bool> canContinue)
{
var results = new List<BreachedEntry>();

foreach (var checker in checkers)
{
if (!canContinue())
{
break;
}

var r = await checker.CheckGroup(group, expireEntries, oldEntriesOnly, ignoreDeleted, ignoreExpired, progressIndicator, canContinue);
results.AddRange(r);
}

return results;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ public string Title {
}
}

public string[] DataClasses
{
get
{
return new[] { "Known Leaked Password" };
}
}

public string Description
{
get
{
return "haveibeenpwned.com indicates that the password used has been exposed in a data breach.";
}
}

public DateTime BreachDate {
get
{
Expand Down
4 changes: 4 additions & 0 deletions HaveIBeenPwned/BreachCheckers/IBreach.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ public interface IBreach

DateTime BreachDate { get; }

string[] DataClasses { get; }

string Domain { get; }

string Username { get; }

string Description { get; }
}
}
5 changes: 4 additions & 1 deletion HaveIBeenPwned/BreachEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public enum BreachEnum
HIBPUsername,

[CheckerType(Name = "Have I Been Pwned", Type = CheckTypeEnum.Password, Description = "This checker will send a partial hash of the password for each entry to the Have I Been Pwned password checker. Your passwords or complete hashes are not disclosed to this service.")]
HIBPPassword
HIBPPassword,

[CheckerType(Name = "CheckAll", Type = CheckTypeEnum.CheckAll, Description = "This checker will return all results from all other checkers.")]
CheckAll
}
}
5 changes: 4 additions & 1 deletion HaveIBeenPwned/CheckTypeEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public enum CheckTypeEnum
Username,

[Display(Name = "Password Checker")]
Password
Password,

[Display(Name = "Check All")]
CheckAll
}
}
2 changes: 2 additions & 0 deletions HaveIBeenPwned/HaveIBeenPwned.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
Expand All @@ -81,6 +82,7 @@
<Compile Include="BreachCheckers\BaseChecker.cs" />
<Compile Include="BreachCheckers\HaveIBeenPwnedPassword\HaveIBeenPwnedPasswordChecker.cs" />
<Compile Include="BreachCheckers\HaveIBeenPwnedPassword\HaveIBeenPwnedPasswordEntry.cs" />
<Compile Include="BreachCheckers\CombinedChecker.cs" />
<Compile Include="BreachCheckers\HaveIBeenPwnedUsername\HaveIBeenPwnedUsernameChecker.cs" />
<Compile Include="BreachCheckers\HaveIBeenPwnedUsername\HaveIBeenPwnedUsernameEntry.cs" />
<Compile Include="DisplayAttribute.cs" />
Expand Down
48 changes: 47 additions & 1 deletion HaveIBeenPwned/HaveIBeenPwnedExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,21 @@ public sealed class HaveIBeenPwnedExt : Plugin
private ToolStripMenuItem haveIBeenPwnedGlobalServiceMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedGlobalUsernameMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedGlobalPasswordMenuItem = null;
private ToolStripMenuItem checkAllGlobalMenuItem = null;

private ToolStripSeparator toolStripSeperatorGroup = null;
private ToolStripMenuItem haveIBeenPwnedGroupMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedGroupServiceMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedGroupUsernameMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedGroupPasswordMenuItem = null;
private ToolStripMenuItem checkAllGroupMenuItem = null;

private ToolStripSeparator toolStripSeperatorEntry = null;
private ToolStripMenuItem haveIBeenPwnedEntryMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedEntryServiceMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedEntryUsernameMenuItem = null;
private ToolStripMenuItem haveIBeenPwnedEntryPasswordMenuItem = null;
private ToolStripMenuItem checkAllEntryMenuItem = null;

private static HttpClient client;
private StatusProgressForm progressForm;
Expand All @@ -53,7 +56,8 @@ public sealed class HaveIBeenPwnedExt : Plugin
{ BreachEnum.HIBPSite, (h,p) => new HaveIBeenPwnedSiteChecker(h, p) },
{ BreachEnum.CloudBleedSite, (h,p) => new CloudbleedSiteChecker(h, p) },
{ BreachEnum.HIBPUsername, (h, p) => new HaveIBeenPwnedUsernameChecker(h, p) },
{ BreachEnum.HIBPPassword, (h, p) => new HaveIBeenPwnedPasswordChecker(h, p) }
{ BreachEnum.HIBPPassword, (h, p) => new HaveIBeenPwnedPasswordChecker(h, p) },
{ BreachEnum.CheckAll, (h, p) => new CombinedChecker(h, p) }
};

public HaveIBeenPwnedExt()
Expand Down Expand Up @@ -140,6 +144,12 @@ public override bool Initialize(IPluginHost host)
haveIBeenPwnedGlobalPasswordMenuItem.Click += this.Database_CheckHaveIBeenPwnedPasswords;
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Add(haveIBeenPwnedGlobalPasswordMenuItem);

checkAllGlobalMenuItem = new ToolStripMenuItem();
checkAllGlobalMenuItem.Text = Resources.MenuItemCheckAllTitle;
checkAllGlobalMenuItem.Image = Resources.hibp.ToBitmap();
checkAllGlobalMenuItem.Click += this.Database_CheckAll;
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Add(checkAllGlobalMenuItem);

tsMenu.Add(haveIBeenPwnedGlobalMenuItem);

// Add group context menu item for the selected group
Expand All @@ -164,6 +174,12 @@ public override bool Initialize(IPluginHost host)
haveIBeenPwnedGroupPasswordMenuItem.Image = Resources.hibp.ToBitmap();
haveIBeenPwnedGroupPasswordMenuItem.Click += this.Group_CheckHaveIBeenPwnedPasswords;
haveIBeenPwnedGroupMenuItem.DropDown.Items.Add(haveIBeenPwnedGroupPasswordMenuItem);

checkAllGroupMenuItem = new ToolStripMenuItem();
checkAllGroupMenuItem.Text = Resources.MenuItemCheckAllTitle;
checkAllGroupMenuItem.Image = Resources.hibp.ToBitmap();
checkAllGroupMenuItem.Click += this.Group_CheckAll;
haveIBeenPwnedGroupMenuItem.DropDown.Items.Add(checkAllGroupMenuItem);

groupContextMenu.Add(haveIBeenPwnedGroupMenuItem);

Expand All @@ -190,6 +206,12 @@ public override bool Initialize(IPluginHost host)
haveIBeenPwnedEntryPasswordMenuItem.Click += this.Entries_CheckHaveIBeenPwnedPasswords;
haveIBeenPwnedEntryMenuItem.DropDown.Items.Add(haveIBeenPwnedEntryPasswordMenuItem);

checkAllEntryMenuItem = new ToolStripMenuItem();
checkAllEntryMenuItem.Text = Resources.MenuItemCheckAllTitle;
checkAllEntryMenuItem.Image = Resources.hibp.ToBitmap();
checkAllEntryMenuItem.Click += this.Entries_CheckAll;
haveIBeenPwnedEntryMenuItem.DropDown.Items.Add(checkAllEntryMenuItem);

entryContextMenu.Add(haveIBeenPwnedEntryMenuItem);

return true;
Expand All @@ -202,29 +224,35 @@ public override void Terminate()
haveIBeenPwnedGlobalServiceMenuItem.Click -= this.Database_CheckHaveIBeenPwnedSites;
haveIBeenPwnedGlobalUsernameMenuItem.Click -= this.Database_CheckHaveIBeenPwnedUsernames;
haveIBeenPwnedGlobalPasswordMenuItem.Click -= this.Database_CheckHaveIBeenPwnedPasswords;
checkAllGlobalMenuItem.Click -= this.Database_CheckAll;
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Remove(haveIBeenPwnedGlobalServiceMenuItem);
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Remove(haveIBeenPwnedGlobalUsernameMenuItem);
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Remove(haveIBeenPwnedGlobalPasswordMenuItem);
haveIBeenPwnedGlobalMenuItem.DropDown.Items.Remove(checkAllGlobalMenuItem);
tsMenu.Remove(haveIBeenPwnedGlobalMenuItem);
tsMenu.Remove(toolStripSeperatorGlobal);

var groupContextMenu = pluginHost.MainWindow.GroupContextMenu.Items;
haveIBeenPwnedGroupServiceMenuItem.Click -= this.Group_CheckHaveIBeenPwnedSites;
haveIBeenPwnedGroupUsernameMenuItem.Click -= this.Group_CheckHaveIBeenPwnedUsernames;
haveIBeenPwnedGroupPasswordMenuItem.Click -= this.Group_CheckHaveIBeenPwnedPasswords;
checkAllGroupMenuItem.Click -= this.Group_CheckAll;
haveIBeenPwnedGroupMenuItem.DropDown.Items.Remove(haveIBeenPwnedGroupServiceMenuItem);
haveIBeenPwnedGroupMenuItem.DropDown.Items.Remove(haveIBeenPwnedGroupUsernameMenuItem);
haveIBeenPwnedGroupMenuItem.DropDown.Items.Remove(haveIBeenPwnedGroupPasswordMenuItem);
haveIBeenPwnedGroupMenuItem.DropDown.Items.Remove(checkAllGroupMenuItem);
groupContextMenu.Remove(haveIBeenPwnedGroupMenuItem);
groupContextMenu.Remove(toolStripSeperatorGroup);

var entryContextMenu = pluginHost.MainWindow.EntryContextMenu.Items;
haveIBeenPwnedEntryServiceMenuItem.Click -= this.Entries_CheckHaveIBeenPwnedSites;
haveIBeenPwnedEntryUsernameMenuItem.Click -= this.Entries_CheckHaveIBeenPwnedUsernames;
haveIBeenPwnedEntryPasswordMenuItem.Click -= this.Entries_CheckHaveIBeenPwnedPasswords;
checkAllEntryMenuItem.Click -= this.Entries_CheckAll;
haveIBeenPwnedEntryMenuItem.DropDown.Items.Remove(haveIBeenPwnedEntryServiceMenuItem);
haveIBeenPwnedEntryMenuItem.DropDown.Items.Remove(haveIBeenPwnedEntryUsernameMenuItem);
haveIBeenPwnedEntryMenuItem.DropDown.Items.Remove(haveIBeenPwnedEntryPasswordMenuItem);
haveIBeenPwnedEntryMenuItem.DropDown.Items.Remove(checkAllEntryMenuItem);
entryContextMenu.Remove(haveIBeenPwnedEntryMenuItem);
entryContextMenu.Remove(toolStripSeperatorEntry);
}
Expand Down Expand Up @@ -274,6 +302,12 @@ private async void Database_CheckHaveIBeenPwnedPasswords(object sender, EventArg
await CheckBreach(CheckTypeEnum.Password, pluginHost.Database.RootGroup);
}

private async void Database_CheckAll(object sender, EventArgs e)
{
if (!AssertDatabaseOpen()) return;
await CheckBreach(CheckTypeEnum.CheckAll, pluginHost.Database.RootGroup);
}

private async void Group_CheckHaveIBeenPwnedSites(object sender, EventArgs e)
{
if (!AssertDatabaseOpen()) return;
Expand All @@ -292,6 +326,12 @@ private async void Group_CheckHaveIBeenPwnedPasswords(object sender, EventArgs e
await CheckBreach(CheckTypeEnum.Password, pluginHost.MainWindow.GetSelectedGroup());
}

private async void Group_CheckAll(object sender, EventArgs e)
{
if (!AssertDatabaseOpen()) return;
await CheckBreach(CheckTypeEnum.CheckAll, pluginHost.MainWindow.GetSelectedGroup());
}

private async void Entries_CheckHaveIBeenPwnedSites(object sender, EventArgs e)
{
if (!AssertDatabaseOpen()) return;
Expand All @@ -310,6 +350,12 @@ private async void Entries_CheckHaveIBeenPwnedPasswords(object sender, EventArgs
await CheckBreach(CheckTypeEnum.Password, pluginHost.MainWindow.GetSelectedEntriesAsGroup());
}

private async void Entries_CheckAll(object sender, EventArgs e)
{
if (!AssertDatabaseOpen()) return;
await CheckBreach(CheckTypeEnum.CheckAll, pluginHost.MainWindow.GetSelectedEntriesAsGroup());
}

private async Task CheckBreach(CheckTypeEnum breachType, PwGroup group)
{
var dialog = new CheckerPrompt(breachType, breachType != CheckTypeEnum.Password);
Expand Down
9 changes: 9 additions & 0 deletions HaveIBeenPwned/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions HaveIBeenPwned/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,9 @@
bVKJ7awAAAAASUVORK5CYII=
</value>
</data>
<data name="MenuItemCheckAllTitle" xml:space="preserve">
<value>Check all breach types</value>
</data>
<data name="MenuItemPasswordTitle" xml:space="preserve">
<value>Check for breaches based on password</value>
</data>
Expand Down
Loading

0 comments on commit 0c1ba7a

Please sign in to comment.