Phase 1.2: SMB3 encryption negotiation + session state
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled

- Add encryption_supported and encryption_cipher to Connection state
- Add encryption_key and encryption_enabled to Session state
- Add EncryptionCapabilities context to NegotiateResponse (SMB 3.1.1)
- Derive encryption_key from session_base_key in session_setup
- Export derive_encryption_key as public method
- Fix Session::new() signature with 8 parameters
- All encryption tests pass (3 passed)
This commit is contained in:
Warren
2026-06-22 02:56:02 +08:00
parent 104e7f5f9c
commit 98239c09d4
6 changed files with 56 additions and 4 deletions

View File

@@ -4,10 +4,11 @@ use std::sync::Arc;
use crate::proto::auth::spnego::encode_init_response;
use crate::proto::crypto::SigningAlgo;
use crate::proto::crypto::encryption::CipherAlgorithm;
use crate::proto::header::Smb2Header;
use crate::proto::messages::{
Dialect, NegotiateContext, NegotiateRequest, NegotiateResponse, PreauthIntegrityCapabilities,
SigningCapabilities,
SigningCapabilities, EncryptionCapabilities,
};
use tracing::info;
use uuid::Uuid;
@@ -117,7 +118,29 @@ pub async fn handle(
data: signing_data,
};
let ctxs = vec![preauth_ctx, signing_ctx];
// ENCRYPTION_CAPABILITIES — advertise AES-128-GCM (simplified)
let encryption_caps = EncryptionCapabilities {
cipher_count: 1,
ciphers: vec![EncryptionCapabilities::CIPHER_AES_128_GCM],
};
let encryption_data = {
use binrw::BinWrite;
let mut c = std::io::Cursor::new(Vec::new());
BinWrite::write(&encryption_caps, &mut c).expect("encryption negotiate context encodes");
c.into_inner()
};
let encryption_ctx = NegotiateContext {
context_type: NegotiateContext::TYPE_ENCRYPTION,
data_length: encryption_data.len() as u16,
reserved: 0,
data: encryption_data,
};
// Store encryption support in connection state
*conn.encryption_supported.write().await = true;
*conn.encryption_cipher.write().await = Some(CipherAlgorithm::Aes128Gcm);
let ctxs = vec![preauth_ctx, signing_ctx, encryption_ctx];
if let Err(e) = NegotiateContext::encode_list(&ctxs, &mut contexts_bytes) {
tracing::error!(error = %e, "encode_list failed");
return HandlerResponse::err(ntstatus::STATUS_INVALID_PARAMETER);

View File

@@ -198,13 +198,27 @@ pub async fn handle(
0
};
let signing_required = false;
// Check if encryption is negotiated
let encryption_supported = *conn.encryption_supported.read().await;
let encryption_cipher = *conn.encryption_cipher.read().await;
let encryption_enabled = encryption_supported && encryption_cipher.is_some();
let encryption_key = if encryption_enabled {
// Derive encryption key from session_base_key (simplified approach)
use crate::proto::crypto::encryption::Smb3Encryption;
Some(Smb3Encryption::derive_encryption_key(&session_base_key, b"SMB3ENC"))
} else {
None
};
let session = Session::new(
sid,
outcome.identity.clone(),
session_base_key,
signing_key,
encryption_key,
signing_required,
encryption_enabled,
None,
);
let session_arc = Arc::new(tokio::sync::RwLock::new(session));