aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
diff options
context:
space:
mode:
authorPhallacy <Dragoonmac@gmail.com>2019-02-12 02:16:03 -0800
committerPhallacy <Dragoonmac@gmail.com>2019-02-12 02:16:03 -0800
commit05bbf71b6d97614888efe103f763753e4487cc2c (patch)
treea43ea503958842d1852c19e871d995cf9a747dc1 /Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
parent8bf88f4cb2ddb140baffd8e4542d8f528b482a67 (diff)
sha256 with salt auth and sha1 interop
Diffstat (limited to 'Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs')
-rw-r--r--Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs167
1 files changed, 137 insertions, 30 deletions
diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
index 4013ac0c8..92346c65a 100644
--- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
+++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Authentication;
@@ -19,31 +20,110 @@ namespace Emby.Server.Implementations.Library
public bool IsEnabled => true;
+
+ //This is dumb and an artifact of the backwards way auth providers were designed.
+ //This version of authenticate was never meant to be called, but needs to be here for interface compat
+ //Only the providers that don't provide local user support use this
public Task<ProviderAuthenticationResult> Authenticate(string username, string password)
{
throw new NotImplementedException();
}
- public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
- {
- if (resolvedUser == null)
- {
- throw new Exception("Invalid username or password");
- }
-
- var success = string.Equals(GetPasswordHash(resolvedUser), GetHashedString(resolvedUser, password), StringComparison.OrdinalIgnoreCase);
- if (!success)
- {
- throw new Exception("Invalid username or password");
- }
+ //This is the verson that we need to use for local users. Because reasons.
+ public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
+ {
+ ConvertPasswordFormat(resolvedUser);
+ byte[] passwordbytes = Encoding.UTF8.GetBytes(password);
+ bool success = false;
+ if (resolvedUser == null)
+ {
+ success = false;
+ throw new Exception("Invalid username or password");
+ }
+ if (!resolvedUser.Password.Contains("$"))
+ {
+ ConvertPasswordFormat(resolvedUser);
+ }
+ PasswordHash ReadyHash = new PasswordHash(resolvedUser.Password);
+ byte[] CalculatedHash;
+ string CalculatedHashString;
+ if (_cryptographyProvider.GetSupportedHashMethods().Any(i => i == ReadyHash.Id))
+ {
+ if (String.IsNullOrEmpty(ReadyHash.Salt))
+ {
+ CalculatedHash = _cryptographyProvider.ComputeHash(ReadyHash.Id, passwordbytes);
+ CalculatedHashString = BitConverter.ToString(CalculatedHash).Replace("-", string.Empty);
+ }
+ else
+ {
+ CalculatedHash = _cryptographyProvider.ComputeHash(ReadyHash.Id, passwordbytes, ReadyHash.SaltBytes);
+ CalculatedHashString = BitConverter.ToString(CalculatedHash).Replace("-", string.Empty);
+ }
+ if (CalculatedHashString == ReadyHash.Hash)
+ {
+ success = true;
+ //throw new Exception("Invalid username or password");
+ }
+ }
+ else
+ {
+ success = false;
+ throw new Exception(String.Format("Requested crypto method not available in provider: {0}", ReadyHash.Id));
+ }
+
+ //var success = string.Equals(GetPasswordHash(resolvedUser), GetHashedString(resolvedUser, password), StringComparison.OrdinalIgnoreCase);
+
+ if (!success)
+ {
+ throw new Exception("Invalid username or password");
+ }
+
+ return Task.FromResult(new ProviderAuthenticationResult
+ {
+ Username = username
+ });
+ }
- return Task.FromResult(new ProviderAuthenticationResult
- {
- Username = username
- });
+ //This allows us to move passwords forward to the newformat without breaking. They are still insecure, unsalted, and dumb before a password change
+ //but at least they are in the new format.
+ private void ConvertPasswordFormat(User user)
+ {
+ if (!string.IsNullOrEmpty(user.Password))
+ {
+ 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);
+ }
+ }
}
+ // OLD VERSION //public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
+ // OLD VERSION //{
+ // OLD VERSION // if (resolvedUser == null)
+ // OLD VERSION // {
+ // OLD VERSION // throw new Exception("Invalid username or password");
+ // OLD VERSION // }
+ // OLD VERSION //
+ // OLD VERSION // var success = string.Equals(GetPasswordHash(resolvedUser), GetHashedString(resolvedUser, password), StringComparison.OrdinalIgnoreCase);
+ // OLD VERSION //
+ // OLD VERSION // if (!success)
+ // OLD VERSION // {
+ // OLD VERSION // throw new Exception("Invalid username or password");
+ // OLD VERSION // }
+ // OLD VERSION //
+ // OLD VERSION // return Task.FromResult(new ProviderAuthenticationResult
+ // OLD VERSION // {
+ // OLD VERSION // Username = username
+ // OLD VERSION // });
+ // OLD VERSION //}
+
public Task<bool> HasPassword(User user)
{
var hasConfiguredPassword = !IsPasswordEmpty(user, GetPasswordHash(user));
@@ -57,19 +137,26 @@ namespace Emby.Server.Implementations.Library
public Task ChangePassword(User user, string newPassword)
{
- string newPasswordHash = null;
-
- if (newPassword != null)
+ //string newPasswordHash = null;
+ ConvertPasswordFormat(user);
+ PasswordHash passwordHash = new PasswordHash(user.Password);
+ if(passwordHash.Id == "SHA1" && string.IsNullOrEmpty(passwordHash.Salt))
{
- newPasswordHash = GetHashedString(user, newPassword);
+ passwordHash.SaltBytes = _cryptographyProvider.GenerateSalt();
+ passwordHash.Salt = BitConverter.ToString(passwordHash.SaltBytes).Replace("-","");
+ passwordHash.Id = _cryptographyProvider.DefaultHashMethod;
+ passwordHash.Hash = GetHashedStringChangeAuth(newPassword, passwordHash);
+ }else if (newPassword != null)
+ {
+ passwordHash.Hash = GetHashedString(user, newPassword);
}
- if (string.IsNullOrWhiteSpace(newPasswordHash))
+ if (string.IsNullOrWhiteSpace(passwordHash.Hash))
{
- throw new ArgumentNullException(nameof(newPasswordHash));
+ throw new ArgumentNullException(nameof(passwordHash.Hash));
}
- user.Password = newPasswordHash;
+ user.Password = passwordHash.ToString();
return Task.CompletedTask;
}
@@ -86,19 +173,39 @@ namespace Emby.Server.Implementations.Library
return GetHashedString(user, string.Empty);
}
+ public string GetHashedStringChangeAuth(string NewPassword, PasswordHash passwordHash)
+ {
+ return BitConverter.ToString(_cryptographyProvider.ComputeHash(passwordHash.Id, Encoding.UTF8.GetBytes(NewPassword), passwordHash.SaltBytes)).Replace("-", string.Empty);
+ }
+
/// <summary>
/// Gets the hashed string.
/// </summary>
- public string GetHashedString(User user, string str)
- {
- var salt = user.Salt;
- if (salt != null)
+ public string GetHashedString(User user, string str)
+ {
+ //This is legacy. Deprecated in the auth method.
+ //return BitConverter.ToString(_cryptoProvider2.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
+ PasswordHash passwordHash;
+ if (String.IsNullOrEmpty(user.Password))
+ {
+ passwordHash = new PasswordHash(_cryptographyProvider);
+ }
+ else
{
- // return BCrypt.HashPassword(str, salt);
+ ConvertPasswordFormat(user);
+ passwordHash = new PasswordHash(user.Password);
+ }
+ if (passwordHash.SaltBytes != null)
+ {
+ return BitConverter.ToString(_cryptographyProvider.ComputeHash(passwordHash.Id, Encoding.UTF8.GetBytes(str), passwordHash.SaltBytes)).Replace("-",string.Empty);
+ }
+ else
+ {
+ return BitConverter.ToString(_cryptographyProvider.ComputeHash(passwordHash.Id, Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
+ //throw new Exception("User does not have a hash, this should not be possible");
}
- // legacy
- return BitConverter.ToString(_cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
+
}
}
}