diff --git a/SMC/Helper/Info.plist b/SMC/Helper/Info.plist index 7265bf1e..e64e4b39 100644 --- a/SMC/Helper/Info.plist +++ b/SMC/Helper/Info.plist @@ -7,11 +7,11 @@ CFBundleName eu.exelban.Stats.SMC.Helper CFBundleShortVersionString - 1.0.0 + 1.0.1 CFBundleVersion - 1 - CFBundleInfoDictionaryVersion - 6.0 + 2 + CFBundleInfoDictionaryVersion + 6.0 SMAuthorizedClients anchor apple generic and identifier "eu.exelban.Stats" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = RP2S87B72W) diff --git a/SMC/Helper/main.swift b/SMC/Helper/main.swift index d90dfdcf..d94fdef2 100644 --- a/SMC/Helper/main.swift +++ b/SMC/Helper/main.swift @@ -48,11 +48,22 @@ class Helper: NSObject, NSXPCListenerDelegate, HelperProtocol { } } - func listener(_ listener: NSXPCListener, shouldAcceptNewConnection connection: NSXPCConnection) -> Bool { - connection.exportedInterface = NSXPCInterface(with: HelperProtocol.self) - connection.exportedObject = self - connection.invalidationHandler = { - if let connectionIndex = self.connections.firstIndex(of: connection) { + func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { + do { + let isValid = try CodesignCheck.codeSigningMatches(pid: newConnection.processIdentifier) + if !isValid { + NSLog("invalid connection, dropping") + return false + } + } catch { + NSLog("error checking code signing: \(error)") + return false + } + + newConnection.exportedInterface = NSXPCInterface(with: HelperProtocol.self) + newConnection.exportedObject = self + newConnection.invalidationHandler = { + if let connectionIndex = self.connections.firstIndex(of: newConnection) { self.connections.remove(at: connectionIndex) } if self.connections.isEmpty { @@ -60,8 +71,8 @@ class Helper: NSObject, NSXPCListenerDelegate, HelperProtocol { } } - self.connections.append(connection) - connection.resume() + self.connections.append(newConnection) + newConnection.resume() return true } @@ -185,3 +196,81 @@ extension Helper { exit(0) } } + +// https://github.com/duanefields/VirtualKVM/blob/master/VirtualKVM/CodesignCheck.swift +let kSecCSDefaultFlags = 0 + +enum CodesignCheckError: Error { + case message(String) +} + +struct CodesignCheck { + public static func codeSigningMatches(pid: pid_t) throws -> Bool { + return try self.codeSigningCertificatesForSelf() == self.codeSigningCertificates(forPID: pid) + } + + private static func codeSigningCertificatesForSelf() throws -> [SecCertificate] { + guard let secStaticCode = try secStaticCodeSelf() else { return [] } + return try codeSigningCertificates(forStaticCode: secStaticCode) + } + + private static func codeSigningCertificates(forPID pid: pid_t) throws -> [SecCertificate] { + guard let secStaticCode = try secStaticCode(forPID: pid) else { return [] } + return try codeSigningCertificates(forStaticCode: secStaticCode) + } + + private static func executeSecFunction(_ secFunction: () -> (OSStatus) ) throws { + let osStatus = secFunction() + guard osStatus == errSecSuccess else { + throw CodesignCheckError.message(String(describing: SecCopyErrorMessageString(osStatus, nil))) + } + } + + private static func secStaticCodeSelf() throws -> SecStaticCode? { + var secCodeSelf: SecCode? + try executeSecFunction { SecCodeCopySelf(SecCSFlags(rawValue: 0), &secCodeSelf) } + guard let secCode = secCodeSelf else { + throw CodesignCheckError.message("SecCode returned empty from SecCodeCopySelf") + } + return try secStaticCode(forSecCode: secCode) + } + + private static func secStaticCode(forPID pid: pid_t) throws -> SecStaticCode? { + var secCodePID: SecCode? + try executeSecFunction { SecCodeCopyGuestWithAttributes(nil, [kSecGuestAttributePid: pid] as CFDictionary, [], &secCodePID) } + guard let secCode = secCodePID else { + throw CodesignCheckError.message("SecCode returned empty from SecCodeCopyGuestWithAttributes") + } + return try secStaticCode(forSecCode: secCode) + } + + private static func secStaticCode(forSecCode secCode: SecCode) throws -> SecStaticCode? { + var secStaticCodeCopy: SecStaticCode? + try executeSecFunction { SecCodeCopyStaticCode(secCode, [], &secStaticCodeCopy) } + guard let secStaticCode = secStaticCodeCopy else { + throw CodesignCheckError.message("SecStaticCode returned empty from SecCodeCopyStaticCode") + } + return secStaticCode + } + + private static func isValid(secStaticCode: SecStaticCode) throws { + try executeSecFunction { SecStaticCodeCheckValidity(secStaticCode, SecCSFlags(rawValue: kSecCSDoNotValidateResources | kSecCSCheckNestedCode), nil) } + } + + private static func secCodeInfo(forStaticCode secStaticCode: SecStaticCode) throws -> [String: Any]? { + try isValid(secStaticCode: secStaticCode) + var secCodeInfoCFDict: CFDictionary? + try executeSecFunction { SecCodeCopySigningInformation(secStaticCode, SecCSFlags(rawValue: kSecCSSigningInformation), &secCodeInfoCFDict) } + guard let secCodeInfo = secCodeInfoCFDict as? [String: Any] else { + throw CodesignCheckError.message("CFDictionary returned empty from SecCodeCopySigningInformation") + } + return secCodeInfo + } + + private static func codeSigningCertificates(forStaticCode secStaticCode: SecStaticCode) throws -> [SecCertificate] { + guard + let secCodeInfo = try secCodeInfo(forStaticCode: secStaticCode), + let secCertificates = secCodeInfo[kSecCodeInfoCertificates as String] as? [SecCertificate] else { return [] } + return secCertificates + } +} diff --git a/Stats.xcodeproj/xcshareddata/xcschemes/SMC.xcscheme b/Stats.xcodeproj/xcshareddata/xcschemes/SMC.xcscheme index acf91b28..8fb3609a 100644 --- a/Stats.xcodeproj/xcshareddata/xcschemes/SMC.xcscheme +++ b/Stats.xcodeproj/xcshareddata/xcschemes/SMC.xcscheme @@ -1,6 +1,6 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 639 + 640 Description Simple macOS system monitor in your menu bar LSApplicationCategoryType diff --git a/Widgets/Supporting Files/Info.plist b/Widgets/Supporting Files/Info.plist index e01c1cd8..2f0de2ec 100644 --- a/Widgets/Supporting Files/Info.plist +++ b/Widgets/Supporting Files/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 2.11.20 CFBundleVersion - 639 + 640 NSExtension NSExtensionPointIdentifier