fixes #1074
This commit is contained in:
parent
1f12ab6658
commit
bca1d65bdc
|
@ -180,11 +180,6 @@ namespace Emby.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
public Task<User> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint)
|
||||
{
|
||||
return AuthenticateUser(username, passwordSha1, null, remoteEndPoint);
|
||||
}
|
||||
|
||||
public bool IsValidUsername(string username)
|
||||
{
|
||||
// Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
|
||||
|
@ -223,7 +218,7 @@ namespace Emby.Server.Implementations.Library
|
|||
return builder.ToString();
|
||||
}
|
||||
|
||||
public async Task<User> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint)
|
||||
public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
{
|
||||
|
@ -237,23 +232,23 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
if (user != null)
|
||||
{
|
||||
if (password != null)
|
||||
{
|
||||
hashedPassword = GetHashedString(user, password);
|
||||
}
|
||||
|
||||
// Authenticate using local credentials if not a guest
|
||||
if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
|
||||
{
|
||||
success = string.Equals(GetPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
|
||||
{
|
||||
success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
success = AuthenticateLocalUser(user, password, hashedPassword, remoteEndPoint);
|
||||
}
|
||||
|
||||
// Maybe user accidently entered connect credentials. let's be flexible
|
||||
if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5) && !string.IsNullOrWhiteSpace(user.ConnectUserName))
|
||||
if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(user.ConnectUserName))
|
||||
{
|
||||
try
|
||||
{
|
||||
await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
|
||||
await _connectFactory().Authenticate(user.ConnectUserName, password, passwordMd5).ConfigureAwait(false);
|
||||
success = true;
|
||||
}
|
||||
catch
|
||||
|
@ -268,7 +263,7 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
try
|
||||
{
|
||||
var connectAuthResult = await _connectFactory().Authenticate(username, passwordMd5).ConfigureAwait(false);
|
||||
var connectAuthResult = await _connectFactory().Authenticate(username, password, passwordMd5).ConfigureAwait(false);
|
||||
|
||||
user = Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectAuthResult.User.Id, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
|
@ -307,6 +302,36 @@ namespace Emby.Server.Implementations.Library
|
|||
return success ? user : null;
|
||||
}
|
||||
|
||||
private bool AuthenticateLocalUser(User user, string password, string hashedPassword, string remoteEndPoint)
|
||||
{
|
||||
bool success;
|
||||
|
||||
if (password == null)
|
||||
{
|
||||
// legacy
|
||||
success = string.Equals(GetPasswordHash(user), hashedPassword.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = string.Equals(GetPasswordHash(user), GetHashedString(user, password), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
|
||||
{
|
||||
if (password == null)
|
||||
{
|
||||
// legacy
|
||||
success = string.Equals(GetLocalPasswordHash(user), hashedPassword.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = string.Equals(GetLocalPasswordHash(user), GetHashedString(user, password), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void UpdateInvalidLoginAttemptCount(User user, int newValue)
|
||||
{
|
||||
if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0)
|
||||
|
@ -342,29 +367,39 @@ namespace Emby.Server.Implementations.Library
|
|||
private string GetPasswordHash(User user)
|
||||
{
|
||||
return string.IsNullOrEmpty(user.Password)
|
||||
? GetSha1String(string.Empty)
|
||||
? GetEmptyHashedString(user)
|
||||
: user.Password;
|
||||
}
|
||||
|
||||
private string GetLocalPasswordHash(User user)
|
||||
{
|
||||
return string.IsNullOrEmpty(user.EasyPassword)
|
||||
? GetSha1String(string.Empty)
|
||||
? GetEmptyHashedString(user)
|
||||
: user.EasyPassword;
|
||||
}
|
||||
|
||||
private bool IsPasswordEmpty(string passwordHash)
|
||||
private bool IsPasswordEmpty(User user, string passwordHash)
|
||||
{
|
||||
return string.Equals(passwordHash, GetSha1String(string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
return string.Equals(passwordHash, GetEmptyHashedString(user), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private string GetEmptyHashedString(User user)
|
||||
{
|
||||
return GetHashedString(user, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sha1 string.
|
||||
/// Gets the hashed string.
|
||||
/// </summary>
|
||||
/// <param name="str">The STR.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetSha1String(string str)
|
||||
private string GetHashedString(User user, string str)
|
||||
{
|
||||
var salt = user.Salt;
|
||||
if (salt != null)
|
||||
{
|
||||
// return BCrypt.HashPassword(str, salt);
|
||||
}
|
||||
|
||||
// legacy
|
||||
return BitConverter.ToString(_cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
|
||||
}
|
||||
|
||||
|
@ -407,8 +442,8 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
var passwordHash = GetPasswordHash(user);
|
||||
|
||||
var hasConfiguredPassword = !IsPasswordEmpty(passwordHash);
|
||||
var hasConfiguredEasyPassword = !IsPasswordEmpty(GetLocalPasswordHash(user));
|
||||
var hasConfiguredPassword = !IsPasswordEmpty(user, passwordHash);
|
||||
var hasConfiguredEasyPassword = !IsPasswordEmpty(user, GetLocalPasswordHash(user));
|
||||
|
||||
var hasPassword = user.Configuration.EnableLocalPassword && !string.IsNullOrEmpty(remoteEndPoint) && _networkManager.IsInLocalNetwork(remoteEndPoint) ?
|
||||
hasConfiguredEasyPassword :
|
||||
|
@ -460,14 +495,6 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
var dto = GetUserDto(user);
|
||||
|
||||
var offlinePasswordHash = GetLocalPasswordHash(user);
|
||||
dto.HasPassword = !IsPasswordEmpty(offlinePasswordHash);
|
||||
|
||||
dto.OfflinePasswordSalt = Guid.NewGuid().ToString("N");
|
||||
|
||||
// Hash the pin with the device Id to create a unique result for this device
|
||||
dto.OfflinePassword = GetSha1String((offlinePasswordHash + dto.OfflinePasswordSalt).ToLower());
|
||||
|
||||
dto.ServerName = _appHost.FriendlyName;
|
||||
|
||||
return dto;
|
||||
|
@ -682,23 +709,29 @@ namespace Emby.Server.Implementations.Library
|
|||
/// <returns>Task.</returns>
|
||||
public void ResetPassword(User user)
|
||||
{
|
||||
ChangePassword(user, GetSha1String(string.Empty));
|
||||
ChangePassword(user, string.Empty, null);
|
||||
}
|
||||
|
||||
public void ResetEasyPassword(User user)
|
||||
{
|
||||
ChangeEasyPassword(user, GetSha1String(string.Empty));
|
||||
ChangeEasyPassword(user, string.Empty, null);
|
||||
}
|
||||
|
||||
public void ChangePassword(User user, string newPasswordSha1)
|
||||
public void ChangePassword(User user, string newPassword, string newPasswordHash)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(newPasswordSha1))
|
||||
|
||||
if (newPassword != null)
|
||||
{
|
||||
throw new ArgumentNullException("newPasswordSha1");
|
||||
newPasswordHash = GetHashedString(user, newPassword);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(newPasswordHash))
|
||||
{
|
||||
throw new ArgumentNullException("newPasswordHash");
|
||||
}
|
||||
|
||||
if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest)
|
||||
|
@ -706,25 +739,31 @@ namespace Emby.Server.Implementations.Library
|
|||
throw new ArgumentException("Passwords for guests cannot be changed.");
|
||||
}
|
||||
|
||||
user.Password = newPasswordSha1;
|
||||
user.Password = newPasswordHash;
|
||||
|
||||
UpdateUser(user);
|
||||
|
||||
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
|
||||
}
|
||||
|
||||
public void ChangeEasyPassword(User user, string newPasswordSha1)
|
||||
public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(newPasswordSha1))
|
||||
|
||||
if (newPassword != null)
|
||||
{
|
||||
throw new ArgumentNullException("newPasswordSha1");
|
||||
newPasswordHash = GetHashedString(user, newPassword);
|
||||
}
|
||||
|
||||
user.EasyPassword = newPasswordSha1;
|
||||
if (string.IsNullOrWhiteSpace(newPasswordHash))
|
||||
{
|
||||
throw new ArgumentNullException("newPasswordHash");
|
||||
}
|
||||
|
||||
user.EasyPassword = newPasswordHash;
|
||||
|
||||
UpdateUser(user);
|
||||
|
||||
|
@ -744,7 +783,8 @@ namespace Emby.Server.Implementations.Library
|
|||
Id = Guid.NewGuid(),
|
||||
DateCreated = DateTime.UtcNow,
|
||||
DateModified = DateTime.UtcNow,
|
||||
UsesIdForConfigurationPath = true
|
||||
UsesIdForConfigurationPath = true,
|
||||
//Salt = BCrypt.GenerateSalt()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,9 @@ namespace MediaBrowser.Api
|
|||
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
|
||||
public string Pw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
|
@ -125,6 +128,9 @@ namespace MediaBrowser.Api
|
|||
[ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
|
||||
public string Pw { get; set; }
|
||||
|
||||
[ApiMember(Name = "PasswordMd5", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
|
||||
public string PasswordMd5 { get; set; }
|
||||
}
|
||||
|
@ -148,12 +154,16 @@ namespace MediaBrowser.Api
|
|||
/// <value>The password.</value>
|
||||
public string CurrentPassword { get; set; }
|
||||
|
||||
public string CurrentPw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the new password.
|
||||
/// </summary>
|
||||
/// <value>The new password.</value>
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
public string NewPw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [reset password].
|
||||
/// </summary>
|
||||
|
@ -180,6 +190,8 @@ namespace MediaBrowser.Api
|
|||
/// <value>The new password.</value>
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
public string NewPw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [reset password].
|
||||
/// </summary>
|
||||
|
@ -408,7 +420,8 @@ namespace MediaBrowser.Api
|
|||
return Post(new AuthenticateUserByName
|
||||
{
|
||||
Username = user.Name,
|
||||
Password = request.Password
|
||||
Password = request.Password,
|
||||
Pw = request.Pw
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -422,6 +435,7 @@ namespace MediaBrowser.Api
|
|||
AppVersion = auth.Version,
|
||||
DeviceId = auth.DeviceId,
|
||||
DeviceName = auth.Device,
|
||||
Password = request.Pw,
|
||||
PasswordSha1 = request.Password,
|
||||
PasswordMd5 = request.PasswordMd5,
|
||||
RemoteEndPoint = Request.RemoteIp,
|
||||
|
@ -459,14 +473,14 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
else
|
||||
{
|
||||
var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPassword, Request.RemoteIp).ConfigureAwait(false);
|
||||
var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp).ConfigureAwait(false);
|
||||
|
||||
if (success == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid user or password entered.");
|
||||
}
|
||||
|
||||
_userManager.ChangePassword(user, request.NewPassword);
|
||||
_userManager.ChangePassword(user, request.NewPw, request.NewPassword);
|
||||
|
||||
var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
|
||||
|
||||
|
@ -491,7 +505,7 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
else
|
||||
{
|
||||
_userManager.ChangeEasyPassword(user, request.NewPassword);
|
||||
_userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,8 +515,6 @@ namespace MediaBrowser.Api
|
|||
/// <param name="request">The request.</param>
|
||||
public void Post(UpdateUser request)
|
||||
{
|
||||
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
|
||||
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
|
||||
var id = GetPathValue(1);
|
||||
|
||||
AssertCanUpdateUser(_authContext, _userManager, id, false);
|
||||
|
|
|
@ -58,10 +58,7 @@ namespace MediaBrowser.Controller.Connect
|
|||
/// <summary>
|
||||
/// Authenticates the specified username.
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <param name="passwordMd5">The password MD5.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task<ConnectAuthenticationResult> Authenticate(string username, string passwordMd5);
|
||||
Task<ConnectAuthenticationResult> Authenticate(string username, string password, string passwordMd5);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local user.
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <value>The password.</value>
|
||||
public string Password { get; set; }
|
||||
public string EasyPassword { get; set; }
|
||||
public string Salt { get; set; }
|
||||
|
||||
public string ConnectUserName { get; set; }
|
||||
public string ConnectUserId { get; set; }
|
||||
|
|
|
@ -58,16 +58,6 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>User.</returns>
|
||||
User GetUserByName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates a User and returns a result indicating whether or not it succeeded
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <param name="passwordSha1">The password sha1.</param>
|
||||
/// <param name="remoteEndPoint">The remote end point.</param>
|
||||
/// <returns>Task{System.Boolean}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">user</exception>
|
||||
Task<User> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint);
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes metadata for each user
|
||||
/// </summary>
|
||||
|
@ -135,18 +125,12 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <summary>
|
||||
/// Changes the password.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="newPasswordSha1">The new password sha1.</param>
|
||||
/// <returns>Task.</returns>
|
||||
void ChangePassword(User user, string newPasswordSha1);
|
||||
void ChangePassword(User user, string newPassword, string newPasswordSha1);
|
||||
|
||||
/// <summary>
|
||||
/// Changes the easy password.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="newPasswordSha1">The new password sha1.</param>
|
||||
/// <returns>Task.</returns>
|
||||
void ChangeEasyPassword(User user, string newPasswordSha1);
|
||||
void ChangeEasyPassword(User user, string newPassword, string newPasswordSha1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user dto.
|
||||
|
@ -159,12 +143,7 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <summary>
|
||||
/// Authenticates the user.
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <param name="passwordSha1">The password sha1.</param>
|
||||
/// <param name="passwordMd5">The password MD5.</param>
|
||||
/// <param name="remoteEndPoint">The remote end point.</param>
|
||||
/// <returns>Task<System.Boolean>.</returns>
|
||||
Task<User> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint);
|
||||
Task<User> AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint);
|
||||
|
||||
/// <summary>
|
||||
/// Starts the forgot password process.
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace MediaBrowser.Controller.Session
|
|||
{
|
||||
public string Username { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string PasswordSha1 { get; set; }
|
||||
public string PasswordMd5 { get; set; }
|
||||
public string App { get; set; }
|
||||
|
|
Loading…
Reference in New Issue
Block a user