-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathCodesignCheck.swift
More file actions
executable file
·111 lines (92 loc) · 4.54 KB
/
Copy pathCodesignCheck.swift
File metadata and controls
executable file
·111 lines (92 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
// CodesignCheck.swift
// SwiftPrivilegedHelperApplication
//
// Created by Erik Berglund on 2018-10-01.
// Copyright © 2018 Erik Berglund. All rights reserved.
//
import Foundation
import Security
let kSecCSDefaultFlags = 0
enum CodesignCheckError: Error {
case message(String)
}
struct CodesignCheck {
// MARK: -
// MARK: Compare Functions
public static func codeSigningMatches(pid: pid_t) throws -> Bool {
return try self.codeSigningCertificatesForSelf() == self.codeSigningCertificates(forPID: pid)
}
// MARK: -
// MARK: Public Functions
public static func codeSigningCertificatesForSelf() throws -> [SecCertificate] {
guard let secStaticCode = try secStaticCodeSelf() else { return [] }
return try codeSigningCertificates(forStaticCode: secStaticCode)
}
public static func codeSigningCertificates(forPID pid: pid_t) throws -> [SecCertificate] {
guard let secStaticCode = try secStaticCode(forPID: pid) else { return [] }
return try codeSigningCertificates(forStaticCode: secStaticCode)
}
public static func codeSigningCertificates(forURL url: URL) throws -> [SecCertificate] {
guard let secStaticCode = try secStaticCode(forURL: url) else { return [] }
return try codeSigningCertificates(forStaticCode: secStaticCode)
}
// MARK: -
// MARK: Private Functions
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(forURL url: URL) throws -> SecStaticCode? {
var secStaticCodePath: SecStaticCode?
try executeSecFunction { SecStaticCodeCreateWithPath(url as CFURL, [], &secStaticCodePath) }
guard let secStaticCode = secStaticCodePath else {
throw CodesignCheckError.message("SecStaticCode returned empty from SecStaticCodeCreateWithPath")
}
return secStaticCode
}
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
}
}