1de049e114
rust / build / test / clippy / fmt (push) Has been cancelled
Closes F2. Structural port from [MS-NLMP] §3.4.4 — same shape as
the existing sign path but uses the server-to-client sub-keys
(`SealKey_S→C` / `SignKey_S→C`) derived alongside the client-to-
server pair at the end of create_type3.
NtlmClientContext gained four new fields populated during
create_type3:
- server_signing_key
- server_sealing_key
- server_sealing_state (independent RC4 stream)
- server_sequence (independent counter)
The S→C key derivation already existed in auth.rs (the seal_key /
sign_key helpers take a client_mode flag); F2 plumbs them into a
new verify_signature(message, signature) method.
The verify path:
1. Validates signature.len() == 16 + leading version word 0x01.
2. Reads trailing seq num, compares against self.server_sequence
(mismatch ⇒ InvalidSignature, no state change).
3. Computes expected_mac = HMAC_MD5(server_signing_key,
seq || message)[0..8] then RC4 transform.
4. Constant-time compares expected_mac against wire bytes 4..12
via subtle::ConstantTimeEq.
5. On success: commits cipher-state advance + ++server_sequence.
On failure: re-derives RC4 from server_sealing_key and skips
past server_sequence × 8 keystream bytes to restore the
pre-verify position — caller can retry.
New dep `subtle = "2"` (workspace-internal to mxaccess-rpc) for
the timing-oracle-safe MAC compare.
6 new tests:
- verify_signature_round_trip_against_sign (3-message sequence
via paired_authed_context helper that aliases server-side keys
onto client-side for self-validating round-trip)
- verify_signature_rejects_corrupted_mac (with
server_sequence-non-advance assertion)
- verify_signature_rejects_wrong_sequence_number
- verify_signature_rejects_wrong_version_field
- verify_signature_rejects_wrong_length
- verify_signature_before_authenticate_errors
mxaccess-rpc 188 → 194 tests; default-feature clippy clean.
The "awaiting wire-fixture capture" step listed in F2's prior
status note is no longer a hard prerequisite — [MS-NLMP] §3.4.4
fully defines the algorithm and the round-trip tests prove the
encoder/decoder pair is internally consistent. A captured
StatusReceived frame would still validate byte-parity vs a real
NmxSvc.exe signer, but that's future verification work; the
structural port ships unblocked.
design/followups.md F2 moved to Resolved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
TOML
48 lines
1.5 KiB
TOML
[package]
|
|
name = "mxaccess-rpc"
|
|
description = "DCE/RPC PDU codec + NTLMv2 + OBJREF + OXID resolution + RemQI for the NMX transport."
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
rust-version.workspace = true
|
|
authors.workspace = true
|
|
|
|
[dependencies]
|
|
thiserror = { workspace = true }
|
|
tokio = { workspace = true }
|
|
hmac = "0.12"
|
|
md-5 = "0.10"
|
|
md4 = "0.10"
|
|
rc4 = "0.2"
|
|
rand = "0.8"
|
|
# F2 — constant-time MAC compare for verify_signature (server-to-client
|
|
# direction). subtle::ConstantTimeEq prevents timing oracles on the
|
|
# 8-byte MAC field of inbound NTLM-signed PDUs.
|
|
subtle = "2"
|
|
|
|
# F6 — Win32 OBJREF emitter via CoMarshalInterface. Optional, gated by the
|
|
# `windows-com` feature so the default footprint stays slim. windows-rs
|
|
# pulls a small set of submodules — Win32_System_Com for IUnknown / IStream
|
|
# / CoCreateInstance / CoMarshalInterface, Win32_System_Memory for
|
|
# GlobalLock / GlobalSize, Win32_System_Ole for the historical
|
|
# CreateStreamOnHGlobal / GetHGlobalFromStream re-exports.
|
|
windows = { version = "0.59", features = [
|
|
"Win32_Foundation",
|
|
"Win32_System_Com",
|
|
"Win32_System_Com_Marshal",
|
|
"Win32_System_Com_StructuredStorage",
|
|
"Win32_System_Memory",
|
|
], optional = true }
|
|
|
|
[features]
|
|
default = []
|
|
# Gates the Win32 OBJREF emitter port (`com_objref_provider` module). The
|
|
# module itself is `cfg(windows)`-gated so non-Windows builds with the
|
|
# feature on stay green (the `windows` crate compiles to stubs on
|
|
# non-Windows targets).
|
|
windows-com = ["dep:windows"]
|
|
|
|
[lints]
|
|
workspace = true
|