Remove self-signed TLS option (system trust only); add session changelog
Parity with the Android client: drop the "Allow self-signed certificate" escape hatch. The app now performs system TLS trust only — a self-signed appliance must have its CA installed on the device (MDM/profile). A code-only public-key pinning policy remains (no UI). - ServerTrustEvaluator: remove ServerTrustPolicy.allowSelfSignedForHost and its challenge handler; keep .system (default) and .pinPublicKeySHA256. - SettingsView: remove the self-signed toggle/state/prefill; makeConfig uses the default .system policy. - MCMSConnection / APIConfiguration: update usage-sketch + doc comments. - README / GUI-NOTES / MCMS_API.md: document system-trust-only; self-signed boxes need their CA installed on the device. - Add CHANGELOG.md for this session, flagged for the Android port. Note: configs previously persisted with the self-signed policy fail to decode and reset to defaults (one-time re-entry of the server URL). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d8f1c7b2d
commit
6bb65d2aa3
8 changed files with 142 additions and 70 deletions
|
|
@ -4,22 +4,18 @@ import CryptoKit
|
|||
|
||||
/// How to evaluate the server's TLS certificate.
|
||||
///
|
||||
/// MCMS appliances usually present a self-signed or internal-CA certificate.
|
||||
/// Pick the *narrowest* policy that works for your deployment. Never ship
|
||||
/// `.allowSelfSignedForHost` against a host you don't control.
|
||||
/// The appliance must present a CA-trusted certificate — a real cert, or an
|
||||
/// internal CA installed on the device via MDM/configuration profile. There is
|
||||
/// deliberately NO "accept self-signed" escape hatch: the app never bypasses
|
||||
/// trust evaluation (parity with the Android client).
|
||||
enum ServerTrustPolicy: Equatable, Codable {
|
||||
/// Default OS trust evaluation (use this if the box has a real cert or a
|
||||
/// CA your devices already trust via MDM/profile — strongly preferred).
|
||||
/// Default OS trust evaluation. The default policy and the only one the UI
|
||||
/// produces.
|
||||
case system
|
||||
|
||||
/// Accept the server's certificate ONLY for this exact host, after a normal
|
||||
/// trust evaluation that ignores the "untrusted root" failure. Scoped escape
|
||||
/// hatch for self-signed boxes on a controlled mgmt network/VPN.
|
||||
case allowSelfSignedForHost(String)
|
||||
|
||||
/// Certificate/public-key pinning: trust only if the leaf's SHA-256
|
||||
/// public-key hash (base64) matches one of these. The safest option for a
|
||||
/// fixed appliance — capture the hash once and pin it.
|
||||
/// SubjectPublicKeyInfo hash (base64) matches one of these. Code-only (no UI);
|
||||
/// the strictest option for a fixed appliance — capture the hash once and pin it.
|
||||
case pinPublicKeySHA256([String], host: String)
|
||||
}
|
||||
|
||||
|
|
@ -49,19 +45,6 @@ final class ServerTrustEvaluator: NSObject, URLSessionDelegate {
|
|||
case .system:
|
||||
completionHandler(.performDefaultHandling, nil)
|
||||
|
||||
case .allowSelfSignedForHost(let allowedHost):
|
||||
// Scoped escape hatch for self-signed appliances on a controlled
|
||||
// network. Because a self-signed root fails normal evaluation, this
|
||||
// accepts ANY certificate the allowed host presents — including
|
||||
// expired or name-mismatched ones. The only gate is the hostname, so
|
||||
// use this only on hosts you control; prefer `.pinPublicKeySHA256`
|
||||
// once you can capture the appliance's key hash.
|
||||
guard host == allowedHost else {
|
||||
completionHandler(.cancelAuthenticationChallenge, nil)
|
||||
return
|
||||
}
|
||||
completionHandler(.useCredential, URLCredential(trust: trust))
|
||||
|
||||
case .pinPublicKeySHA256(let pins, let pinnedHost):
|
||||
guard host == pinnedHost,
|
||||
let leaf = Self.leafCertificate(from: trust),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue