aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst20
-rw-r--r--common/playlist.h3
-rw-r--r--player/loadfile.c19
-rw-r--r--stream/stream.c16
-rw-r--r--stream/stream.h3
-rw-r--r--stream/stream_file.c1
-rw-r--r--stream/stream_lavf.c20
7 files changed, 54 insertions, 28 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 87f7eb54b2..d2b062109c 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -198,20 +198,12 @@ Playback Control
(i.e. not with stdin, pipe, etc).
``--load-unsafe-playlists``
- Normally, something like ``mpv playlist.m3u`` won't load the playlist. This
- is because the playlist code is unsafe. (This is the same in all other
- variations of MPlayer.)
-
- See ``--playlist`` for details.
-
- Note: this option will allow opening playlists using the ``playlist``
- special demuxer. The ``--playlist`` uses different code, and supports more
- playlist formats than the playlist demuxer. This means that for now, the
- ``--playlist`` option should always be used if you intend to open playlists.
- Background: the special demuxer contains newly written code, while the
- ``--playlist`` option uses the old MPlayer code. Adding support for more
- playlist formats to the special demuxer is work in progress, and eventually
- the old code should disappear.
+ Load URLs from playlists which are considered unsafe (default: no). This
+ includes special protocols and anything that doesn't refer to normal files.
+ Local files and http links on the other hand are always considered safe.
+
+ Note that ``--playlist`` always loads all entries, so you use that instead
+ if you really have the need for this functionality.
``--loop-file``
Loop a single file. The difference to ``--loop=inf`` is that this doesn't
diff --git a/common/playlist.h b/common/playlist.h
index ea0e3698a2..916d21bf45 100644
--- a/common/playlist.h
+++ b/common/playlist.h
@@ -41,6 +41,9 @@ 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;
};
struct playlist {
diff --git a/player/loadfile.c b/player/loadfile.c
index 3833a80231..e685c15b80 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -1084,7 +1084,10 @@ static void play_current_file(struct MPContext *mpctx)
}
stream_filename = mpctx->resolve_result->url;
}
- mpctx->stream = stream_open(stream_filename, mpctx->global);
+ int stream_flags = STREAM_READ;
+ if (mpctx->playlist->current->unsafe_origin && !opts->load_unsafe_playlists)
+ stream_flags |= STREAM_SAFE_ONLY;
+ mpctx->stream = stream_create(stream_filename, stream_flags, mpctx->global);
if (!mpctx->stream) { // error...
demux_was_interrupted(mpctx);
goto terminate_playback;
@@ -1127,16 +1130,10 @@ goto_reopen_demuxer: ;
mpctx->initialized_flags |= INITIALIZED_DEMUXER;
if (mpctx->demuxer->playlist) {
- if (mpctx->demuxer->stream->safe_origin || opts->load_unsafe_playlists) {
- transfer_playlist(mpctx, mpctx->demuxer->playlist);
- } else {
- MP_ERR(mpctx, "\nThis looks like a playlist, but playlist support "
- "will not be used automatically.\nThe main problem with "
- "playlist safety is that playlist entries can be arbitrary,\n"
- "and an attacker could make mpv poke around in your local "
- "filesystem or network.\nUse --playlist=file or the "
- "--load-unsafe-playlists option to load them anyway.\n");
- }
+ 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;
+ transfer_playlist(mpctx, pl);
goto terminate_playback;
}
diff --git a/stream/stream.c b/stream/stream.c
index cfb3cb6c82..226626cf3c 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -61,6 +61,7 @@ extern const stream_info_t stream_info_null;
extern const stream_info_t stream_info_memory;
extern const stream_info_t stream_info_mf;
extern const stream_info_t stream_info_ffmpeg;
+extern const stream_info_t stream_info_ffmpeg_unsafe;
extern const stream_info_t stream_info_avdevice;
extern const stream_info_t stream_info_file;
extern const stream_info_t stream_info_ifo;
@@ -77,6 +78,7 @@ static const stream_info_t *const stream_list[] = {
&stream_info_cdda,
#endif
&stream_info_ffmpeg,
+ &stream_info_ffmpeg_unsafe,
&stream_info_avdevice,
#if HAVE_DVBIN
&stream_info_dvb,
@@ -257,6 +259,8 @@ static int open_internal(const stream_info_t *sinfo, struct stream *underlying,
return STREAM_NO_MATCH;
if (sinfo->stream_filter && (flags & STREAM_NO_FILTERS))
return STREAM_NO_MATCH;
+ if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY))
+ return STREAM_UNSAFE;
const char *path = NULL;
// Stream filters use the original URL, with no protocol matching at all.
@@ -335,18 +339,30 @@ struct stream *stream_create(const char *url, int flags, struct mpv_global *glob
assert(url);
// Open stream proper
+ bool unsafe = false;
for (int i = 0; stream_list[i]; i++) {
int r = open_internal(stream_list[i], NULL, url, flags, global, &s);
if (r == STREAM_OK)
break;
if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
continue;
+ if (r == STREAM_UNSAFE) {
+ unsafe = true;
+ continue;
+ }
if (r != STREAM_OK) {
mp_err(log, "Failed to open %s.\n", url);
goto done;
}
}
+ if (!s && unsafe) {
+ mp_err(log, "\nRefusing to load potentially unsafe URL from a playlist.\n"
+ "Use --playlist=file or the --load-unsafe-playlists option to "
+ "load it anyway.\n\n");
+ goto done;
+ }
+
if (!s) {
mp_err(log, "No stream found to handle url %s\n", url);
goto done;
diff --git a/stream/stream.h b/stream/stream.h
index a961267aac..94103962c9 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -55,7 +55,9 @@ 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_UNSAFE -3
#define STREAM_NO_MATCH -2
#define STREAM_UNSUPPORTED -1
#define STREAM_ERROR 0
@@ -141,6 +143,7 @@ typedef struct stream_info_st {
const char *const *url_options;
bool stream_filter;
bool can_write;
+ bool is_safe;
} stream_info_t;
typedef struct stream {
diff --git a/stream/stream_file.c b/stream/stream_file.c
index 12bea3554c..6a10114832 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -281,4 +281,5 @@ const stream_info_t stream_info_file = {
.open = open_f,
.protocols = (const char*const[]){ "file", "", NULL },
.can_write = true,
+ .is_safe = true,
};
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c
index 37c6adc51c..2270831b88 100644
--- a/stream/stream_lavf.c
+++ b/stream/stream_lavf.c
@@ -322,10 +322,24 @@ const stream_info_t stream_info_ffmpeg = {
.name = "ffmpeg",
.open = open_f,
.protocols = (const char *const[]){
- "lavf", "ffmpeg", "rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh",
- "mmshttp", "udp", "ftp", "rtp", "httpproxy", "hls", "rtmpe", "rtmps",
- "rtmpt", "rtmpte", "rtmpts", "srtp", "tcp", "udp", "tls", "unix", "sftp",
+ "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,
};
+
+// Unlike above, this is not marked as safe, and can contain protocols which
+// may do insecure things. (Such as "ffmpeg", which can access the "lavfi"
+// pseudo-demuxer, which in turn gives access to filters that can access the
+// local filesystem.)
+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",
+ NULL },
+ .can_write = true,
+};
+