video: Check OpenH264 library downloads with SHA256 instead of MD5
KJ: Cisco distributes the OpenH264 binaries and their MD5 hashes over HTTP. Knowing that HTTP is insecure, MD5 hashes may easily collide, and both are served over the same medium, saying that this method is ridiculous is an understatement. Take into account that these are binaries we download and execute, and we for sure do not want to turn Ruffle into a remote code execution framework. This patch changes MD5 to SHA256 in order to increase security and protect our users from attacks resulting from this vulnerability. Co-authored-by: Kamil Jarosz <kjarosh256@gmail.com>
This commit is contained in:
parent
f1c39d13c5
commit
3dd32aba1f
|
@ -3076,16 +3076,6 @@ dependencies = [
|
||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "md-5"
|
|
||||||
version = "0.10.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.2"
|
version = "2.7.2"
|
||||||
|
@ -4558,11 +4548,11 @@ dependencies = [
|
||||||
"bzip2",
|
"bzip2",
|
||||||
"hex",
|
"hex",
|
||||||
"libloading",
|
"libloading",
|
||||||
"md-5",
|
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"ruffle_render",
|
"ruffle_render",
|
||||||
"ruffle_video",
|
"ruffle_video",
|
||||||
"ruffle_video_software",
|
"ruffle_video_software",
|
||||||
|
"sha2",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"swf",
|
"swf",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
|
|
@ -17,14 +17,8 @@ ruffle_video_software = { path = "../software" }
|
||||||
|
|
||||||
# Needed for OpenH264:
|
# Needed for OpenH264:
|
||||||
libloading = "0.8.5"
|
libloading = "0.8.5"
|
||||||
md-5 = "0.10.6"
|
|
||||||
reqwest = { version = "0.12.5", default-features = false, features = ["blocking"] }
|
reqwest = { version = "0.12.5", default-features = false, features = ["blocking"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
bzip2 = { version = "0.4.4", features = ["static"] }
|
bzip2 = { version = "0.4.4", features = ["static"] }
|
||||||
tempfile = "3.12.0"
|
tempfile = "3.12.0"
|
||||||
|
sha2 = "0.10.8"
|
||||||
[package.metadata.cargo-machete]
|
|
||||||
ignored = [
|
|
||||||
# Renames itself to "md5", see: https://github.com/bnjbvr/cargo-machete/issues/8
|
|
||||||
"md-5"
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::decoder::VideoDecoder;
|
use crate::decoder::VideoDecoder;
|
||||||
use bzip2::read::BzDecoder;
|
use bzip2::read::BzDecoder;
|
||||||
use md5::{Digest, Md5};
|
|
||||||
use ruffle_render::backend::RenderBackend;
|
use ruffle_render::backend::RenderBackend;
|
||||||
use ruffle_render::bitmap::{BitmapHandle, BitmapInfo, PixelRegion};
|
use ruffle_render::bitmap::{BitmapHandle, BitmapInfo, PixelRegion};
|
||||||
use ruffle_video::backend::VideoBackend;
|
use ruffle_video::backend::VideoBackend;
|
||||||
|
@ -8,6 +7,7 @@ use ruffle_video::error::Error;
|
||||||
use ruffle_video::frame::{EncodedFrame, FrameDependency};
|
use ruffle_video::frame::{EncodedFrame, FrameDependency};
|
||||||
use ruffle_video::VideoStreamHandle;
|
use ruffle_video::VideoStreamHandle;
|
||||||
use ruffle_video_software::backend::SoftwareVideoBackend;
|
use ruffle_video_software::backend::SoftwareVideoBackend;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::copy;
|
use std::io::copy;
|
||||||
|
@ -44,35 +44,35 @@ impl ExternalVideoBackend {
|
||||||
match (std::env::consts::OS, std::env::consts::ARCH) {
|
match (std::env::consts::OS, std::env::consts::ARCH) {
|
||||||
("linux", "x86") => Ok((
|
("linux", "x86") => Ok((
|
||||||
"libopenh264-2.4.1-linux32.7.so",
|
"libopenh264-2.4.1-linux32.7.so",
|
||||||
"dd0743066117d63e1b2abc56a86506e5",
|
"b7cf0e407f99056d90cbf62787a34820a7595b2129b165319d50766e00a66704",
|
||||||
)),
|
)),
|
||||||
("linux", "x86_64") => Ok((
|
("linux", "x86_64") => Ok((
|
||||||
"libopenh264-2.4.1-linux64.7.so",
|
"libopenh264-2.4.1-linux64.7.so",
|
||||||
"19c561386a9564f8510fcb7586b9d402",
|
"1392d21466bc638e68151b716d5b2086d54cd812afd43253f1adb5b6e0185f51",
|
||||||
)),
|
)),
|
||||||
("linux", "arm") => Ok((
|
("linux", "arm") => Ok((
|
||||||
"libopenh264-2.4.1-linux-arm.7.so",
|
"libopenh264-2.4.1-linux-arm.7.so",
|
||||||
"2274a1bbd13f32b7afe22092e44fa2b5",
|
"fd1dfb27d30bb72e903c9d2b4c650104a4369d2e7ffe8a4a533e8db2e7e9b19e",
|
||||||
)),
|
)),
|
||||||
("linux", "aarch64") => Ok((
|
("linux", "aarch64") => Ok((
|
||||||
"libopenh264-2.4.1-linux-arm64.7.so",
|
"libopenh264-2.4.1-linux-arm64.7.so",
|
||||||
"2aa205f08077aa2d049032e0b56c5b84",
|
"e8ea7e42855ceb4a90e7bd0b3abeba0c58b5f97166e8b0a30eefd58e099557a4",
|
||||||
)),
|
)),
|
||||||
("macos", "x86_64") => Ok((
|
("macos", "x86_64") => Ok((
|
||||||
"libopenh264-2.4.1-mac-x64.dylib",
|
"libopenh264-2.4.1-mac-x64.dylib",
|
||||||
"9fefa1e0279a49b8a4e9cf6fc148bc0c",
|
"cc0ba518a63791c37571f3c851f0aa03a4fbda5410acc214ecd4f24f8d1c478e",
|
||||||
)),
|
)),
|
||||||
("macos", "aarch64") => Ok((
|
("macos", "aarch64") => Ok((
|
||||||
"libopenh264-2.4.1-mac-arm64.dylib",
|
"libopenh264-2.4.1-mac-arm64.dylib",
|
||||||
"41f59bb5696ffeadbfba3a8a95ec39b7",
|
"213ff93831cfa3dd6d7ad0c3a3403a6ceedf4ac1341e1278b5b869d42fefb496",
|
||||||
)),
|
)),
|
||||||
("windows", "x86") => Ok((
|
("windows", "x86") => Ok((
|
||||||
"openh264-2.4.1-win32.dll",
|
"openh264-2.4.1-win32.dll",
|
||||||
"a9360e6dd1e24320c3d65a0c65bf14a4",
|
"83270149640469c994a62cc32a6d8c0413cd7b802b7f1f2f532159f5bdc1cedd",
|
||||||
)),
|
)),
|
||||||
("windows", "x86_64") => Ok((
|
("windows", "x86_64") => Ok((
|
||||||
"openh264-2.4.1-win64.dll",
|
"openh264-2.4.1-win64.dll",
|
||||||
"c85406e6b73812ec3fb9da5f898c6a9e",
|
"081b0c081480d177cbfddfbc90b1613640e702f875897b30d8de195cde73dd34",
|
||||||
)),
|
)),
|
||||||
(os, arch) => Err(format!("Unsupported OS/ARCH: {} {}", os, arch).into()),
|
(os, arch) => Err(format!("Unsupported OS/ARCH: {} {}", os, arch).into()),
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl ExternalVideoBackend {
|
||||||
const URL_BASE: &str = "http://ciscobinary.openh264.org/";
|
const URL_BASE: &str = "http://ciscobinary.openh264.org/";
|
||||||
const URL_SUFFIX: &str = ".bz2";
|
const URL_SUFFIX: &str = ".bz2";
|
||||||
|
|
||||||
let (filename, md5sum) = Self::get_openh264_data()?;
|
let (filename, sha256sum) = Self::get_openh264_data()?;
|
||||||
|
|
||||||
let current_exe = std::env::current_exe()?;
|
let current_exe = std::env::current_exe()?;
|
||||||
let directory = current_exe
|
let directory = current_exe
|
||||||
|
@ -101,20 +101,20 @@ impl ExternalVideoBackend {
|
||||||
copy(&mut bzip2_reader, &mut tempfile)?;
|
copy(&mut bzip2_reader, &mut tempfile)?;
|
||||||
// Let's assume that if this fails, it's because another process has already put it there
|
// Let's assume that if this fails, it's because another process has already put it there
|
||||||
// and loaded it, therefore it can't be overwritten (on Windows at least), but in the end,
|
// and loaded it, therefore it can't be overwritten (on Windows at least), but in the end,
|
||||||
// all's fine - the MD5 hash will still be checked before attempting to load the library.
|
// all's fine - the hash will still be checked before attempting to load the library.
|
||||||
let _ = tempfile.persist(&filepath);
|
let _ = tempfile.persist(&filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regardless of whether the library was already there, or we just downloaded it, let's check the MD5 hash.
|
// Regardless of whether the library was already there, or we just downloaded it, let's check the MD5 hash.
|
||||||
let mut md5 = Md5::new();
|
let mut sha256 = Sha256::new();
|
||||||
copy(&mut File::open(filepath.clone())?, &mut md5)?;
|
copy(&mut File::open(filepath.clone())?, &mut sha256)?;
|
||||||
let md5digest = md5.finalize();
|
let sha256digest = sha256.finalize();
|
||||||
let result: [u8; 16] = md5digest.into();
|
let result: [u8; 32] = sha256digest.into();
|
||||||
|
|
||||||
if result[..] != hex::decode(md5sum)?[..] {
|
if result[..] != hex::decode(sha256sum)?[..] {
|
||||||
let size = filepath.metadata().map(|f| f.len()).unwrap_or_default();
|
let size = filepath.metadata().map(|f| f.len()).unwrap_or_default();
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"MD5 checksum mismatch for {filename}; expected {md5sum}, found {md5digest:x} (with a size of {size} bytes)",
|
"SHA256 checksum mismatch for {filename}; expected {sha256sum}, found {sha256digest:x} (with a size of {size} bytes)",
|
||||||
)
|
)
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue