aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers/HlsSegmentController.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs')
-rw-r--r--Jellyfin.Api/Controllers/HlsSegmentController.cs40
1 files changed, 22 insertions, 18 deletions
diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs
index 1b432aaf44..c61ee45830 100644
--- a/Jellyfin.Api/Controllers/HlsSegmentController.cs
+++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs
@@ -5,7 +5,6 @@ using System.IO;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Helpers;
-using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
@@ -61,10 +60,8 @@ public class HlsSegmentController : BaseJellyfinApiController
public ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string segmentId)
{
// TODO: Deprecate with new iOS app
- var file = string.Concat(segmentId, Path.GetExtension(Request.Path.Value.AsSpan()));
- var transcodePath = _serverConfigurationManager.GetTranscodePath();
- file = Path.GetFullPath(Path.Combine(transcodePath, file));
- if (!PathHelper.IsContainedIn(transcodePath, file))
+ var file = ValidateTranscodePath(string.Concat(segmentId, Path.GetExtension(Request.Path.Value.AsSpan())));
+ if (file is null)
{
return BadRequest("Invalid segment.");
}
@@ -86,11 +83,9 @@ public class HlsSegmentController : BaseJellyfinApiController
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")]
public ActionResult GetHlsPlaylistLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string playlistId)
{
- var file = string.Concat(playlistId, Path.GetExtension(Request.Path.Value.AsSpan()));
- var transcodePath = _serverConfigurationManager.GetTranscodePath();
- file = Path.GetFullPath(Path.Combine(transcodePath, file));
- if (!PathHelper.IsContainedIn(transcodePath, file)
- || Path.GetExtension(file.AsSpan()).Equals(".m3u8", StringComparison.OrdinalIgnoreCase))
+ var file = ValidateTranscodePath(string.Concat(playlistId, Path.GetExtension(Request.Path.Value.AsSpan())));
+ if (file is null
+ || !Path.GetExtension(file.AsSpan()).Equals(".m3u8", StringComparison.OrdinalIgnoreCase))
{
return BadRequest("Invalid segment.");
}
@@ -139,17 +134,13 @@ public class HlsSegmentController : BaseJellyfinApiController
[FromRoute, Required] string segmentId,
[FromRoute, Required] string segmentContainer)
{
- var file = string.Concat(segmentId, Path.GetExtension(Request.Path.Value.AsSpan()));
- var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();
-
- file = Path.GetFullPath(Path.Combine(transcodeFolderPath, file));
- if (!PathHelper.IsContainedIn(transcodeFolderPath, file))
+ var file = ValidateTranscodePath(string.Concat(segmentId, Path.GetExtension(Request.Path.Value.AsSpan())));
+ if (file is null)
{
return BadRequest("Invalid segment.");
}
- var normalizedPlaylistId = playlistId;
-
+ var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();
var filePaths = _fileSystem.GetFilePaths(transcodeFolderPath);
// Add . to start of segment container for future use.
segmentContainer = segmentContainer.Insert(0, ".");
@@ -159,7 +150,7 @@ public class HlsSegmentController : BaseJellyfinApiController
var pathExtension = Path.GetExtension(path);
if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase)
|| string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase))
- && path.Contains(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase))
+ && path.Contains(playlistId, StringComparison.OrdinalIgnoreCase))
{
playlistPath = path;
break;
@@ -171,6 +162,19 @@ public class HlsSegmentController : BaseJellyfinApiController
: GetFileResult(file, playlistPath);
}
+ private string? ValidateTranscodePath(string filename)
+ {
+ var transcodePath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(_serverConfigurationManager.GetTranscodePath()));
+ var file = Path.GetFullPath(filename, transcodePath);
+ // Require a separator after the transcode path so a sibling like "<transcodePath>-evil" can't pass.
+ if (!file.StartsWith(transcodePath + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+
+ return file;
+ }
+
private ActionResult GetFileResult(string path, string playlistPath)
{
var transcodingJob = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);