diff --git a/src/App/Services/CipherService.cs b/src/App/Services/CipherService.cs index c71fd9da2..e1ee71ab3 100644 --- a/src/App/Services/CipherService.cs +++ b/src/App/Services/CipherService.cs @@ -7,6 +7,8 @@ using Bit.App.Models; using Bit.App.Models.Api; using Bit.App.Models.Data; using System.Net.Http; +using Bit.App.Utilities; +using System.Text.RegularExpressions; namespace Bit.App.Services { @@ -158,80 +160,65 @@ namespace Bit.App.Services continue; } - if(cipher.Type != Enums.CipherType.Login || cipher.Login?.Uri == null) + if(cipher.Login?.Uris == null || !cipher.Login.Uris.Any()) { continue; } - var loginUriString = cipher.Login.Uri.Decrypt(cipher.OrganizationId); - if(string.IsNullOrWhiteSpace(loginUriString)) + foreach(var u in cipher.Login.Uris) { - continue; - } - - if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0) - { - matchingLogins.Add(cipher); - continue; - } - else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0) - { - matchingFuzzyLogins.Add(cipher); - continue; - } - else if(!mobileApp) - { - var info = InfoFromMobileAppUri(loginUriString); - if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0) + var loginUriString = u.Uri?.Decrypt(cipher.OrganizationId); + if(string.IsNullOrWhiteSpace(loginUriString)) { - matchingFuzzyLogins.Add(cipher); - continue; + break; } - } - string loginDomainName = null; - if(Uri.TryCreate(loginUriString, UriKind.Absolute, out Uri loginUri) - && DomainName.TryParseBaseDomain(loginUri.Host, out loginDomainName)) - { - loginDomainName = loginDomainName.ToLowerInvariant(); - - if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0) + var added = false; + switch(u.Match) { - matchingLogins.Add(cipher); - continue; - } - else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0) - { - matchingFuzzyLogins.Add(cipher); - continue; - } - } - - if(mobileApp && mobileAppSearchTerms != null && mobileAppSearchTerms.Length > 0) - { - var addedFromSearchTerm = false; - var loginNameString = cipher.Name == null ? null : - cipher.Name.Decrypt(cipher.OrganizationId)?.ToLowerInvariant(); - foreach(var term in mobileAppSearchTerms) - { - addedFromSearchTerm = (loginDomainName != null && loginDomainName.Contains(term)) || - (loginNameString != null && loginNameString.Contains(term)); - if(!addedFromSearchTerm) - { - addedFromSearchTerm = (loginDomainName != null && term.Contains(loginDomainName.Split('.')[0])) - || (loginNameString != null && term.Contains(loginNameString)); - } - - if(addedFromSearchTerm) - { - matchingFuzzyLogins.Add(cipher); + case null: + case Enums.UriMatchType.Domain: + added = CheckDefaultUriMatch(cipher, loginUriString, matchingLogins, matchingFuzzyLogins, + matchingDomainsArray, matchingFuzzyDomainsArray, mobileApp, mobileAppSearchTerms); + break; + case Enums.UriMatchType.Host: + var urlHost = Helpers.GetUrlHost(uriString); + added = urlHost != null && urlHost == Helpers.GetUrlHost(loginUriString); + if(added) + { + matchingLogins.Add(cipher); + } + break; + case Enums.UriMatchType.Exact: + added = uriString == loginUriString; + if(added) + { + matchingLogins.Add(cipher); + } + break; + case Enums.UriMatchType.StartsWith: + added = uriString.StartsWith(loginUriString); + if(added) + { + matchingLogins.Add(cipher); + } + break; + case Enums.UriMatchType.RegularExpression: + var regex = new Regex(loginUriString, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1)); + added = regex.IsMatch(uriString); + if(added) + { + matchingLogins.Add(cipher); + } + break; + case Enums.UriMatchType.Never: + default: break; - } } - if(addedFromSearchTerm) + if(added) { - continue; + break; } } } @@ -442,5 +429,73 @@ namespace Bit.App.Services { return uriString.StartsWith(Constants.iOSAppProtocol); } + + private bool CheckDefaultUriMatch(Cipher cipher, string loginUriString, List matchingLogins, + List matchingFuzzyLogins, string[] matchingDomainsArray, string[] matchingFuzzyDomainsArray, + bool mobileApp, string[] mobileAppSearchTerms) + { + if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0) + { + matchingLogins.Add(cipher); + return true; + } + else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0) + { + matchingFuzzyLogins.Add(cipher); + return true; + } + else if(!mobileApp) + { + var info = InfoFromMobileAppUri(loginUriString); + if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0) + { + matchingFuzzyLogins.Add(cipher); + return true; + } + } + + string loginDomainName = null; + if(Uri.TryCreate(loginUriString, UriKind.Absolute, out Uri loginUri) + && DomainName.TryParseBaseDomain(loginUri.Host, out loginDomainName)) + { + loginDomainName = loginDomainName.ToLowerInvariant(); + + if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0) + { + matchingLogins.Add(cipher); + return true; + } + else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0) + { + matchingFuzzyLogins.Add(cipher); + return true; + } + } + + if(mobileApp && mobileAppSearchTerms != null && mobileAppSearchTerms.Length > 0) + { + var addedFromSearchTerm = false; + var loginNameString = cipher.Name == null ? null : + cipher.Name.Decrypt(cipher.OrganizationId)?.ToLowerInvariant(); + foreach(var term in mobileAppSearchTerms) + { + addedFromSearchTerm = (loginDomainName != null && loginDomainName.Contains(term)) || + (loginNameString != null && loginNameString.Contains(term)); + if(!addedFromSearchTerm) + { + addedFromSearchTerm = (loginDomainName != null && term.Contains(loginDomainName.Split('.')[0])) + || (loginNameString != null && term.Contains(loginNameString)); + } + + if(addedFromSearchTerm) + { + matchingFuzzyLogins.Add(cipher); + return true; + } + } + } + + return false; + } } } diff --git a/src/App/Utilities/Helpers.cs b/src/App/Utilities/Helpers.cs index 985735335..0cb3d4d37 100644 --- a/src/App/Utilities/Helpers.cs +++ b/src/App/Utilities/Helpers.cs @@ -467,5 +467,37 @@ namespace Bit.App.Utilities } } } + + public static string GetUrlHost(string url) + { + if(string.IsNullOrWhiteSpace(url)) + { + return null; + } + + url = url.Trim(); + if(url == string.Empty) + { + return null; + } + + if(!url.Contains("://")) + { + url = $"http://{url}"; + } + + if(!Uri.TryCreate(url, UriKind.Absolute, out Uri u)) + { + return null; + } + + var host = u.Host; + if(!u.IsDefaultPort) + { + host = $"{host}:{u.Port}"; + } + + return host; + } } }