Merge pull request #2492 from Polpetta/fix-api-private-data-leak

Fix emby/user/public API leaking sensitive data
This commit is contained in:
Bond-009 2020-05-07 14:52:10 +02:00 committed by GitHub
commit 62da4d0e5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 11 deletions

View File

@ -608,6 +608,31 @@ namespace Emby.Server.Implementations.Library
return dto; return dto;
} }
public PublicUserDto GetPublicUserDto(User user, string remoteEndPoint = null)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
IAuthenticationProvider authenticationProvider = GetAuthenticationProvider(user);
bool hasConfiguredPassword = authenticationProvider.HasPassword(user);
bool hasConfiguredEasyPassword = !string.IsNullOrEmpty(authenticationProvider.GetEasyPasswordHash(user));
bool hasPassword = user.Configuration.EnableLocalPassword &&
!string.IsNullOrEmpty(remoteEndPoint) &&
_networkManager.IsInLocalNetwork(remoteEndPoint) ? hasConfiguredEasyPassword : hasConfiguredPassword;
PublicUserDto dto = new PublicUserDto
{
Name = user.Name,
HasPassword = hasPassword,
HasConfiguredPassword = hasConfiguredPassword,
};
return dto;
}
public UserDto GetOfflineUserDto(User user) public UserDto GetOfflineUserDto(User user)
{ {
var dto = GetUserDto(user); var dto = GetUserDto(user);

View File

@ -35,7 +35,7 @@ namespace MediaBrowser.Api
} }
[Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")] [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
public class GetPublicUsers : IReturn<UserDto[]> public class GetPublicUsers : IReturn<PublicUserDto[]>
{ {
} }
@ -266,22 +266,38 @@ namespace MediaBrowser.Api
_authContext = authContext; _authContext = authContext;
} }
/// <summary>
/// Gets the public available Users information
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Get(GetPublicUsers request) public object Get(GetPublicUsers request)
{ {
// If the startup wizard hasn't been completed then just return all users var result = _userManager
if (!ServerConfigurationManager.Configuration.IsStartupWizardCompleted) .Users
.Where(item => !item.Policy.IsDisabled);
if (ServerConfigurationManager.Configuration.IsStartupWizardCompleted)
{ {
return Get(new GetUsers var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
result = result.Where(item => !item.Policy.IsHidden);
if (!string.IsNullOrWhiteSpace(deviceId))
{ {
IsDisabled = false result = result.Where(i => _deviceManager.CanAccessDevice(i, deviceId));
});
} }
return Get(new GetUsers if (!_networkManager.IsInLocalNetwork(Request.RemoteIp))
{ {
IsHidden = false, result = result.Where(i => i.Policy.EnableRemoteAccess);
IsDisabled = false }
}, true, true); }
return ToOptimizedResult(result
.OrderBy(u => u.Name)
.Select(i => _userManager.GetPublicUserDto(i, Request.RemoteIp))
.ToArray()
);
} }
/// <summary> /// <summary>

View File

@ -143,6 +143,14 @@ namespace MediaBrowser.Controller.Library
/// <returns>UserDto.</returns> /// <returns>UserDto.</returns>
UserDto GetUserDto(User user, string remoteEndPoint = null); UserDto GetUserDto(User user, string remoteEndPoint = null);
/// <summary>
/// Gets the user public dto.
/// </summary>
/// <param name="user">Ther user.</param>\
/// <param name="remoteEndPoint">The remote end point.</param>
/// <returns>A public UserDto, aka a UserDto stripped of personal data.</returns>
PublicUserDto GetPublicUserDto(User user, string remoteEndPoint = null);
/// <summary> /// <summary>
/// Authenticates the user. /// Authenticates the user.
/// </summary> /// </summary>

View File

@ -0,0 +1,48 @@
using System;
namespace MediaBrowser.Model.Dto
{
/// <summary>
/// Class PublicUserDto. Its goal is to show only public information about a user
/// </summary>
public class PublicUserDto : IItemDto
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance has password.
/// </summary>
/// <value><c>true</c> if this instance has password; otherwise, <c>false</c>.</value>
public bool HasPassword { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance has configured password.
/// Note that in this case this method should not be here, but it is necessary when changing password at the
/// first login.
/// </summary>
/// <value><c>true</c> if this instance has configured password; otherwise, <c>false</c>.</value>
public bool HasConfiguredPassword { get; set; }
/// <summary>
/// Gets or sets the primary image aspect ratio.
/// </summary>
/// <value>The primary image aspect ratio.</value>
public double? PrimaryImageAspectRatio { get; set; }
/// <inheritdoc />
public override string ToString()
{
return Name ?? base.ToString();
}
}
}