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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
base / mac / code_signature.cc [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/mac/code_signature.h"
#include "base/apple/osstatus_logging.h"
#include "base/apple/scoped_cftyperef.h"
#include "base/mac/info_plist_data.h"
#include "base/strings/sys_string_conversions.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
using base::apple::ScopedCFTypeRef;
namespace base::mac {
namespace {
// Return a dictionary of attributes suitable for looking up `process` with
// `SecCodeCopyGuestWithAttributes`.
ScopedCFTypeRef<CFDictionaryRef> AttributesForGuestValidation(
absl::variant<audit_token_t, pid_t> process,
SignatureValidationType validation_type,
std::string_view info_plist_xml) {
ScopedCFTypeRef<CFMutableDictionaryRef> attributes(
CFDictionaryCreateMutable(nullptr, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
if (audit_token_t* token = absl::get_if<audit_token_t>(&process)) {
ScopedCFTypeRef<CFDataRef> audit_token_cf(CFDataCreate(
nullptr, reinterpret_cast<const UInt8*>(token), sizeof(audit_token_t)));
CFDictionarySetValue(attributes.get(), kSecGuestAttributeAudit,
audit_token_cf.get());
} else {
CHECK(absl::holds_alternative<pid_t>(process));
ScopedCFTypeRef<CFNumberRef> pid_cf(
CFNumberCreate(nullptr, kCFNumberIntType, &absl::get<pid_t>(process)));
CFDictionarySetValue(attributes.get(), kSecGuestAttributePid, pid_cf.get());
}
if (validation_type == SignatureValidationType::DynamicOnly) {
ScopedCFTypeRef<CFDataRef> info_plist(CFDataCreate(
nullptr, reinterpret_cast<const UInt8*>(info_plist_xml.data()),
static_cast<CFIndex>(info_plist_xml.length())));
CFDictionarySetValue(attributes.get(), kSecGuestAttributeDynamicCode,
kCFBooleanTrue);
CFDictionarySetValue(attributes.get(),
kSecGuestAttributeDynamicCodeInfoPlist,
info_plist.get());
}
return attributes;
}
OSStatus ValidateGuestWithAttributes(CFDictionaryRef attributes,
SecRequirementRef requirement) {
ScopedCFTypeRef<SecCodeRef> code;
OSStatus status = SecCodeCopyGuestWithAttributes(
nullptr, attributes, kSecCSDefaultFlags, code.InitializeInto());
if (status != errSecSuccess) {
OSSTATUS_LOG(ERROR, status) << "SecCodeCopyGuestWithAttributes";
return status;
}
return SecCodeCheckValidity(code.get(), kSecCSDefaultFlags, requirement);
}
} // namespace
OSStatus ProcessIsSignedAndFulfillsRequirement(
audit_token_t audit_token,
SecRequirementRef requirement,
SignatureValidationType validation_type,
std::string_view info_plist_xml) {
ScopedCFTypeRef<CFDictionaryRef> attributes = AttributesForGuestValidation(
audit_token, validation_type, info_plist_xml);
return ValidateGuestWithAttributes(attributes.get(), requirement);
}
OSStatus ProcessIdIsSignedAndFulfillsRequirement_DoNotUse(
pid_t pid,
SecRequirementRef requirement,
SignatureValidationType validation_type,
std::string_view info_plist_xml) {
ScopedCFTypeRef<CFDictionaryRef> attributes =
AttributesForGuestValidation(pid, validation_type, info_plist_xml);
return ValidateGuestWithAttributes(attributes.get(), requirement);
}
ScopedCFTypeRef<SecRequirementRef> RequirementFromString(
std::string_view requirement_string) {
ScopedCFTypeRef<CFStringRef> requirement_string_cf(
base::SysUTF8ToCFStringRef(requirement_string));
ScopedCFTypeRef<SecRequirementRef> requirement;
OSStatus status = SecRequirementCreateWithString(
requirement_string_cf.get(), kSecCSDefaultFlags,
requirement.InitializeInto());
if (status != errSecSuccess) {
OSSTATUS_LOG(ERROR, status)
<< "SecRequirementCreateWithString: " << requirement_string;
return base::apple::ScopedCFTypeRef<SecRequirementRef>(nullptr);
}
return requirement;
}
base::expected<ScopedCFTypeRef<SecCodeRef>, OSStatus>
DynamicCodeObjectForCurrentProcess() {
std::vector<uint8_t> info_plist_xml = OuterBundleCachedInfoPlistData();
ScopedCFTypeRef<CFDictionaryRef> attributes = AttributesForGuestValidation(
getpid(), SignatureValidationType::DynamicOnly,
base::as_string_view(info_plist_xml));
ScopedCFTypeRef<SecCodeRef> code;
OSStatus status = SecCodeCopyGuestWithAttributes(
nullptr, attributes.get(), kSecCSDefaultFlags, code.InitializeInto());
if (status != errSecSuccess) {
OSSTATUS_LOG(ERROR, status) << "SecCodeCopyGuestWithAttributes";
return base::unexpected(status);
}
return code;
}
} // namespace base::mac