From d093d9662e19919aac96256f7b6c908693e6cbca Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Thu, 27 Apr 2023 00:10:59 +0300 Subject: [PATCH] Parsing quarantine info --- reSign.xcodeproj/project.pbxproj | 4 ++++ reSign/AppPackage.swift | 18 +++++++++-------- reSign/Quarantine.swift | 33 +++++++++++++++++++++++++++++++ reSign/Views/SignInfoView.swift | 34 +++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 reSign/Quarantine.swift diff --git a/reSign.xcodeproj/project.pbxproj b/reSign.xcodeproj/project.pbxproj index da6b554..b9a0ca4 100644 --- a/reSign.xcodeproj/project.pbxproj +++ b/reSign.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 7AF0C51A29EF43C2008D4084 /* OutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C51929EF43C2008D4084 /* OutlineView.swift */; }; 7AF0C51C29EF43CD008D4084 /* TreeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C51B29EF43CD008D4084 /* TreeItem.swift */; }; 7AF0C53B29F72151008D4084 /* PlistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C53A29F72151008D4084 /* PlistView.swift */; }; + 7AF0C53D29F9B7FE008D4084 /* Quarantine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C53C29F9B7FE008D4084 /* Quarantine.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -36,6 +37,7 @@ 7AF0C51929EF43C2008D4084 /* OutlineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineView.swift; sourceTree = ""; }; 7AF0C51B29EF43CD008D4084 /* TreeItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeItem.swift; sourceTree = ""; }; 7AF0C53A29F72151008D4084 /* PlistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlistView.swift; sourceTree = ""; }; + 7AF0C53C29F9B7FE008D4084 /* Quarantine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Quarantine.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,6 +96,7 @@ 7A72231429DCABE400503F78 /* ContentView.swift */, 7A064BEA29DF5BB800C5D978 /* AppPackage.swift */, 7A064BEC29E2C91D00C5D978 /* Certificate.swift */, + 7AF0C53C29F9B7FE008D4084 /* Quarantine.swift */, 7A72231629DCABE500503F78 /* Assets.xcassets */, 7A72231B29DCABE500503F78 /* reSign.entitlements */, 7A72231829DCABE500503F78 /* Preview Content */, @@ -195,6 +198,7 @@ 7A064BE929DE18C700C5D978 /* SignInfoView.swift in Sources */, 7A064BED29E2C91D00C5D978 /* Certificate.swift in Sources */, 7A72231329DCABE400503F78 /* reSignApp.swift in Sources */, + 7AF0C53D29F9B7FE008D4084 /* Quarantine.swift in Sources */, 7A064BE429DE107000C5D978 /* Category.swift in Sources */, 7AF0C51A29EF43C2008D4084 /* OutlineView.swift in Sources */, ); diff --git a/reSign/AppPackage.swift b/reSign/AppPackage.swift index de0bafe..c8cb24e 100644 --- a/reSign/AppPackage.swift +++ b/reSign/AppPackage.swift @@ -48,6 +48,7 @@ class AppPackage { var certificates: [Certificate]? var infoPlist: [String: Any] = [:] var entitlements: [String: Any] = [:] + var quarantine: Quarantine? init(url: URL) { @@ -74,25 +75,24 @@ class AppPackage { func getAppInfo() throws { - let pStaticCode: UnsafeMutablePointer = .allocate(capacity: 1) - defer { pStaticCode.deallocate() } - var status = SecStaticCodeCreateWithPath(url as CFURL, [], pStaticCode) + var staticCode: SecStaticCode? = nil + var status = SecStaticCodeCreateWithPath(url as CFURL, [], &staticCode) try checkResult(status) - guard let staticCode = pStaticCode.pointee else { + guard let staticCode else { throw SecError.staticCodeNil } - let pSigningInfo: UnsafeMutablePointer = .allocate(capacity: 1) - defer { pSigningInfo.deallocate() } + var signingInfo: CFDictionary? let signInfoFlags: SecCSFlags = [ SecCSFlags(rawValue: kSecCSRequirementInformation), SecCSFlags(rawValue: kSecCSSigningInformation), ] - status = SecCodeCopySigningInformation(staticCode, signInfoFlags, pSigningInfo) + + status = SecCodeCopySigningInformation(staticCode, signInfoFlags, &signingInfo) try checkResult(status) - if let signingInfo = pSigningInfo.pointee as? [String: Any] { + if let signingInfo = signingInfo as? [String: Any] { bundleId = signingInfo[kSecCodeInfoIdentifier as String] as? String mainExecutable = (signingInfo[kSecCodeInfoMainExecutable as String] as? URL)?.path() @@ -110,6 +110,8 @@ class AppPackage { infoPlist = signingInfo[kSecCodeInfoPList as String] as? [String: Any] ?? [:] entitlements = signingInfo[kSecCodeInfoEntitlementsDict as String] as? [String: Any] ?? [:] } + + quarantine = Quarantine(url: url) } func getDigestAlgorithm(from dict: [String: Any]) -> String? { diff --git a/reSign/Quarantine.swift b/reSign/Quarantine.swift new file mode 100644 index 0000000..b2da72d --- /dev/null +++ b/reSign/Quarantine.swift @@ -0,0 +1,33 @@ +// +// Quarantine.swift +// reSign +// +// Created by Мустафаев Селим Мустафаевич on 26.04.2023. +// + +import Foundation + +class Quarantine { + + var flags: Int + var date: Date + var agent: String + var uuid: String + + init?(url: URL) { + guard let data = try? url.extendedAttribute(forName: "com.apple.quarantine"), + let stringData = String(data: data, encoding: .utf8) + else { + return nil + } + + let parts = stringData.split(separator: ";") + + self.flags = Int(parts[0]) ?? 0 + self.date = Date(timeIntervalSince1970: TimeInterval(UInt32(parts[1], radix: 16) ?? 0)) + self.agent = String(parts[2]) + self.uuid = String(parts[3]) + + print(parts) + } +} diff --git a/reSign/Views/SignInfoView.swift b/reSign/Views/SignInfoView.swift index 299e5af..e2f9ae9 100644 --- a/reSign/Views/SignInfoView.swift +++ b/reSign/Views/SignInfoView.swift @@ -51,6 +51,21 @@ struct FormTextItem: View { } } +struct FormToggleItem: View { + + let name: String + let value: Bool + + var body: some View { + HStack { + Text(name) + Spacer() + Toggle("", isOn: .constant(value)) + .disabled(true) + } + } +} + struct SignInfoView: View { let appPackage: AppPackage @@ -58,18 +73,31 @@ struct SignInfoView: View { var body: some View { Form { Section(header: Text("General info")) { - FormTextItem(name: "Main executable path", value: appPackage.mainExecutable) + FormTextItem(name: "Bundle ID", value: appPackage.bundleId) + FormTextItem(name: "Team ID", value: appPackage.teamId) + FormToggleItem(name: "Quarantine", value: appPackage.quarantine != nil) + } + + Section(header: Text("Details")) { FormTextItem(name: "Format", value: appPackage.format) + FormTextItem(name: "Main executable path", value: appPackage.mainExecutable) FormTextItem(name: "Code signature source", value: appPackage.source) FormTextItem(name: "Runtime version", value: appPackage.runtimeVersion) FormTextItem(name: "Flags", array: appPackage.flags) FormTextItem(name: "Digest algorithm", value: appPackage.digestAlgorithm) - FormTextItem(name: "Bundle ID", value: appPackage.bundleId) - FormTextItem(name: "Team ID", value: appPackage.teamId) FormTextItem(name: "Signing date", date: appPackage.signingDate) FormTextItem(name: "Signing date (actual)", date: appPackage.signingDateActual) } + if let quarantine = appPackage.quarantine { + Section("Quarantine") { + FormTextItem(name: "Flags", value: quarantine.flags) + FormTextItem(name: "Date", date: quarantine.date) + FormTextItem(name: "Agent", value: quarantine.agent) + FormTextItem(name: "UUID", value: quarantine.uuid) + } + } + Section(header: Text("Requirements")) { FormTextItem(name: "Designated requirements", value: appPackage.designatedRequirements) FormTextItem(name: "Implicit requirements", value: appPackage.implicitRequirements)