mirror of
https://github.com/telemt/telemt.git
synced 2026-10-30 20:40:51 +03:00
Descriptor-anchored Secured Filesystem Operations
This commit is contained in:
@@ -12,6 +12,8 @@ use tracing::{debug, info, warn};
|
||||
use crate::config::ProxyConfig;
|
||||
use crate::error::Result;
|
||||
use crate::transport::UpstreamManager;
|
||||
#[cfg(unix)]
|
||||
use crate::util::secure_fs::{atomic_replace_async, read_regular_limited_async};
|
||||
|
||||
use super::MePool;
|
||||
use super::http_fetch::{HTTPS_RESPONSE_BODY_MAX_BYTES, https_get};
|
||||
@@ -73,25 +75,36 @@ pub fn parse_proxy_config_text(text: &str, http_status: u16) -> ProxyConfigData
|
||||
}
|
||||
|
||||
pub async fn load_proxy_config_cache(path: &str) -> Result<ProxyConfigData> {
|
||||
let text = tokio::fs::read_to_string(path).await.map_err(|e| {
|
||||
#[cfg(unix)]
|
||||
let bytes = read_regular_limited_async(
|
||||
Path::new(path).to_path_buf(),
|
||||
HTTPS_RESPONSE_BODY_MAX_BYTES,
|
||||
)
|
||||
.await;
|
||||
#[cfg(not(unix))]
|
||||
let bytes = tokio::fs::read(path).await;
|
||||
let bytes = bytes.map_err(|e| {
|
||||
crate::error::ProxyError::Proxy(format!("read proxy-config cache '{path}' failed: {e}"))
|
||||
})?;
|
||||
let text = String::from_utf8(bytes).map_err(|e| {
|
||||
crate::error::ProxyError::Proxy(format!(
|
||||
"proxy-config cache '{path}' is not valid UTF-8: {e}"
|
||||
))
|
||||
})?;
|
||||
Ok(parse_proxy_config_text(&text, 200))
|
||||
}
|
||||
|
||||
pub async fn save_proxy_config_cache(path: &str, raw_text: &str) -> Result<()> {
|
||||
if let Some(parent) = Path::new(path).parent()
|
||||
&& !parent.as_os_str().is_empty()
|
||||
{
|
||||
tokio::fs::create_dir_all(parent).await.map_err(|e| {
|
||||
crate::error::ProxyError::Proxy(format!(
|
||||
"create proxy-config cache dir '{}' failed: {e}",
|
||||
parent.display()
|
||||
))
|
||||
})?;
|
||||
}
|
||||
|
||||
tokio::fs::write(path, raw_text).await.map_err(|e| {
|
||||
#[cfg(unix)]
|
||||
let write = atomic_replace_async(
|
||||
Path::new(path).to_path_buf(),
|
||||
raw_text.as_bytes().to_vec(),
|
||||
0o640,
|
||||
)
|
||||
.await;
|
||||
#[cfg(not(unix))]
|
||||
let write = tokio::fs::write(path, raw_text).await;
|
||||
write.map_err(|e| {
|
||||
crate::error::ProxyError::Proxy(format!("write proxy-config cache '{path}' failed: {e}"))
|
||||
})?;
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use httpdate;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
use tracing::{debug, info, warn};
|
||||
@@ -7,6 +8,8 @@ use super::http_fetch::https_get;
|
||||
use super::selftest::record_timeskew_sample;
|
||||
use crate::error::{ProxyError, Result};
|
||||
use crate::transport::UpstreamManager;
|
||||
#[cfg(unix)]
|
||||
use crate::util::secure_fs::{atomic_replace_async, read_regular_limited_async};
|
||||
|
||||
pub const PROXY_SECRET_MIN_LEN: usize = 32;
|
||||
|
||||
@@ -58,7 +61,12 @@ pub async fn fetch_proxy_secret_with_upstream(
|
||||
match download_proxy_secret_with_max_len_via_upstream(max_len, upstream, proxy_secret_url).await
|
||||
{
|
||||
Ok(data) => {
|
||||
if let Err(e) = tokio::fs::write(cache, &data).await {
|
||||
#[cfg(unix)]
|
||||
let cache_result =
|
||||
atomic_replace_async(PathBuf::from(cache), data.clone(), 0o600).await;
|
||||
#[cfg(not(unix))]
|
||||
let cache_result = tokio::fs::write(cache, &data).await;
|
||||
if let Err(e) = cache_result {
|
||||
warn!(error = %e, "Failed to cache proxy-secret (non-fatal)");
|
||||
} else {
|
||||
debug!(path = cache, len = data.len(), "Cached proxy-secret");
|
||||
@@ -72,7 +80,11 @@ pub async fn fetch_proxy_secret_with_upstream(
|
||||
}
|
||||
|
||||
// 2) Fallback to cache/file regardless of age; require len in bounds.
|
||||
match tokio::fs::read(cache).await {
|
||||
#[cfg(unix)]
|
||||
let cached = read_regular_limited_async(PathBuf::from(cache), max_len).await;
|
||||
#[cfg(not(unix))]
|
||||
let cached = tokio::fs::read(cache).await;
|
||||
match cached {
|
||||
Ok(data) if validate_proxy_secret_len(data.len(), max_len).is_ok() => {
|
||||
let age_hours = tokio::fs::metadata(cache)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user