mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-05 21:37:10 -04:00
Merge pull request #5602 from Ullmie02/IP-string-IP
This commit is contained in:
commit
ec0ef1530c
@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
|||||||
var authorization = _authContext.GetAuthorizationInfo(requestContext);
|
var authorization = _authContext.GetAuthorizationInfo(requestContext);
|
||||||
|
|
||||||
var user = authorization.User;
|
var user = authorization.User;
|
||||||
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp(), user);
|
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp().ToString(), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionInfo GetSession(object requestContext)
|
public SessionInfo GetSession(object requestContext)
|
||||||
|
@ -21,6 +21,7 @@ using MediaBrowser.Model.Users;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Jellyfin.Api.Controllers
|
namespace Jellyfin.Api.Controllers
|
||||||
{
|
{
|
||||||
@ -36,6 +37,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
private readonly IDeviceManager _deviceManager;
|
private readonly IDeviceManager _deviceManager;
|
||||||
private readonly IAuthorizationContext _authContext;
|
private readonly IAuthorizationContext _authContext;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="UserController"/> class.
|
/// Initializes a new instance of the <see cref="UserController"/> class.
|
||||||
@ -46,13 +48,15 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
|
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
|
||||||
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
|
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
|
||||||
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
|
||||||
public UserController(
|
public UserController(
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager,
|
||||||
IDeviceManager deviceManager,
|
IDeviceManager deviceManager,
|
||||||
IAuthorizationContext authContext,
|
IAuthorizationContext authContext,
|
||||||
IServerConfigurationManager config)
|
IServerConfigurationManager config,
|
||||||
|
ILogger<UserController> logger)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
@ -60,6 +64,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
_deviceManager = deviceManager;
|
_deviceManager = deviceManager;
|
||||||
_authContext = authContext;
|
_authContext = authContext;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -118,7 +123,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
return NotFound("User not found");
|
return NotFound("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = _userManager.GetUserDto(user, HttpContext.GetNormalizedRemoteIp());
|
var result = _userManager.GetUserDto(user, HttpContext.GetNormalizedRemoteIp().ToString());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +209,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
DeviceName = auth.Device,
|
DeviceName = auth.Device,
|
||||||
Password = request.Pw,
|
Password = request.Pw,
|
||||||
PasswordSha1 = request.Password,
|
PasswordSha1 = request.Password,
|
||||||
RemoteEndPoint = HttpContext.GetNormalizedRemoteIp(),
|
RemoteEndPoint = HttpContext.GetNormalizedRemoteIp().ToString(),
|
||||||
Username = request.Username
|
Username = request.Username
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -291,7 +296,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
user.Username,
|
user.Username,
|
||||||
request.CurrentPw,
|
request.CurrentPw,
|
||||||
request.CurrentPw,
|
request.CurrentPw,
|
||||||
HttpContext.GetNormalizedRemoteIp(),
|
HttpContext.GetNormalizedRemoteIp().ToString(),
|
||||||
false).ConfigureAwait(false);
|
false).ConfigureAwait(false);
|
||||||
|
|
||||||
if (success == null)
|
if (success == null)
|
||||||
@ -483,7 +488,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
|
await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = _userManager.GetUserDto(newUser, HttpContext.GetNormalizedRemoteIp());
|
var result = _userManager.GetUserDto(newUser, HttpContext.GetNormalizedRemoteIp().ToString());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -498,8 +503,14 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public async Task<ActionResult<ForgotPasswordResult>> ForgotPassword([FromBody, Required] ForgotPasswordDto forgotPasswordRequest)
|
public async Task<ActionResult<ForgotPasswordResult>> ForgotPassword([FromBody, Required] ForgotPasswordDto forgotPasswordRequest)
|
||||||
{
|
{
|
||||||
|
var ip = HttpContext.GetNormalizedRemoteIp();
|
||||||
var isLocal = HttpContext.IsLocal()
|
var isLocal = HttpContext.IsLocal()
|
||||||
|| _networkManager.IsInLocalNetwork(HttpContext.GetNormalizedRemoteIp());
|
|| _networkManager.IsInLocalNetwork(ip);
|
||||||
|
|
||||||
|
if (isLocal)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Password reset proccess initiated from outside the local network with IP: {IP}", ip);
|
||||||
|
}
|
||||||
|
|
||||||
var result = await _userManager.StartForgotPasswordProcess(forgotPasswordRequest.EnteredUsername, isLocal).ConfigureAwait(false);
|
var result = await _userManager.StartForgotPasswordProcess(forgotPasswordRequest.EnteredUsername, isLocal).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -581,7 +592,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
|
|
||||||
var result = users
|
var result = users
|
||||||
.OrderBy(u => u.Username)
|
.OrderBy(u => u.Username)
|
||||||
.Select(i => _userManager.GetUserDto(i, HttpContext.GetNormalizedRemoteIp()));
|
.Select(i => _userManager.GetUserDto(i, HttpContext.GetNormalizedRemoteIp().ToString()));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ namespace Jellyfin.Api.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnableAdaptiveBitrateStreaming(StreamState state, bool isLiveStream, bool enableAdaptiveBitrateStreaming, string ipAddress)
|
private bool EnableAdaptiveBitrateStreaming(StreamState state, bool isLiveStream, bool enableAdaptiveBitrateStreaming, IPAddress ipAddress)
|
||||||
{
|
{
|
||||||
// Within the local network this will likely do more harm than good.
|
// Within the local network this will likely do more harm than good.
|
||||||
if (_networkManager.IsInLocalNetwork(ipAddress))
|
if (_networkManager.IsInLocalNetwork(ipAddress))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -179,7 +180,7 @@ namespace Jellyfin.Api.Helpers
|
|||||||
bool enableTranscoding,
|
bool enableTranscoding,
|
||||||
bool allowVideoStreamCopy,
|
bool allowVideoStreamCopy,
|
||||||
bool allowAudioStreamCopy,
|
bool allowAudioStreamCopy,
|
||||||
string ipAddress)
|
IPAddress ipAddress)
|
||||||
{
|
{
|
||||||
var streamBuilder = new StreamBuilder(_mediaEncoder, _logger);
|
var streamBuilder = new StreamBuilder(_mediaEncoder, _logger);
|
||||||
|
|
||||||
@ -551,7 +552,7 @@ namespace Jellyfin.Api.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetMaxBitrate(int? clientMaxBitrate, User user, string ipAddress)
|
private int? GetMaxBitrate(int? clientMaxBitrate, User user, IPAddress ipAddress)
|
||||||
{
|
{
|
||||||
var maxBitrate = clientMaxBitrate;
|
var maxBitrate = clientMaxBitrate;
|
||||||
var remoteClientMaxBitrate = user.RemoteClientBitrateLimit ?? 0;
|
var remoteClientMaxBitrate = user.RemoteClientBitrateLimit ?? 0;
|
||||||
|
@ -84,7 +84,7 @@ namespace Jellyfin.Api.Helpers
|
|||||||
authorization.Version,
|
authorization.Version,
|
||||||
authorization.DeviceId,
|
authorization.DeviceId,
|
||||||
authorization.Device,
|
authorization.Device,
|
||||||
request.HttpContext.GetNormalizedRemoteIp(),
|
request.HttpContext.GetNormalizedRemoteIp().ToString(),
|
||||||
user);
|
user);
|
||||||
|
|
||||||
if (session == null)
|
if (session == null)
|
||||||
|
@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The HTTP context.</param>
|
/// <param name="context">The HTTP context.</param>
|
||||||
/// <returns>The remote caller IP address.</returns>
|
/// <returns>The remote caller IP address.</returns>
|
||||||
public static string GetNormalizedRemoteIp(this HttpContext context)
|
public static IPAddress GetNormalizedRemoteIp(this HttpContext context)
|
||||||
{
|
{
|
||||||
// Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests)
|
// Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests)
|
||||||
var ip = context.Connection.RemoteIpAddress ?? IPAddress.Loopback;
|
var ip = context.Connection.RemoteIpAddress ?? IPAddress.Loopback;
|
||||||
@ -35,7 +35,7 @@ namespace MediaBrowser.Common.Extensions
|
|||||||
ip = ip.MapToIPv4();
|
ip = ip.MapToIPv4();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip.ToString();
|
return ip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoFixture;
|
using AutoFixture;
|
||||||
using AutoFixture.AutoMoq;
|
using AutoFixture.AutoMoq;
|
||||||
@ -41,7 +42,7 @@ namespace Jellyfin.Api.Tests.Auth.LocalAccessPolicy
|
|||||||
public async Task LocalAccessOnly(bool isInLocalNetwork, bool shouldSucceed)
|
public async Task LocalAccessOnly(bool isInLocalNetwork, bool shouldSucceed)
|
||||||
{
|
{
|
||||||
_networkManagerMock
|
_networkManagerMock
|
||||||
.Setup(n => n.IsInLocalNetwork(It.IsAny<string>()))
|
.Setup(n => n.IsInLocalNetwork(It.IsAny<IPAddress>()))
|
||||||
.Returns(isInLocalNetwork);
|
.Returns(isInLocalNetwork);
|
||||||
|
|
||||||
TestHelpers.SetupConfigurationManager(_configurationManagerMock, true);
|
TestHelpers.SetupConfigurationManager(_configurationManagerMock, true);
|
||||||
|
63
tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
Normal file
63
tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Jellyfin.Networking.Configuration;
|
||||||
|
using Jellyfin.Networking.Manager;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Jellyfin.Networking.Tests
|
||||||
|
{
|
||||||
|
public class NetworkManagerTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the given IP address is in the specified network(s).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="network">Network address(es).</param>
|
||||||
|
/// <param name="value">The IP to check.</param>
|
||||||
|
[Theory]
|
||||||
|
[InlineData("192.168.2.1/24", "192.168.2.123")]
|
||||||
|
[InlineData("192.168.2.1/24, !192.168.2.122/32", "192.168.2.123")]
|
||||||
|
[InlineData("fd23:184f:2029:0::/56", "fd23:184f:2029:0:3139:7386:67d7:d517")]
|
||||||
|
[InlineData("fd23:184f:2029:0::/56, !fd23:184f:2029:0:3139:7386:67d7:d518/128", "fd23:184f:2029:0:3139:7386:67d7:d517")]
|
||||||
|
public void InNetwork_True_Success(string network, string value)
|
||||||
|
{
|
||||||
|
var ip = IPAddress.Parse(value);
|
||||||
|
var conf = new NetworkConfiguration()
|
||||||
|
{
|
||||||
|
EnableIPV6 = true,
|
||||||
|
EnableIPV4 = true,
|
||||||
|
LocalNetworkSubnets = network.Split(',')
|
||||||
|
};
|
||||||
|
|
||||||
|
using var networkManager = new NetworkManager(NetworkParseTests.GetMockConfig(conf), new NullLogger<NetworkManager>());
|
||||||
|
|
||||||
|
Assert.True(networkManager.IsInLocalNetwork(ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that thge given IP address is not in the network provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="network">Network address(es).</param>
|
||||||
|
/// <param name="value">The IP to check.</param>
|
||||||
|
[Theory]
|
||||||
|
[InlineData("192.168.10.0/24", "192.168.11.1")]
|
||||||
|
[InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")]
|
||||||
|
[InlineData("192.168.10.0/24", "fd23:184f:2029:0:3139:7386:67d7:d517")]
|
||||||
|
[InlineData("fd23:184f:2029:0::/56", "fd24:184f:2029:0:3139:7386:67d7:d517")]
|
||||||
|
[InlineData("fd23:184f:2029:0::/56, !fd23:184f:2029:0:3139:7386:67d7:d500/120", "fd23:184f:2029:0:3139:7386:67d7:d517")]
|
||||||
|
[InlineData("fd23:184f:2029:0::/56", "192.168.10.60")]
|
||||||
|
public void InNetwork_False_Success(string network, string value)
|
||||||
|
{
|
||||||
|
var ip = IPAddress.Parse(value);
|
||||||
|
var conf = new NetworkConfiguration()
|
||||||
|
{
|
||||||
|
EnableIPV6 = true,
|
||||||
|
EnableIPV4 = true,
|
||||||
|
LocalNetworkSubnets = network.Split(',')
|
||||||
|
};
|
||||||
|
|
||||||
|
using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), new NullLogger<NetworkManager>());
|
||||||
|
|
||||||
|
Assert.False(nm.IsInLocalNetwork(ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ namespace Jellyfin.Networking.Tests
|
|||||||
{
|
{
|
||||||
public class NetworkParseTests
|
public class NetworkParseTests
|
||||||
{
|
{
|
||||||
private static IConfigurationManager GetMockConfig(NetworkConfiguration conf)
|
internal static IConfigurationManager GetMockConfig(NetworkConfiguration conf)
|
||||||
{
|
{
|
||||||
var configManager = new Mock<IConfigurationManager>
|
var configManager = new Mock<IConfigurationManager>
|
||||||
{
|
{
|
||||||
@ -54,32 +54,6 @@ namespace Jellyfin.Networking.Tests
|
|||||||
Assert.Equal(nm.GetInternalBindAddresses().AsString(), value);
|
Assert.Equal(nm.GetInternalBindAddresses().AsString(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check that the value given is in the network provided.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="network">Network address.</param>
|
|
||||||
/// <param name="value">Value to check.</param>
|
|
||||||
[Theory]
|
|
||||||
[InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")]
|
|
||||||
public void IsInNetwork(string network, string value)
|
|
||||||
{
|
|
||||||
if (network == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(network));
|
|
||||||
}
|
|
||||||
|
|
||||||
var conf = new NetworkConfiguration()
|
|
||||||
{
|
|
||||||
EnableIPV6 = true,
|
|
||||||
EnableIPV4 = true,
|
|
||||||
LocalNetworkSubnets = network.Split(',')
|
|
||||||
};
|
|
||||||
|
|
||||||
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
|
|
||||||
|
|
||||||
Assert.False(nm.IsInLocalNetwork(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks IP address formats.
|
/// Checks IP address formats.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user