Vydané zdroje
Stáhnout zdroje ZIP
CH-J Tools
Procházejte adresáře a soubory konkrétního vydání aplikace.
CH-J / Server Manager
872 souborů
core-20261030T220507Z-61e4558d889f
Přidáno: · Sestaveno:
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
}77
}SHA-256
7a388a16d70c648cf3475620249f973b3a944509c527c66014cacb6b39ac505eCH-J Proprietary Software License 1.14 · Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.
SHA-256 archivu
77380d4805485ffa4027fbe7858b5836f197a4aa9d52358a43e2d12d018744df