प्रकाशित सोर्स
सोर्स ZIP डाउनलोड करें
CH-J Tools
किसी विशेष ऐप्लिकेशन रिलीज़ की डायरेक्टरी और फ़ाइलें देखें।
CH-J / Server Manager
1704 फ़ाइलें
0.1.2-beta
जोड़ा गया: · बिल्ड किया गया:
1
//! HTTPS allowlist for update and module catalogs (port of `security/urlPolicy.js`).3
use crate::core::error::{CoreError, CoreResult};4
use url::Url;6
pub fn normalize_base_url(value: &str) -> CoreResult<Url> {7
let mut url = Url::parse(value).map_err(|_| CoreError::plain("Invalid update base URL."))?;8
if url.scheme() != "https" {9
return Err(CoreError::plain("Update URL must use HTTPS."));10
}11
if !url.username().is_empty() || url.password().is_some() || url.fragment().is_some() || url.query().is_some() {12
return Err(CoreError::plain("Invalid update base URL."));13
}14
let path = format!("{}/", url.path().trim_end_matches('/'));15
url.set_path(&path);16
Ok(url)17
}19
#[derive(Default)]20
pub struct AllowOptions<'a> {21
pub base_url: Option<&'a str>,22
pub path_segment: Option<&'a str>,23
}25
pub fn assert_allowed_url(candidate: &str, allowed: &[String], options: &AllowOptions<'_>) -> CoreResult<Url> {26
let raw = candidate.trim();27
if raw.is_empty() {28
return Err(CoreError::plain("Missing URL."));29
}30
let bases = allowed.iter().map(|b| normalize_base_url(b)).collect::<CoreResult<Vec<_>>>()?;31
if raw.starts_with('/') {32
let base = normalize_base_url(options.base_url.ok_or_else(|| CoreError::plain("Relative URL requires a base URL."))?)?;33
let joined = base.join(raw.trim_start_matches('/')).map_err(|_| CoreError::plain("Invalid URL."))?;34
return assert_allowed_url(joined.as_str(), allowed, options);35
}36
let url = Url::parse(raw).map_err(|_| CoreError::plain("Invalid URL."))?;37
if !url.username().is_empty() || url.password().is_some() || url.fragment().is_some() {38
return Err(CoreError::plain("URL credentials and fragments are not allowed."));39
}40
let matched = bases41
.iter()42
.find(|base| url.scheme() == base.scheme() && url.host_str() == base.host_str() && url.port() == base.port() && url.path().starts_with(base.path()))43
.ok_or_else(|| CoreError::plain("URL is outside the update allowlist."))?;44
if let Some(segment) = options.path_segment {45
if !url.path().starts_with(&format!("{}{}", matched.path(), segment)) {46
return Err(CoreError::plain("URL path is outside the allowed update area."));47
}48
}49
Ok(url)50
}52
/// External links the main window may open in the system browser (same rule as 0.1.0).53
pub fn is_allowed_external_url(value: &str) -> bool {54
Url::parse(value).map(|u| u.scheme() == "https" && u.host_str() == Some("ch-j.de")).unwrap_or(false)55
}57
#[cfg(test)]58
mod tests {59
use super::*;61
#[test]62
fn allowlist() {63
let allowed = vec!["https://sm.ch-j.de/".to_string()];64
assert!(assert_allowed_url("https://sm.ch-j.de/files/a.dmg", &allowed, &AllowOptions { path_segment: Some("files/"), ..Default::default() }).is_ok());65
assert!(assert_allowed_url("https://sm.ch-j.de/api/x", &allowed, &AllowOptions { path_segment: Some("files/"), ..Default::default() }).is_err());66
assert!(assert_allowed_url("https://evil.example/files/a", &allowed, &AllowOptions::default()).is_err());67
assert!(assert_allowed_url("https://u:p@sm.ch-j.de/x", &allowed, &AllowOptions::default()).is_err());68
assert!(assert_allowed_url("http://sm.ch-j.de/x", &allowed, &AllowOptions::default()).is_err());69
assert!(assert_allowed_url("https://sm.ch-j.de:444/x", &allowed, &AllowOptions::default()).is_err());70
assert_eq!(71
assert_allowed_url("/files/b.deb", &allowed, &AllowOptions { base_url: Some("https://sm.ch-j.de"), ..Default::default() }).unwrap().as_str(),72
"https://sm.ch-j.de/files/b.deb"73
);74
assert!(is_allowed_external_url("https://ch-j.de/x"));75
assert!(!is_allowed_external_url("http://ch-j.de/x"));76
}78
#[test]79
fn both_update_hosts_and_nothing_alike() {80
let allowed: Vec<String> = crate::core::config::UPDATE_BASE_URLS.iter().map(|u| u.to_string()).collect();81
let files = AllowOptions { path_segment: Some("files/"), ..Default::default() };82
for ok in ["https://sm.ch-j.de/files/a.deb", "https://tools.ch-j.de/files/a.deb"] {83
assert!(assert_allowed_url(ok, &allowed, &files).is_ok(), "{ok}");84
}85
for bad in ["https://tools.ch-j.de.evil.example/files/a.deb", "https://eviltools.ch-j.de/files/a.deb", "http://tools.ch-j.de/files/a.deb", "https://ch-j.de/files/a.deb"] {86
assert!(assert_allowed_url(bad, &allowed, &files).is_err(), "{bad}");87
}88
}89
}SHA-256
a88ceab518eaf121f050b5055211a00ad7e7b96285b398c95f43a9e3ebdeb34eCH-J Proprietary Software License 1.14 · सोर्स CH-J Proprietary Software License 1.14 के तहत उपलब्ध कराया जाता है। इसकी उपलब्धता लाइसेंस की शर्तें नहीं बदलती और न ही अतिरिक्त अधिकार देती है।
आर्काइव SHA-256
ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f