diff options
author | leot <leot@pkgsrc.org> | 2018-01-29 21:54:22 +0000 |
---|---|---|
committer | leot <leot@pkgsrc.org> | 2018-01-29 21:54:22 +0000 |
commit | fbe3a8c08433fe9ecb10d82a6128be571ded616c (patch) | |
tree | c1066a1d30e2dd0e2771c3dee8b18dccea19f53a /multimedia | |
parent | a7fd58faa1183791266cd44dc094c728dcae6ea1 (diff) | |
download | pkgsrc-fbe3a8c08433fe9ecb10d82a6128be571ded616c.tar.gz |
mpv: Add patch-player_lua_ytdl__hook.lua to address CVE-2018-6360
Sync player/lua/ytdl_hook.lua with upstream commit
2a0f9fc1588d8bda51a6340197c54285f3f62755 minus hunks that need `on_load_fail'
hook introduced after mpv-0.27.
Bump PKGREVISION.
Diffstat (limited to 'multimedia')
-rw-r--r-- | multimedia/mpv/Makefile | 4 | ||||
-rw-r--r-- | multimedia/mpv/distinfo | 3 | ||||
-rw-r--r-- | multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua | 265 |
3 files changed, 269 insertions, 3 deletions
diff --git a/multimedia/mpv/Makefile b/multimedia/mpv/Makefile index a3bc4b64f89..38baf052703 100644 --- a/multimedia/mpv/Makefile +++ b/multimedia/mpv/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.62 2018/01/28 20:10:57 wiz Exp $ +# $NetBSD: Makefile,v 1.63 2018/01/29 21:54:22 leot Exp $ DISTNAME= mpv-0.27.0 -PKGREVISION= 1 +PKGREVISION= 2 CATEGORIES= multimedia MASTER_SITES= ${MASTER_SITE_GITHUB:=mpv-player/} GITHUB_TAG= v${PKGVERSION_NOREV} diff --git a/multimedia/mpv/distinfo b/multimedia/mpv/distinfo index c13152b7f5b..bb9e3c70d5d 100644 --- a/multimedia/mpv/distinfo +++ b/multimedia/mpv/distinfo @@ -1,8 +1,9 @@ -$NetBSD: distinfo,v 1.37 2017/09/13 10:35:58 leot Exp $ +$NetBSD: distinfo,v 1.38 2018/01/29 21:54:22 leot Exp $ SHA1 (mpv-0.27.0.tar.gz) = d4bddb88cf7a112a295a130a091181acbe25605b RMD160 (mpv-0.27.0.tar.gz) = d2edbdfdc6fdf3a0c210536ac3966e99113c83ad SHA512 (mpv-0.27.0.tar.gz) = 22738f907d84d362095773972f685e3b03ab4c8172a22ddede290fc221a83ab9135b96f8b18191dabe842b2963f68983929cf065097287fc1a054a7d5f1d0ae4 Size (mpv-0.27.0.tar.gz) = 2956816 bytes SHA1 (patch-audio_out_ao__oss.c) = d7f3a75ab43efe396ce536fb54e6207a7ded3510 +SHA1 (patch-player_lua_ytdl__hook.lua) = 450a6f2640c76b5db0c0cd585674ccd689712f78 SHA1 (patch-player_main.c) = 842432e448526a9d170e7efd2b01276e36072e16 diff --git a/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua b/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua new file mode 100644 index 00000000000..c5aba3bd0a1 --- /dev/null +++ b/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua @@ -0,0 +1,265 @@ +$NetBSD: patch-player_lua_ytdl__hook.lua,v 1.1 2018/01/29 21:54:22 leot Exp $ + +Sync ytdl_hook.lua script with commit 2a0f9fc1588d8bda51a6340197c54285f3f62755 +in order to fix CVE-2018-6360. + +Please note that this completely omits hunks that need `on_load_fail' hook that +was implemented post-0.27. + +--- player/lua/ytdl_hook.lua.orig 2018-01-28 10:58:02.151884824 +0000 ++++ player/lua/ytdl_hook.lua +@@ -15,6 +16,18 @@ local ytdl = { + + local chapter_list = {} + ++function Set (t) ++ local set = {} ++ for _, v in pairs(t) do set[v] = true end ++ return set ++end ++ ++local safe_protos = Set { ++ "http", "https", "ftp", "ftps", ++ "rtmp", "rtmps", "rtmpe", "rtmpt", "rtmpts", "rtmpte", ++ "data" ++} ++ + local function exec(args) + local ret = utils.subprocess({args = args}) + return ret.status, ret.stdout, ret +@@ -71,6 +84,15 @@ local function edl_escape(url) + return "%" .. string.len(url) .. "%" .. url + end + ++local function url_is_safe(url) ++ local proto = type(url) == "string" and url:match("^(.+)://") or nil ++ local safe = proto and safe_protos[proto] ++ if not safe then ++ msg.error(("Ignoring potentially unsafe url: '%s'"):format(url)) ++ end ++ return safe ++end ++ + local function time_to_secs(time_string) + local ret + +@@ -182,6 +204,9 @@ local function edl_track_joined(fragment + + for i = offset, #fragments do + local fragment = fragments[i] ++ if not url_is_safe(join_url(base, fragment)) then ++ return nil ++ end + table.insert(parts, edl_escape(join_url(base, fragment))) + if fragment.duration then + parts[#parts] = +@@ -191,16 +216,63 @@ local function edl_track_joined(fragment + return edl .. table.concat(parts, ";") .. ";" + end + ++local function has_native_dash_demuxer() ++ local demuxers = mp.get_property_native("demuxer-lavf-list") ++ for _,v in ipairs(demuxers) do ++ if v == "dash" then ++ return true ++ end ++ end ++ return false ++end ++ ++local function valid_manifest(json) ++ local reqfmt = json["requested_formats"] and json["requested_formats"][1] or {} ++ if not reqfmt["manifest_url"] and not json["manifest_url"] then ++ return false ++ end ++ local proto = reqfmt["protocol"] or json["protocol"] or "" ++ return (has_native_dash_demuxer() and proto == "http_dash_segments") or ++ proto:find("^m3u8") ++end ++ + local function add_single_video(json) + local streamurl = "" ++ local max_bitrate = 0 ++ local reqfmts = json["requested_formats"] ++ ++ -- prefer manifest_url if present ++ if valid_manifest(json) then ++ local mpd_url = reqfmts and reqfmts[1]["manifest_url"] or ++ json["manifest_url"] ++ if not mpd_url then ++ msg.error("No manifest URL found in JSON data.") ++ return ++ elseif not url_is_safe(mpd_url) then ++ return ++ end ++ ++ streamurl = mpd_url ++ ++ if reqfmts then ++ for _, track in pairs(reqfmts) do ++ max_bitrate = track.tbr > max_bitrate and ++ track.tbr or max_bitrate ++ end ++ elseif json.tbr then ++ max_bitrate = json.tbr > max_bitrate and json.tbr or max_bitrate ++ end + + -- DASH/split tracks +- if not (json["requested_formats"] == nil) then +- for _, track in pairs(json.requested_formats) do ++ elseif reqfmts then ++ for _, track in pairs(reqfmts) do + local edl_track = nil + edl_track = edl_track_joined(track.fragments, + track.protocol, json.is_live, + track.fragment_base_url) ++ if not edl_track and not url_is_safe(track.url) then ++ return ++ end + if track.acodec and track.acodec ~= "none" then + -- audio track + mp.commandv("audio-add", +@@ -217,6 +289,9 @@ local function add_single_video(json) + edl_track = edl_track_joined(json.fragments, json.protocol, + json.is_live, json.fragment_base_url) + ++ if not edl_track and not url_is_safe(json.url) then ++ return ++ end + -- normal video or single track + streamurl = edl_track or json.url + set_http_headers(json.http_headers) +@@ -231,6 +306,13 @@ local function add_single_video(json) + + mp.set_property("file-local-options/force-media-title", json.title) + ++ -- set hls-bitrate for dash track selection ++ if max_bitrate > 0 and ++ not option_was_set("hls-bitrate") and ++ not option_was_set_locally("hls-bitrate") then ++ mp.set_property_native('file-local-options/hls-bitrate', max_bitrate*1000) ++ end ++ + -- add subtitles + if not (json.requested_subtitles == nil) then + for lang, sub_info in pairs(json.requested_subtitles) do +@@ -309,7 +391,8 @@ mp.add_hook("on_load", 10, function () + + -- check for youtube-dl in mpv's config dir + if not (ytdl.searched) then +- local ytdl_mcd = mp.find_config_file("youtube-dl") ++ local exesuf = (package.config:sub(1,1) == '\\') and '.exe' or '' ++ local ytdl_mcd = mp.find_config_file("youtube-dl" .. exesuf) + if not (ytdl_mcd == nil) then + msg.verbose("found youtube-dl at: " .. ytdl_mcd) + ytdl.path = ytdl_mcd +@@ -365,9 +448,15 @@ mp.add_hook("on_load", 10, function () + local es, json, result = exec(command) + + if (es < 0) or (json == nil) or (json == "") then +- if not result.killed_by_us then +- msg.warn("youtube-dl failed, trying to play URL directly ...") ++ local err = "youtube-dl failed: " ++ if result.error and result.error == "init" then ++ err = err .. "not found or not enough permissions" ++ elseif not result.killed_by_us then ++ err = err .. "unexpected error ocurred" ++ else ++ err = string.format("%s returned '%d'", err, es) + end ++ msg.error(err) + return + end + +@@ -396,18 +485,26 @@ mp.add_hook("on_load", 10, function () + return + end + ++ local self_redirecting_url = ++ json.entries[1]["_type"] ~= "url_transparent" and ++ json.entries[1]["webpage_url"] and ++ json.entries[1]["webpage_url"] == json["webpage_url"] ++ + + -- some funky guessing to detect multi-arc videos +- if (not (json.entries[1]["_type"] == "url_transparent")) and +- (not (json.entries[1]["webpage_url"] == nil) +- and (json.entries[1]["webpage_url"] == json["webpage_url"])) +- and not (json.entries[1].url == nil) then ++ if self_redirecting_url and #json.entries > 1 ++ and json.entries[1].protocol == "m3u8_native" ++ and json.entries[1].url then + msg.verbose("multi-arc video detected, building EDL") + + local playlist = edl_track_joined(json.entries) + + msg.debug("EDL: " .. playlist) + ++ if not playlist then ++ return ++ end ++ + -- can't change the http headers for each entry, so use the 1st + if json.entries[1] then + set_http_headers(json.entries[1].http_headers) +@@ -446,39 +543,43 @@ mp.add_hook("on_load", 10, function () + end + end + +- elseif (not (json.entries[1]["_type"] == "url_transparent")) and +- (not (json.entries[1]["webpage_url"] == nil) +- and (json.entries[1]["webpage_url"] == json["webpage_url"])) +- and (#json.entries == 1) then +- ++ elseif self_redirecting_url and #json.entries == 1 then + msg.verbose("Playlist with single entry detected.") + add_single_video(json.entries[1]) + else +- +- local playlist = "#EXTM3U\n" ++ local playlist = {"#EXTM3U"} + for i, entry in pairs(json.entries) do + local site = entry.url + local title = entry.title + + if not (title == nil) then + title = string.gsub(title, '%s+', ' ') +- playlist = playlist .. "#EXTINF:0," .. title .. "\n" ++ table.insert(playlist, "#EXTINF:0," .. title) + end + +- -- some extractors will still return the full info for +- -- all clips in the playlist and the URL will point +- -- directly to the file in that case, which we don't +- -- want so get the webpage URL instead, which is what +- -- we want +- if not (json.entries[1]["_type"] == "url_transparent") +- and not (entry["webpage_url"] == nil) then ++ --[[ some extractors will still return the full info for ++ all clips in the playlist and the URL will point ++ directly to the file in that case, which we don't ++ want so get the webpage URL instead, which is what ++ we want, but only if we aren't going to trigger an ++ infinite loop ++ --]] ++ if entry["webpage_url"] and not self_redirecting_url then + site = entry["webpage_url"] + end + +- playlist = playlist .. "ytdl://" .. site .. "\n" ++ -- links with only youtube id as returned by --flat-playlist ++ if not site:find("://") then ++ table.insert(playlist, "ytdl://" .. site) ++ elseif url_is_safe(site) then ++ table.insert(playlist, site) ++ end ++ + end + +- mp.set_property("stream-open-filename", "memory://" .. playlist) ++ if #playlist > 0 then ++ mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n")) ++ end + end + + else -- probably a video |