CH-J Server Managerpamamahala ng server sa pamamagitan ng SSH
Menu
Nailathalang source

CH-J Server Manager

I-browse ang mga direktoryo at file ng isang partikular na release ng application.

I-download ang source ZIP
CH-J / Server Manager 377 file
core-20261019T111616Z-160a00bfcddc Idinagdag: · Binuo:
mac.swift Idinagdag: Hindi naitala ang petsa 7.7 KB · 112 linya
Code I-download ang file
1import Foundation
2import Security
3import LocalAuthentication
4import CryptoKit
6struct Failure: Error { let code: String }
7// Legacy v1 Keychain service; kept only so "remove" can clean up old items.
8let service = "de.ch-j.servermanager.vault.biometry.v1"
9let wrapInfo = Data("CH-J Server Manager vault biometry v2".utf8)
10func fail(_ code: String) throws -> Never { throw Failure(code: code) }
11func laFailure(_ error: Error?) throws -> Never {
12 let code = (error as? LAError)?.code
13 if code == .userCancel || code == .appCancel || code == .systemCancel || code == .userFallback { try fail("BIOMETRIC_CANCELLED") }
14 if code == .biometryLockout || code == .biometryNotAvailable { try fail("BIOMETRIC_DEVICE_UNAVAILABLE") }
15 if code == .biometryNotEnrolled { try fail("BIOMETRIC_NO_ENROLLMENT") }
16 try fail("BIOMETRIC_FAILED")
18func authenticate(_ reason: String, _ context: LAContext = LAContext()) throws {
19 context.localizedFallbackTitle = "" // Master-password fallback is in the application.
20 let semaphore = DispatchSemaphore(value: 0)
21 var accepted = false
22 var failure: Error?
23 context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { ok, error in
24 accepted = ok; failure = error; semaphore.signal()
25 }
26 if semaphore.wait(timeout: .now() + 60) == .timedOut { context.invalidate(); try fail("BIOMETRIC_TIMEOUT") }
27 if !accepted { try laFailure(failure) }
29func keychainFailure(_ status: OSStatus) throws -> Never {
30 if status == errSecUserCanceled { try fail("BIOMETRIC_CANCELLED") }
31 if status == errSecItemNotFound { try fail("BIOMETRIC_ENROLLMENT_INVALIDATED") }
32 if status == errSecNotAvailable || status == errSecInteractionNotAllowed { try fail("BIOMETRIC_DEVICE_UNAVAILABLE") }
33 try fail("BIOMETRIC_CREDENTIAL_FAILED")
35// The vault key is sealed with a key derived from ECDH against a Secure Enclave
36// P-256 key bound to the current biometric set. The enclave key never leaves the
37// chip; its opaque dataRepresentation is usable only on this Mac's Secure Enclave.
38// Unlike Keychain items with access control, this needs no keychain-access-groups
39// entitlement, so it works for ad-hoc and Developer ID signed builds alike.
40func symmetricKey(_ secret: SharedSecret, _ entry: String) -> SymmetricKey {
41 secret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: Data(entry.utf8), sharedInfo: wrapInfo, outputByteCount: 32)
43func store(_ entry: String, _ key: Data) throws -> String {
44 guard SecureEnclave.isAvailable else { try fail("BIOMETRIC_UNAVAILABLE") }
45 var error: Unmanaged<CFError>?
46 guard let access = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, [.privateKeyUsage, .biometryCurrentSet], &error) else { try fail("BIOMETRIC_UNAVAILABLE") }
47 let enclaveKey: SecureEnclave.P256.KeyAgreement.PrivateKey
48 do { enclaveKey = try SecureEnclave.P256.KeyAgreement.PrivateKey(accessControl: access) } catch { try fail("BIOMETRIC_CREDENTIAL_FAILED") }
49 let ephemeral = P256.KeyAgreement.PrivateKey()
50 guard let secret = try? ephemeral.sharedSecretFromKeyAgreement(with: enclaveKey.publicKey),
51 let sealed = try? AES.GCM.seal(key, using: symmetricKey(secret, entry), authenticating: Data(entry.utf8)),
52 let box = sealed.combined else { try fail("BIOMETRIC_CREDENTIAL_FAILED") }
53 let payload: [String: Any] = ["v": 2, "se": enclaveKey.dataRepresentation.base64EncodedString(), "epk": ephemeral.publicKey.x963Representation.base64EncodedString(), "box": box.base64EncodedString()]
54 return try JSONSerialization.data(withJSONObject: payload).base64EncodedString()
56func retrieve(_ entry: String, _ wrapped: String, _ reason: String) throws -> Data {
57 guard let raw = Data(base64Encoded: wrapped), let payload = try? JSONSerialization.jsonObject(with: raw) as? [String: Any], payload["v"] as? Int == 2,
58 let se = (payload["se"] as? String).flatMap({ Data(base64Encoded: $0) }), let epk = (payload["epk"] as? String).flatMap({ Data(base64Encoded: $0) }),
59 let box = (payload["box"] as? String).flatMap({ Data(base64Encoded: $0) }) else { try fail("BIOMETRIC_ENROLLMENT_INVALIDATED") }
60 let context = LAContext()
61 context.touchIDAuthenticationAllowableReuseDuration = 0
62 try authenticate(reason, context) // Fresh Touch ID for every unlock; the context then authorizes the enclave key.
63 let enclaveKey: SecureEnclave.P256.KeyAgreement.PrivateKey
64 do { enclaveKey = try SecureEnclave.P256.KeyAgreement.PrivateKey(dataRepresentation: se, authenticationContext: context) }
65 catch { try fail("BIOMETRIC_ENROLLMENT_INVALIDATED") } // Biometric set changed or the key belongs to another Mac.
66 let secret: SharedSecret
67 do { secret = try enclaveKey.sharedSecretFromKeyAgreement(with: P256.KeyAgreement.PublicKey(x963Representation: epk)) }
68 catch { if error is LAError { try laFailure(error) }; try fail("BIOMETRIC_ENROLLMENT_INVALIDATED") }
69 guard let sealed = try? AES.GCM.SealedBox(combined: box), let key = try? AES.GCM.open(sealed, using: symmetricKey(secret, entry), authenticating: Data(entry.utf8)), key.count == 32 else { try fail("BIOMETRIC_INVALID_KEY") }
70 return key
72func run() throws -> [String: Any] {
73 let input = FileHandle.standardInput.readDataToEndOfFile()
74 guard input.count <= 16384, let request = try JSONSerialization.jsonObject(with: input) as? [String: Any], let op = request["op"] as? String else { try fail("BIOMETRIC_FAILED") }
75 let reason = request["reason"] as? String ?? "Unlock CH-J Server Manager"
76 if op == "status" {
77 let context = LAContext(); var error: NSError?
78 let available = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) && SecureEnclave.isAvailable
79 let code = available ? "BIOMETRIC_AVAILABLE" : error?.code == LAError.biometryNotEnrolled.rawValue ? "BIOMETRIC_NO_ENROLLMENT" : error?.code == LAError.biometryLockout.rawValue ? "BIOMETRIC_DEVICE_UNAVAILABLE" : "BIOMETRIC_UNAVAILABLE"
80 return ["ok": true, "available": available, "code": code]
81 }
82 if op == "authenticate" { try authenticate(reason); return ["ok": true] }
83 guard let entry = request["entryId"] as? String, entry.count == 64, entry.allSatisfy({ $0.isHexDigit && !$0.isUppercase }) else { try fail("BIOMETRIC_FAILED") }
84 if op == "remove" {
85 // v2 material lives only in the app's metadata file; delete any legacy v1 Keychain item.
86 let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: entry]
87 let status = SecItemDelete(query as CFDictionary)
88 if status != errSecSuccess && status != errSecItemNotFound { try keychainFailure(status) }
89 return ["ok": true]
90 }
91 if op == "store" {
92 guard let encoded = request["key"] as? String, var key = Data(base64Encoded: encoded), key.count == 32 else { try fail("BIOMETRIC_INVALID_KEY") }
93 defer { key.resetBytes(in: 0..<key.count) }
94 return ["ok": true, "wrapped": try store(entry, key)]
95 }
96 if op == "retrieve" {
97 guard let wrapped = request["wrapped"] as? String, wrapped.count <= 8192 else { try fail("BIOMETRIC_ENROLLMENT_INVALIDATED") }
98 var key = try retrieve(entry, wrapped, reason)
99 defer { key.resetBytes(in: 0..<key.count) }
100 return ["ok": true, "key": key.base64EncodedString()]
101 }
102 try fail("BIOMETRIC_FAILED")
104do {
105 let value = try run()
106 FileHandle.standardOutput.write(try JSONSerialization.data(withJSONObject: value)); exit(0)
107} catch {
108 let code = (error as? Failure)?.code ?? "BIOMETRIC_FAILED"
109 let result = ["ok": false, "code": code] as [String: Any]
110 if let data = try? JSONSerialization.data(withJSONObject: result) { FileHandle.standardOutput.write(data) }
111 exit(1)
SHA-25681d496480499ccd90ef37cfa536ba460092c4823a88ce7a0160cfc67e7e6d053

CH-J Proprietary Software License 1.14 · Ibinibigay ang source sa ilalim ng CH-J Proprietary Software License 1.14. Hindi binabago ng pagiging available nito ang mga tuntunin ng lisensya at hindi ito nagbibigay ng karagdagang karapatan.

SHA-256 ng archivea9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a
Mga file