fix(vfs): V-04 — structured anti-leak shield rules and custom filter list
This commit is contained in:
+53
-9
@@ -23,7 +23,7 @@ use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
use crate::crypto::{decrypt_chunk, encrypt_chunk, CHUNK_SIZE};
|
||||
use crate::storage::Database;
|
||||
use crate::vfs::{is_leak_file, SanctumDirEntry, SanctumMetaData};
|
||||
use crate::vfs::{is_leak_file_with_custom, SanctumDirEntry, SanctumMetaData};
|
||||
|
||||
pub const CARRIER_MAGIC: &[u8; 8] = b"SANCTCAR";
|
||||
pub const CARRIER_VERSION: u32 = 1;
|
||||
@@ -271,11 +271,16 @@ pub struct CarrierFsInner {
|
||||
pub dek_inner: Arc<Zeroizing<[u8; 32]>>,
|
||||
pub format_version: u32,
|
||||
pub anti_leak: bool,
|
||||
pub custom_leak_rules: Arc<Vec<String>>,
|
||||
pub leak_counter: Arc<AtomicU64>,
|
||||
pub manifest: CarrierManifest,
|
||||
pub last_activity: Arc<AtomicU64>,
|
||||
}
|
||||
|
||||
impl CarrierFsInner {
|
||||
pub fn is_leak(&self, name: &str) -> bool {
|
||||
self.anti_leak && is_leak_file_with_custom(name, &self.custom_leak_rules)
|
||||
}
|
||||
pub fn save_manifest(&mut self) -> Result<()> {
|
||||
let manifest_bytes = serde_json::to_vec(&self.manifest)?;
|
||||
if manifest_bytes.len() > (crate::crypto::CHUNK_SIZE - 64) {
|
||||
@@ -369,14 +374,15 @@ pub struct CarrierFs {
|
||||
}
|
||||
|
||||
impl CarrierFs {
|
||||
/// Lädt ein bestehendes Carrier-Dateisystem aus Block 0 der Trägerdatei.
|
||||
pub fn load(
|
||||
/// Lädt ein bestehendes Carrier-Dateisystem mit benutzerdefinierten Anti-Leak-Regeln (V-04).
|
||||
pub fn load_with_leak_rules(
|
||||
db: Database,
|
||||
carrier_node_id: i64,
|
||||
dek_outer: Arc<Zeroizing<[u8; 32]>>,
|
||||
dek_inner: Arc<Zeroizing<[u8; 32]>>,
|
||||
format_version: u32,
|
||||
anti_leak: bool,
|
||||
custom_leak_rules: Vec<String>,
|
||||
) -> Result<Self> {
|
||||
let manifest_bytes = read_carrier_block(
|
||||
&db,
|
||||
@@ -408,6 +414,8 @@ impl CarrierFs {
|
||||
dek_inner,
|
||||
format_version,
|
||||
anti_leak,
|
||||
custom_leak_rules: Arc::new(custom_leak_rules),
|
||||
leak_counter: Arc::new(AtomicU64::new(0)),
|
||||
manifest,
|
||||
last_activity: Arc::new(AtomicU64::new(now)),
|
||||
};
|
||||
@@ -417,8 +425,33 @@ impl CarrierFs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Lädt ein bestehendes Carrier-Dateisystem aus Block 0 der Trägerdatei.
|
||||
pub fn load(
|
||||
db: Database,
|
||||
carrier_node_id: i64,
|
||||
dek_outer: Arc<Zeroizing<[u8; 32]>>,
|
||||
dek_inner: Arc<Zeroizing<[u8; 32]>>,
|
||||
format_version: u32,
|
||||
anti_leak: bool,
|
||||
) -> Result<Self> {
|
||||
Self::load_with_leak_rules(
|
||||
db,
|
||||
carrier_node_id,
|
||||
dek_outer,
|
||||
dek_inner,
|
||||
format_version,
|
||||
anti_leak,
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn leak_counter(&self) -> Arc<AtomicU64> {
|
||||
let inner = self.inner.lock().unwrap_or_else(|e| e.into_inner());
|
||||
inner.leak_counter.clone()
|
||||
}
|
||||
|
||||
pub fn last_activity(&self) -> Arc<AtomicU64> {
|
||||
let inner = self.inner.lock().unwrap();
|
||||
let inner = self.inner.lock().unwrap_or_else(|e| e.into_inner());
|
||||
inner.last_activity.clone()
|
||||
}
|
||||
|
||||
@@ -449,13 +482,14 @@ impl DavFileSystem for CarrierFs {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let (parent_path, file_name) = inner.split_parent_and_name(&path_str);
|
||||
|
||||
if inner.anti_leak && is_leak_file(file_name) {
|
||||
if inner.is_leak(file_name) {
|
||||
if options.create
|
||||
|| options.create_new
|
||||
|| options.write
|
||||
|| options.append
|
||||
|| options.truncate
|
||||
{
|
||||
inner.leak_counter.fetch_add(1, Ordering::Relaxed);
|
||||
return Err(FsError::Forbidden);
|
||||
}
|
||||
}
|
||||
@@ -554,7 +588,14 @@ impl DavFileSystem for CarrierFs {
|
||||
.inodes
|
||||
.values()
|
||||
.filter(|child| child.parent_id == Some(node.id))
|
||||
.filter(|child| !inner.anti_leak || !is_leak_file(&child.name))
|
||||
.filter(|child| {
|
||||
if inner.is_leak(&child.name) {
|
||||
inner.leak_counter.fetch_add(1, Ordering::Relaxed);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|child| {
|
||||
Ok(Box::new(SanctumDirEntry {
|
||||
name: child.name.clone(),
|
||||
@@ -601,7 +642,8 @@ impl DavFileSystem for CarrierFs {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let (parent_path, dir_name) = inner.split_parent_and_name(&path_str);
|
||||
|
||||
if inner.anti_leak && is_leak_file(dir_name) {
|
||||
if inner.is_leak(dir_name) {
|
||||
inner.leak_counter.fetch_add(1, Ordering::Relaxed);
|
||||
return Err(FsError::Forbidden);
|
||||
}
|
||||
|
||||
@@ -712,7 +754,8 @@ impl DavFileSystem for CarrierFs {
|
||||
let node = inner.resolve_path(&from_str).ok_or(FsError::NotFound)?;
|
||||
|
||||
let (to_parent_path, to_name) = inner.split_parent_and_name(&to_str);
|
||||
if inner.anti_leak && is_leak_file(to_name) {
|
||||
if inner.is_leak(to_name) {
|
||||
inner.leak_counter.fetch_add(1, Ordering::Relaxed);
|
||||
return Err(FsError::Forbidden);
|
||||
}
|
||||
|
||||
@@ -776,7 +819,8 @@ impl DavFileSystem for CarrierFs {
|
||||
}
|
||||
|
||||
let (to_parent_path, to_name) = inner.split_parent_and_name(&to_str);
|
||||
if inner.anti_leak && is_leak_file(to_name) {
|
||||
if inner.is_leak(to_name) {
|
||||
inner.leak_counter.fetch_add(1, Ordering::Relaxed);
|
||||
return Err(FsError::Forbidden);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user