2 * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // Code - SecCode API objects
28 #include "StaticCode.h"
29 #include <Security/SecCodeHost.h>
32 #include <security_utilities/debugging.h>
33 #include <sys/codesign.h>
36 namespace CodeSigning
{
42 SecCode::SecCode(SecCode
*host
)
49 // Clean up a SecCode object
51 SecCode::~SecCode() throw()
57 // Yield the host Code
59 SecCode
*SecCode::host() const
66 // Yield the static code. This is cached.
67 // The caller does not own the object returned; it lives (at least) as long
68 // as the SecCode it was derived from.
70 SecStaticCode
*SecCode::staticCode()
73 mStaticCode
.take(this->getStaticCode());
74 secdebug("seccode", "%p got static=%p", this, mStaticCode
.get());
82 // By default, we have no guests
84 SecCode
*SecCode::locateGuest(CFDictionaryRef
)
91 // By default, we map ourselves to disk using our host's mapping facility.
92 // (This is currently only overridden in the root-of-trust (kernel) implementation.)
93 // The caller owns the object returned.
95 SecStaticCode
*SecCode::getStaticCode()
97 return host()->mapGuestToStatic(this);
102 // The default implementation cannot map guests to disk
104 SecStaticCode
*SecCode::mapGuestToStatic(SecCode
*guest
)
106 MacOSError::throwMe(errSecCSNoSuchCode
);
111 // Master validation function.
113 // This is the most important function in all of Code Signing. It performs
114 // dynamic validation on running code. Despite its simple structure, it does
115 // everything that's needed to establish whether a Code is currently valid...
116 // with a little help from StaticCode, format drivers, type drivers, and so on.
118 // This function validates internal requirements in the hosting chain. It does
119 // not validate external requirements - the caller needs to do that with a separate call.
121 static const uint8_t interim_hosting_default_requirement
[] = {
122 // anchor apple and (identifier com.apple.translate or identifier com.apple.LaunchCFMApp)
123 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
124 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13,
125 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c,
126 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x63, 0x6f, 0x6d, 0x2e,
127 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x43, 0x46, 0x4d, 0x41,
128 0x70, 0x70, 0x00, 0x00,
131 void SecCode::checkValidity(SecCSFlags flags
)
133 if (this->isRoot()) {
134 // the root-of-trust is valid by definition
135 secdebug("validator", "%p root of trust is presumed valid", this);
138 secdebug("validator", "%p begin validating %s",
139 this, this->staticCode()->mainExecutablePath().c_str());
142 // Do not reorder the operations below without thorough cogitation. There are
143 // interesting dependencies and significant performance issues.
145 // For the most part, failure of (secure) identity will cause exceptions to be
146 // thrown, and success is indicated by survival. If you make it to the end,
147 // you have won the validity race. (Good rat.)
150 // check my host first, recursively
151 this->host()->checkValidity(flags
);
153 SecStaticCode
*myDisk
= this->staticCode();
154 SecStaticCode
*hostDisk
= this->host()->staticCode();
156 // check my static state
157 myDisk
->validateDirectory();
159 // check my own dynamic state
160 if (!(this->host()->getGuestStatus(this) & CS_VALID
))
161 MacOSError::throwMe(errSecCSGuestInvalid
);
163 // check host/guest constraints
164 if (!this->host()->isRoot()) { // not hosted by root of trust
165 myDisk
->validateRequirements(kSecHostRequirementType
, hostDisk
, errSecCSHostReject
);
166 hostDisk
->validateRequirements(kSecGuestRequirementType
, myDisk
);
169 secdebug("validator", "%p validation successful", this);
174 // By default, we track no validity for guests (we don't have any)
176 uint32_t SecCode::getGuestStatus(SecCode
*guest
)
178 MacOSError::throwMe(errSecCSNoSuchCode
);
183 // Given a bag of attribute values, automagically come up with a SecCode
184 // without any other information.
185 // This is meant to be the "just do what makes sense" generic call, for callers
186 // who don't want to engage in the fascinating dance of manual guest enumeration.
188 // Note that we expect the logic embedded here to change over time (in backward
189 // compatible fashion, one hopes), and that it's all right to use heuristics here
190 // as long as it's done sensibly.
192 // Be warned that the present logic is quite a bit ad-hoc, and will likely not
193 // handle arbitrary combinations of proxy hosting, dynamic hosting, and dedicated
194 // hosting all that well.
196 SecCode
*SecCode::autoLocateGuest(CFDictionaryRef attributes
, SecCSFlags flags
)
198 // main logic: we need a pid, and we'll take a canonical guest id as an option
200 if (!cfscan(attributes
, "{%O=%d}", kSecGuestAttributePid
, &pid
))
201 CSError::throwMe(errSecCSUnsupportedGuestAttributes
, kSecCFErrorGuestAttributes
, attributes
);
202 if (SecCode
*process
=
203 KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%d}", kSecGuestAttributePid
, pid
))) {
204 SecPointer
<SecCode
> code
;
205 code
.take(process
); // locateGuest gave us a retained object
206 if (code
->staticCode()->flag(kSecCodeSignatureHost
)) {
207 // might be a code host. Let's find out
208 CFRef
<CFMutableDictionaryRef
> rest
= CFDictionaryCreateMutableCopy(NULL
, 0, attributes
);
209 CFDictionaryRemoveValue(rest
, kSecGuestAttributePid
);
210 if (SecCode
*guest
= code
->locateGuest(rest
))
213 if (!CFDictionaryGetValue(attributes
, kSecGuestAttributeCanonical
)) {
214 // only "soft" attributes, and no hosting is happening. Return the (non-)host itself
218 MacOSError::throwMe(errSecCSNoSuchCode
);
222 } // end namespace CodeSigning
223 } // end namespace Security