Implement SMB 3.x Lease support Phase 3
- CREATE handler parse RqLs create context - Extract LeaseKey (16 bytes) + LeaseState (4 bytes) - Check can_grant() before registration - Register with LeaseManager - Set Open.lease_key/lease_state fields All 229 tests pass.
This commit is contained in:
54
vendor/smb-server/src/handlers/create.rs
vendored
54
vendor/smb-server/src/handlers/create.rs
vendored
@@ -182,6 +182,49 @@ pub async fn handle(
|
|||||||
}).await;
|
}).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 3: Check for lease request in create contexts (SMB 3.x)
|
||||||
|
let (lease_key, lease_state) = if !req.create_contexts.is_empty() {
|
||||||
|
use crate::proto::messages::CreateContext;
|
||||||
|
let contexts = CreateContext::parse_chain(&req.create_contexts).unwrap_or_default();
|
||||||
|
|
||||||
|
// Find RqLs (REQUEST_LEASE) context
|
||||||
|
let lease_ctx = contexts.iter().find(|ctx| ctx.name == CreateContext::NAME_RQLS);
|
||||||
|
|
||||||
|
if let Some(ctx) = lease_ctx {
|
||||||
|
// Parse lease request (MS-SMB2 §2.2.13.2)
|
||||||
|
// Data format: LeaseKey (16 bytes) + LeaseState (4 bytes) + LeaseFlags (4 bytes)
|
||||||
|
if ctx.data.len() >= 24 {
|
||||||
|
let lease_key_bytes: [u8; 16] = ctx.data[0..16].try_into().unwrap_or([0; 16]);
|
||||||
|
let lease_state = u32::from_le_bytes([ctx.data[16], ctx.data[17], ctx.data[18], ctx.data[19]]);
|
||||||
|
|
||||||
|
// Check if lease can be granted
|
||||||
|
if server.lease_manager.can_grant(lease_state).await {
|
||||||
|
// Register lease
|
||||||
|
use crate::oplock::LeaseEntry;
|
||||||
|
server.lease_manager.register(LeaseEntry {
|
||||||
|
lease_key: lease_key_bytes,
|
||||||
|
lease_state,
|
||||||
|
lease_flags: 0,
|
||||||
|
file_id,
|
||||||
|
path: path.clone(),
|
||||||
|
session_id: hdr.session_id,
|
||||||
|
tree_id: tree.id,
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
(Some(lease_key_bytes), Some(lease_state))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
let open = Open::new(
|
let open = Open::new(
|
||||||
file_id,
|
file_id,
|
||||||
handle,
|
handle,
|
||||||
@@ -192,8 +235,17 @@ pub async fn handle(
|
|||||||
granted_oplock, // oplock_level
|
granted_oplock, // oplock_level
|
||||||
req.share_access, // share_access
|
req.share_access, // share_access
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Phase 3: Set lease fields if granted
|
||||||
let open_arc = Arc::new(tokio::sync::RwLock::new(open));
|
let open_arc = Arc::new(tokio::sync::RwLock::new(open));
|
||||||
tree.opens.write().await.insert(file_id, open_arc);
|
if lease_key.is_some() {
|
||||||
|
let mut open_mut = open_arc.write().await;
|
||||||
|
open_mut.lease_key = lease_key;
|
||||||
|
open_mut.lease_state = lease_state;
|
||||||
|
open_mut.lease_flags = Some(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.opens.write().await.insert(file_id, open_arc.clone());
|
||||||
drop(tree);
|
drop(tree);
|
||||||
|
|
||||||
let create_action = match intent {
|
let create_action = match intent {
|
||||||
|
|||||||
Reference in New Issue
Block a user