diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index dc528c280..2f2fd9592 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -73,8 +73,9 @@ namespace Emby.Server.Implementations.Cryptography } private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations) - { - using (var r = new Rfc2898DeriveBytes(bytes, salt, iterations, new HashAlgorithmName(method))) + { + //downgrading for now as we need this library to be dotnetstandard compliant + using (var r = new Rfc2898DeriveBytes(bytes, salt, iterations)) { return r.GetBytes(32); } diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs index 1b6deae7d..3df91f71c 100644 --- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs @@ -54,7 +54,8 @@ namespace Emby.Server.Implementations.Data if (!localUsersTableExists && TableExists(connection, "Users")) { TryMigrateToLocalUsersTable(connection); - } + } + RemoveEmptyPasswordHashes(); } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 86b2efe54..8356a9501 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -34,7 +34,7 @@ - netcoreapp2.1 + netstandard2.0 false diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs index 80026d97c..2ac3ef424 100644 --- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs +++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.Library string CalculatedHashString; if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id)) { - if (String.IsNullOrEmpty(readyHash.Salt)) + if (string.IsNullOrEmpty(readyHash.Salt)) { CalculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes); CalculatedHashString = BitConverter.ToString(CalculatedHash).Replace("-", string.Empty); @@ -65,7 +65,8 @@ namespace Emby.Server.Implementations.Library { CalculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes, readyHash.SaltBytes); CalculatedHashString = BitConverter.ToString(CalculatedHash).Replace("-", string.Empty); - } + } + if (CalculatedHashString == readyHash.Hash) { success = true; @@ -95,18 +96,20 @@ namespace Emby.Server.Implementations.Library private void ConvertPasswordFormat(User user) { if (!string.IsNullOrEmpty(user.Password)) + { + return; + } + + if (!user.Password.Contains("$")) { - if (!user.Password.Contains("$")) - { - string hash = user.Password; - user.Password = String.Format("$SHA1${0}", hash); - } - - if (user.EasyPassword != null && !user.EasyPassword.Contains("$")) - { - string hash = user.EasyPassword; - user.EasyPassword = string.Format("$SHA1${0}", hash); - } + string hash = user.Password; + user.Password = String.Format("$SHA1${0}", hash); + } + + if (user.EasyPassword != null && !user.EasyPassword.Contains("$")) + { + string hash = user.EasyPassword; + user.EasyPassword = string.Format("$SHA1${0}", hash); } } @@ -122,6 +125,7 @@ namespace Emby.Server.Implementations.Library { return string.IsNullOrEmpty(password); } + return false; } @@ -188,7 +192,8 @@ namespace Emby.Server.Implementations.Library { ConvertPasswordFormat(user); passwordHash = new PasswordHash(user.Password); - } + } + if (passwordHash.SaltBytes != null) { //the password is modern format with PBKDF and we should take advantage of that diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 3daed0c08..b74006233 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -221,9 +221,8 @@ namespace Emby.Server.Implementations.Library { //This is some regex that matches only on unicode "word" characters, as well as -, _ and @ //In theory this will cut out most if not all 'control' characters which should help minimize any weirdness - string UserNameRegex = "^[\\w-'._@]*$"; // Usernames can contain letters (a-z + whatever else unicode is cool with), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.) - return Regex.IsMatch(username, UserNameRegex); + return Regex.IsMatch(username, "^[\\w-'._@]*$"); } private static bool IsValidUsernameCharacter(char i) diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs index 3a817543b..49bd510e9 100644 --- a/MediaBrowser.Model/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs @@ -10,26 +10,33 @@ namespace MediaBrowser.Model.Cryptography //https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md //$[$=(,=)*][$[$]] - public string Id; - public Dictionary Parameters = new Dictionary(); - public string Salt; - public byte[] SaltBytes; - public string Hash; - public byte[] HashBytes; + private string id; + private Dictionary parameters = new Dictionary(); + private string salt; + private byte[] saltBytes; + private string hash; + private byte[] hashBytes; + public string Id { get => id; set => id = value; } + public Dictionary Parameters { get => parameters; set => parameters = value; } + public string Salt { get => salt; set => salt = value; } + public byte[] SaltBytes { get => saltBytes; set => saltBytes = value; } + public string Hash { get => hash; set => hash = value; } + public byte[] HashBytes { get => hashBytes; set => hashBytes = value; } + public PasswordHash(string storageString) { string[] splitted = storageString.Split('$'); - Id = splitted[1]; + id = splitted[1]; if (splitted[2].Contains("=")) { foreach (string paramset in (splitted[2].Split(','))) { - if (!String.IsNullOrEmpty(paramset)) + if (!string.IsNullOrEmpty(paramset)) { string[] fields = paramset.Split('='); if (fields.Length == 2) { - Parameters.Add(fields[0], fields[1]); + parameters.Add(fields[0], fields[1]); } else { @@ -39,32 +46,32 @@ namespace MediaBrowser.Model.Cryptography } if (splitted.Length == 5) { - Salt = splitted[3]; - SaltBytes = ConvertFromByteString(Salt); - Hash = splitted[4]; - HashBytes = ConvertFromByteString(Hash); + salt = splitted[3]; + saltBytes = ConvertFromByteString(salt); + hash = splitted[4]; + hashBytes = ConvertFromByteString(hash); } else { - Salt = string.Empty; - Hash = splitted[3]; - HashBytes = ConvertFromByteString(Hash); + salt = string.Empty; + hash = splitted[3]; + hashBytes = ConvertFromByteString(hash); } } else { if (splitted.Length == 4) { - Salt = splitted[2]; - SaltBytes = ConvertFromByteString(Salt); - Hash = splitted[3]; - HashBytes = ConvertFromByteString(Hash); + salt = splitted[2]; + saltBytes = ConvertFromByteString(salt); + hash = splitted[3]; + hashBytes = ConvertFromByteString(hash); } else { - Salt = string.Empty; - Hash = splitted[2]; - HashBytes = ConvertFromByteString(Hash); + salt = string.Empty; + hash = splitted[2]; + hashBytes = ConvertFromByteString(hash); } } @@ -73,9 +80,9 @@ namespace MediaBrowser.Model.Cryptography public PasswordHash(ICryptoProvider cryptoProvider) { - Id = cryptoProvider.DefaultHashMethod; - SaltBytes = cryptoProvider.GenerateSalt(); - Salt = ConvertToByteString(SaltBytes); + id = cryptoProvider.DefaultHashMethod; + saltBytes = cryptoProvider.GenerateSalt(); + salt = ConvertToByteString(SaltBytes); } public static byte[] ConvertFromByteString(string byteString) @@ -95,31 +102,35 @@ namespace MediaBrowser.Model.Cryptography private string SerializeParameters() { - string ReturnString = String.Empty; - foreach (var KVP in Parameters) + string ReturnString = string.Empty; + foreach (var KVP in parameters) { - ReturnString += String.Format(",{0}={1}", KVP.Key, KVP.Value); - } + ReturnString += $",{KVP.Key}={KVP.Value}"; + } + if ((!string.IsNullOrEmpty(ReturnString)) && ReturnString[0] == ',') { ReturnString = ReturnString.Remove(0, 1); - } + } + return ReturnString; } public override string ToString() { - string outString = "$" +Id; + string outString = "$" +id; string paramstring = SerializeParameters(); if (!string.IsNullOrEmpty(paramstring)) { outString += $"${paramstring}"; } - if (!string.IsNullOrEmpty(Salt)) + + if (!string.IsNullOrEmpty(salt)) { - outString += $"${Salt}"; + outString += $"${salt}"; } - outString += $"${Hash}"; + + outString += $"${hash}"; return outString; } }