Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions core/src/backend/navigator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@
Other,
}

impl FetchReason {
pub fn all() -> &'static [FetchReason] {
&[
FetchReason::LoadSwf,
FetchReason::UrlLoader,
FetchReason::Other,
]
}

Check warning on line 73 in core/src/backend/navigator.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (67–73)
}

impl NavigationMethod {
/// Convert an SWF method enum into a NavigationMethod.
pub fn from_send_vars_method(s: SendVarsMethod) -> Option<Self> {
Expand Down
63 changes: 57 additions & 6 deletions core/src/compatibility_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::collections::HashSet;
use url::Url;

use crate::backend::navigator::FetchReason;
use crate::backend::navigator::{ErrorResponse, FetchReason};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UrlRewriteStage {
Expand Down Expand Up @@ -40,10 +40,26 @@
}
}

#[derive(Debug, Clone)]
pub struct UrlBlockRule {
pub fetch_reasons: HashSet<FetchReason>,
pub host: String,
}

impl UrlBlockRule {
pub fn new(fetch_reasons: &[FetchReason], host: impl ToString) -> Self {
Self {
fetch_reasons: fetch_reasons.iter().cloned().collect(),
host: host.to_string(),
}
}

Check warning on line 55 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (50–55)
}

#[derive(Debug, Clone)]
pub struct RuleSet {
name: String,
domain_rewrite_rules: Vec<UrlRewriteRule>,
domain_block_rules: Vec<UrlBlockRule>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -84,6 +100,7 @@
"*.konggames.com",
"chat.kongregate.com",
)],
domain_block_rules: vec![],

Check warning on line 103 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (103)
},
// Replaces fpdownload.adobe.com with Ruffle's CDN. fpdownload.adobe.com hosts SWZ files
// which do not work on web due to CORS (and the reliability of fpdownload.adobe.com is
Expand All @@ -96,22 +113,33 @@
"fpdownload.adobe.com",
"cdn.ruffle.rs",
)],
domain_block_rules: vec![],
},
// Mochiads currently don't work and the moachiads.com domain is up for sale.
// There are real concerns that a malicious party could buy it.
RuleSet {
name: "mochiads".to_string(),
domain_rewrite_rules: vec![],
domain_block_rules: vec![UrlBlockRule::new(
FetchReason::all(),
"*.mochiads.com",
)],

Check warning on line 126 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (116–126)
},
],
}
}

pub fn rewrite_swf_url(
pub fn block_or_rewrite_swf_url(
&self,
original_url: Cow<'_, str>,
stage: UrlRewriteStage,
fetch_reason: FetchReason,
) -> Option<String> {
) -> Result<Option<String>, ErrorResponse> {
let mut url = match Url::parse(&original_url) {
Ok(url) => url,
Err(e) => {
tracing::warn!("Couldn't rewrite swf url {original_url}: {e}");
return None;
return Ok(None);
}
};
let mut rewritten = false;
Expand Down Expand Up @@ -139,12 +167,34 @@
}
}
}

if stage == UrlRewriteStage::BeforeRequest {
for rule in &rule_set.domain_block_rules {
if !rule.fetch_reasons.contains(&fetch_reason) {
continue;
}

Check warning on line 175 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (171–175)

if let Some(host) = url.host_str() {
if domain_matches(&rule.host, host) {
tracing::info!(

Check warning on line 179 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (177–179)
"Blocking url due to compatibility ruleset '{}'",
rule_set.name
);

return Err(ErrorResponse {
url: original_url.to_string(),
error: crate::loader::Error::BlockedHost(rule.host.clone()),
});
}
}

Check warning on line 189 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (184–189)
}
}

Check warning on line 191 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (191)
}

if rewritten {
Some(url.to_string())
Ok(Some(url.to_string()))

Check warning on line 195 in core/src/compatibility_rules.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (195)
} else {
None
Ok(None)
}
}
}
Expand Down Expand Up @@ -183,6 +233,7 @@
#[test]
fn test_domain_matches() {
assert!(domain_matches("foo.example.com", "foo.example.com"));
assert!(domain_matches("*.example.com", "example.com"));
assert!(domain_matches("*.example.com", "foo.example.com"));
assert!(domain_matches("*.foo.example.com", "foo.example.com"));
assert!(domain_matches("*.com", "foo.example.com"));
Expand Down
3 changes: 3 additions & 0 deletions core/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ pub enum Error {
#[error("Domain resolution failure: {0}")]
InvalidDomain(String),

#[error("Blocked host: {0}")]
BlockedHost(String),

#[error("Invalid SWF: {0}")]
InvalidSwf(#[from] swf::error::Error),

Expand Down
23 changes: 14 additions & 9 deletions core/src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2520,13 +2520,14 @@
mut request: Request,
fetch_reason: FetchReason,
) -> OwnedFuture<Box<dyn SuccessResponse>, ErrorResponse> {
let new_url = self.compatibility_rules.rewrite_swf_url(
match self.compatibility_rules.block_or_rewrite_swf_url(
request.url().into(),
UrlRewriteStage::BeforeRequest,
fetch_reason,
);
if let Some(new_url) = new_url {
request.set_url(new_url);
) {
Ok(Some(new_url)) => request.set_url(new_url),

Check warning on line 2528 in core/src/player.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (2528)
Ok(None) => {}
Err(error) => return Box::pin(async move { Err(error) }),
}

let self_reference = self.self_reference.clone();
Expand All @@ -2542,11 +2543,15 @@
return Ok(response);
};

let new_url = player.lock().unwrap().compatibility_rules.rewrite_swf_url(
response.url(),
UrlRewriteStage::AfterResponse,
fetch_reason,
);
let new_url = player
.lock()
.unwrap()
.compatibility_rules
.block_or_rewrite_swf_url(
response.url(),
UrlRewriteStage::AfterResponse,
fetch_reason,
)?;
if let Some(new_url) = new_url {
response.set_url(new_url);
}
Expand Down
Loading