From 5ea84e17c03dc86222fbda5c60f2ff00152b8017 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 1 Sep 2014 00:12:47 +0200 Subject: 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. --- common/playlist.h | 9 ++++++--- player/loadfile.c | 9 ++++++--- stream/stream.c | 4 ++++ stream/stream.h | 7 +++++-- stream/stream_lavf.c | 4 ++-- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/common/playlist.h b/common/playlist.h index 916d21bf45..6c609733da 100644 --- a/common/playlist.h +++ b/common/playlist.h @@ -41,9 +41,12 @@ struct playlist_entry { bool playback_short : 1; // Set to true if not at least 1 frame (audio or video) could be played. bool init_failed : 1; - // If set, assume that this is e.g. from an external playlist, and needs an - // additional safety check. - bool unsafe_origin : 1; + // Used to reject loading of unsafe entries from external playlists. + // Can have any of the following bit flags set: + // 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 { diff --git a/player/loadfile.c b/player/loadfile.c index e685c15b80..f976832a01 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -1085,8 +1085,8 @@ static void play_current_file(struct MPContext *mpctx) stream_filename = mpctx->resolve_result->url; } int stream_flags = STREAM_READ; - if (mpctx->playlist->current->unsafe_origin && !opts->load_unsafe_playlists) - stream_flags |= STREAM_SAFE_ONLY; + if (!opts->load_unsafe_playlists) + stream_flags |= mpctx->playlist->current->stream_flags; mpctx->stream = stream_create(stream_filename, stream_flags, mpctx->global); if (!mpctx->stream) { // error... demux_was_interrupted(mpctx); @@ -1130,9 +1130,12 @@ goto_reopen_demuxer: ; mpctx->initialized_flags |= INITIALIZED_DEMUXER; 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; 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); goto terminate_playback; } diff --git a/stream/stream.c b/stream/stream.c index 226626cf3c..455c0a5409 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -261,6 +261,8 @@ static int open_internal(const stream_info_t *sinfo, struct stream *underlying, return STREAM_NO_MATCH; if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY)) return STREAM_UNSAFE; + if (!sinfo->is_network && (flags & STREAM_NETWORK_ONLY)) + return STREAM_UNSAFE; const char *path = NULL; // 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->source = underlying; s->allow_caching = true; + s->is_network = sinfo->is_network; s->mode = flags & (STREAM_READ | STREAM_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->safe_origin = orig->safe_origin; cache->streaming = orig->streaming, + cache->is_network = orig->is_network; cache->opts = orig->opts; cache->global = orig->global; diff --git a/stream/stream.h b/stream/stream.h index 94103962c9..20c2e03e6a 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -56,6 +56,7 @@ enum streamtype { // flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE) #define STREAM_NO_FILTERS 2 #define STREAM_SAFE_ONLY 4 +#define STREAM_NETWORK_ONLY 8 #define STREAM_UNSAFE -3 #define STREAM_NO_MATCH -2 @@ -142,8 +143,9 @@ typedef struct stream_info_st { const struct m_option *options; const char *const *url_options; bool stream_filter; - bool can_write; - bool is_safe; + bool can_write; // correctly checks for READ/WRITE modes + 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; typedef struct stream { @@ -181,6 +183,7 @@ typedef struct stream { bool seekable : 1; // presence of general byte seeking support 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 is_network : 1; // original stream_info_t.is_network flag bool allow_caching : 1; // stream cache makes sense struct mp_log *log; struct MPOpts *opts; diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index 2270831b88..5702ec228c 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -324,10 +324,10 @@ const stream_info_t stream_info_ffmpeg = { .protocols = (const char *const[]){ "rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh", "mmshttp", "rtp", "httpproxy", "hls", "rtmpe", "rtmps", "rtmpt", "rtmpte", "rtmpts", "srtp", - "md5", NULL }, .can_write = true, .is_safe = true, + .is_network = true, }; // 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", .open = open_f, .protocols = (const char *const[]){ - "lavf", "ffmpeg", "udp", "ftp", "tcp", "tls", "unix", "sftp", + "lavf", "ffmpeg", "udp", "ftp", "tcp", "tls", "unix", "sftp", "md5", NULL }, .can_write = true, }; -- cgit v1.2.3