mirror of https://github.com/mpv-player/mpv
player: don't allow remote playlists to load local files
Because that might be a bad idea. Note that remote playlists still can use any protocol marked with is_safe and is_network, because the case of http-hosted playlists containing URLs using other streaming protocols is not unusual.
This commit is contained in:
parent
129a7c056a
commit
5ea84e17c0
|
@ -41,9 +41,12 @@ struct playlist_entry {
|
||||||
bool playback_short : 1;
|
bool playback_short : 1;
|
||||||
// Set to true if not at least 1 frame (audio or video) could be played.
|
// Set to true if not at least 1 frame (audio or video) could be played.
|
||||||
bool init_failed : 1;
|
bool init_failed : 1;
|
||||||
// If set, assume that this is e.g. from an external playlist, and needs an
|
// Used to reject loading of unsafe entries from external playlists.
|
||||||
// additional safety check.
|
// Can have any of the following bit flags set:
|
||||||
bool unsafe_origin : 1;
|
// STREAM_SAFE_ONLY: only allow streams marked with is_safe
|
||||||
|
// STREAM_NETWORK_ONLY: only allow streams marked with is_network
|
||||||
|
// The value 0 allows everything.
|
||||||
|
int stream_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct playlist {
|
struct playlist {
|
||||||
|
|
|
@ -1085,8 +1085,8 @@ static void play_current_file(struct MPContext *mpctx)
|
||||||
stream_filename = mpctx->resolve_result->url;
|
stream_filename = mpctx->resolve_result->url;
|
||||||
}
|
}
|
||||||
int stream_flags = STREAM_READ;
|
int stream_flags = STREAM_READ;
|
||||||
if (mpctx->playlist->current->unsafe_origin && !opts->load_unsafe_playlists)
|
if (!opts->load_unsafe_playlists)
|
||||||
stream_flags |= STREAM_SAFE_ONLY;
|
stream_flags |= mpctx->playlist->current->stream_flags;
|
||||||
mpctx->stream = stream_create(stream_filename, stream_flags, mpctx->global);
|
mpctx->stream = stream_create(stream_filename, stream_flags, mpctx->global);
|
||||||
if (!mpctx->stream) { // error...
|
if (!mpctx->stream) { // error...
|
||||||
demux_was_interrupted(mpctx);
|
demux_was_interrupted(mpctx);
|
||||||
|
@ -1130,9 +1130,12 @@ goto_reopen_demuxer: ;
|
||||||
mpctx->initialized_flags |= INITIALIZED_DEMUXER;
|
mpctx->initialized_flags |= INITIALIZED_DEMUXER;
|
||||||
|
|
||||||
if (mpctx->demuxer->playlist) {
|
if (mpctx->demuxer->playlist) {
|
||||||
|
int entry_stream_flags =
|
||||||
|
(mpctx->demuxer->stream->safe_origin ? 0 : STREAM_SAFE_ONLY) |
|
||||||
|
(mpctx->demuxer->stream->is_network ? STREAM_NETWORK_ONLY : 0);
|
||||||
struct playlist *pl = mpctx->demuxer->playlist;
|
struct playlist *pl = mpctx->demuxer->playlist;
|
||||||
for (struct playlist_entry *e = pl->first; e; e = e->next)
|
for (struct playlist_entry *e = pl->first; e; e = e->next)
|
||||||
e->unsafe_origin |= !mpctx->demuxer->stream->safe_origin;
|
e->stream_flags |= entry_stream_flags;
|
||||||
transfer_playlist(mpctx, pl);
|
transfer_playlist(mpctx, pl);
|
||||||
goto terminate_playback;
|
goto terminate_playback;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,8 @@ static int open_internal(const stream_info_t *sinfo, struct stream *underlying,
|
||||||
return STREAM_NO_MATCH;
|
return STREAM_NO_MATCH;
|
||||||
if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY))
|
if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY))
|
||||||
return STREAM_UNSAFE;
|
return STREAM_UNSAFE;
|
||||||
|
if (!sinfo->is_network && (flags & STREAM_NETWORK_ONLY))
|
||||||
|
return STREAM_UNSAFE;
|
||||||
|
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
// Stream filters use the original URL, with no protocol matching at all.
|
// Stream filters use the original URL, with no protocol matching at all.
|
||||||
|
@ -284,6 +286,7 @@ static int open_internal(const stream_info_t *sinfo, struct stream *underlying,
|
||||||
s->path = talloc_strdup(s, path);
|
s->path = talloc_strdup(s, path);
|
||||||
s->source = underlying;
|
s->source = underlying;
|
||||||
s->allow_caching = true;
|
s->allow_caching = true;
|
||||||
|
s->is_network = sinfo->is_network;
|
||||||
s->mode = flags & (STREAM_READ | STREAM_WRITE);
|
s->mode = flags & (STREAM_READ | STREAM_WRITE);
|
||||||
|
|
||||||
if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
|
if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
|
||||||
|
@ -797,6 +800,7 @@ static stream_t *open_cache(stream_t *orig, const char *name)
|
||||||
cache->lavf_type = talloc_strdup(cache, orig->lavf_type);
|
cache->lavf_type = talloc_strdup(cache, orig->lavf_type);
|
||||||
cache->safe_origin = orig->safe_origin;
|
cache->safe_origin = orig->safe_origin;
|
||||||
cache->streaming = orig->streaming,
|
cache->streaming = orig->streaming,
|
||||||
|
cache->is_network = orig->is_network;
|
||||||
cache->opts = orig->opts;
|
cache->opts = orig->opts;
|
||||||
cache->global = orig->global;
|
cache->global = orig->global;
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ enum streamtype {
|
||||||
// flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE)
|
// flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE)
|
||||||
#define STREAM_NO_FILTERS 2
|
#define STREAM_NO_FILTERS 2
|
||||||
#define STREAM_SAFE_ONLY 4
|
#define STREAM_SAFE_ONLY 4
|
||||||
|
#define STREAM_NETWORK_ONLY 8
|
||||||
|
|
||||||
#define STREAM_UNSAFE -3
|
#define STREAM_UNSAFE -3
|
||||||
#define STREAM_NO_MATCH -2
|
#define STREAM_NO_MATCH -2
|
||||||
|
@ -142,8 +143,9 @@ typedef struct stream_info_st {
|
||||||
const struct m_option *options;
|
const struct m_option *options;
|
||||||
const char *const *url_options;
|
const char *const *url_options;
|
||||||
bool stream_filter;
|
bool stream_filter;
|
||||||
bool can_write;
|
bool can_write; // correctly checks for READ/WRITE modes
|
||||||
bool is_safe;
|
bool is_safe; // opening is no security issue, even with remote provided URLs
|
||||||
|
bool is_network; // used to restrict remote playlist entries to remote URLs
|
||||||
} stream_info_t;
|
} stream_info_t;
|
||||||
|
|
||||||
typedef struct stream {
|
typedef struct stream {
|
||||||
|
@ -181,6 +183,7 @@ typedef struct stream {
|
||||||
bool seekable : 1; // presence of general byte seeking support
|
bool seekable : 1; // presence of general byte seeking support
|
||||||
bool fast_skip : 1; // consider stream fast enough to fw-seek by skipping
|
bool fast_skip : 1; // consider stream fast enough to fw-seek by skipping
|
||||||
bool safe_origin : 1; // used for playlists that can be opened safely
|
bool safe_origin : 1; // used for playlists that can be opened safely
|
||||||
|
bool is_network : 1; // original stream_info_t.is_network flag
|
||||||
bool allow_caching : 1; // stream cache makes sense
|
bool allow_caching : 1; // stream cache makes sense
|
||||||
struct mp_log *log;
|
struct mp_log *log;
|
||||||
struct MPOpts *opts;
|
struct MPOpts *opts;
|
||||||
|
|
|
@ -324,10 +324,10 @@ const stream_info_t stream_info_ffmpeg = {
|
||||||
.protocols = (const char *const[]){
|
.protocols = (const char *const[]){
|
||||||
"rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh", "mmshttp", "rtp",
|
"rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh", "mmshttp", "rtp",
|
||||||
"httpproxy", "hls", "rtmpe", "rtmps", "rtmpt", "rtmpte", "rtmpts", "srtp",
|
"httpproxy", "hls", "rtmpe", "rtmps", "rtmpt", "rtmpte", "rtmpts", "srtp",
|
||||||
"md5",
|
|
||||||
NULL },
|
NULL },
|
||||||
.can_write = true,
|
.can_write = true,
|
||||||
.is_safe = true,
|
.is_safe = true,
|
||||||
|
.is_network = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unlike above, this is not marked as safe, and can contain protocols which
|
// Unlike above, this is not marked as safe, and can contain protocols which
|
||||||
|
@ -338,7 +338,7 @@ const stream_info_t stream_info_ffmpeg_unsafe = {
|
||||||
.name = "ffmpeg",
|
.name = "ffmpeg",
|
||||||
.open = open_f,
|
.open = open_f,
|
||||||
.protocols = (const char *const[]){
|
.protocols = (const char *const[]){
|
||||||
"lavf", "ffmpeg", "udp", "ftp", "tcp", "tls", "unix", "sftp",
|
"lavf", "ffmpeg", "udp", "ftp", "tcp", "tls", "unix", "sftp", "md5",
|
||||||
NULL },
|
NULL },
|
||||||
.can_write = true,
|
.can_write = true,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue