1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Windows ACL hardening for secret-bearing files and directories.
//!
//! On Unix the crate enforces tight `mode(0o600)` (files) /
//! `mode(0o700)` (directories) atomically at create-time via
//! `OpenOptionsExt` / `DirBuilderExt`. Windows has no equivalent
//! convenience; the caller must replace the file/directory's DACL
//! after creation. This module is the single canonical entry point
//! for that operation, used by:
//!
//! - [`unified_api::audit::FileAuditStorage`] when creating audit logs
//! - [`unified_api::atomic_write::AtomicWrite::secret_mode`] when
//! persisting secret-key files
//! - `latticearc-cli`'s `keygen` command when creating the output
//! directory
//!
//! All paths converge on a single SDDL string so the policy is
//! identical across call sites: protected DACL granting full access
//! to **three principals only** — the file owner (current user),
//! Built-in Administrators (`BA`), and `LocalSystem` (`SY`). No
//! inheritance from the parent directory; no entry for `Everyone`,
//! `Users`, or `Authenticated Users`. The function is named
//! [`set_local_admin_dacl`] (not "owner-only") to avoid promising
//! more than the policy delivers — the `BA` entry is necessary so
//! a local administrator can recover the file when the user account
//! is later disabled, matching the posture Windows applies to
//! per-user `%USERPROFILE%` files; the `SY` entry is necessary so
//! VSS / backup services that run as `SYSTEM` can read the file.
//!
//! The implementation is gated on `cfg(windows)`. On non-Windows
//! targets the entry points are present but compile to no-ops so the
//! call sites stay platform-agnostic.
use crateCoreError;
use crateResult;
use Path;
/// SDDL string applied to secret-bearing files and directories.
///
/// - `D:P` — protected DACL (no inheritance from parent).
/// - `OICI` — object-inherit + container-inherit so contents of a
/// directory inherit the same DACL.
/// - `FA` — file-all rights.
/// - `OW` — file owner (the current user, who created the file).
/// - `BA` — Built-in Administrators (so an admin can recover the
/// file even if the user account is later disabled — matches the
/// posture Windows applies to per-user `%USERPROFILE%` files).
/// - `SY` — `LocalSystem` (so backup / volume-shadow services
/// that run as `SYSTEM` can read the files; without this entry,
/// restic / VSS-based backups silently fail).
///
/// No `Everyone`, no `Users`, no `Authenticated Users` entry. A
/// second non-admin user on the same machine cannot read the file
/// even though the parent directory may grant them traversal.
const LOCAL_ADMIN_DACL_SDDL: &str = "D:P(A;OICI;FA;;;OW)(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)";
/// Apply the protected owner+admin+system DACL to a file or
/// directory at `path`. Three principals only (Owner / BA / SY).
///
/// On Windows: replaces the object's DACL with
/// [`LOCAL_ADMIN_DACL_SDDL`] via `SetNamedSecurityInfoW`. The DACL
/// is `protected` so it does not inherit any permissive ACEs from
/// the parent (e.g. a `Users:Read` entry on the user's profile root
/// would otherwise leak into a fresh secret file).
///
/// **Path-based API note:** `SetNamedSecurityInfoW` resolves `path`
/// at call time. Callers that have just created a file via
/// `OpenOptions::create_new(...).open(...)` and then immediately
/// invoke this helper close the TOCTOU window in practice (the
/// kernel inode is already published under the path; the only race
/// is rename-during-call which is fast). For higher-assurance call
/// sites the handle-based `SetSecurityInfo` would be marginally
/// safer; this is documented as a known residual path-API exposure.
///
/// On non-Windows: no-op. Unix call sites set `mode(0o600)` /
/// `mode(0o700)` atomically at create-time; this function is only
/// invoked on the Windows branch.
///
/// # Errors
///
/// Returns [`CoreError::Internal`] when the SDDL fails to parse
/// (programmer error — the constant is fixed) or when
/// `SetNamedSecurityInfoW` rejects the call (typical: target path
/// does not exist, or the calling process lacks `WRITE_DAC`).