ServerConfig parses https base URL and derives wss livekit URL; TokenClient POSTs /token with clean 503/offline error states; TLSPinning holds optional cert SHA-384 pins (empty = system trust); Settings gains a Connection test screen proving the endpoint works.
37 lines
1.5 KiB
Swift
37 lines
1.5 KiB
Swift
import Foundation
|
|
import CommonCrypto
|
|
import Security
|
|
|
|
/// ATS exception for the LAN host is declared in Info.plist. If the deployment
|
|
/// uses a self-signed certificate, pin its SHA-384 here (extract with:
|
|
/// `openssl s_client -connect 192.168.86.2:9178 </dev/null 2>/dev/null | openssl x509 -outform der | shasum -a 384`).
|
|
/// While empty, standard system trust is used (works for the current deployment).
|
|
enum TLSPinning {
|
|
static let pinnedCertSHA384: [String] = []
|
|
|
|
static func validate(_ trust: SecTrust) -> Bool {
|
|
guard !pinnedCertSHA384.isEmpty else { return true }
|
|
var error: CFError?
|
|
guard SecTrustEvaluateWithError(trust, &error) else { return false }
|
|
let count = SecTrustGetCertificateCount(trust)
|
|
guard count > 0 else { return false }
|
|
guard let chain = SecTrustCopyCertificateChain(trust) as? [SecCertificate] else {
|
|
return false
|
|
}
|
|
for cert in chain {
|
|
guard let derData = SecCertificateCopyData(cert) as Data? else { continue }
|
|
if pinnedCertSHA384.contains(sha384Hex(derData)) { return true }
|
|
}
|
|
return false
|
|
}
|
|
|
|
private static func sha384Hex(_ data: Data) -> String {
|
|
var hash = [UInt8](repeating: 0, count: Int(CC_SHA384_DIGEST_LENGTH))
|
|
data.withUnsafeBytes { buffer in
|
|
guard let base = buffer.baseAddress else { return }
|
|
CC_SHA384(base, CC_LONG(data.count), &hash)
|
|
}
|
|
return hash.map { String(format: "%02x", $0) }.joined()
|
|
}
|
|
}
|