2 * Copyright (c) 2002-2004 Apple Computer, 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@
24 #include <Security/SecTrustedApplicationPriv.h>
25 #include <security_keychain/TrustedApplication.h>
26 #include <security_keychain/Certificate.h>
27 #include <securityd_client/ssclient.h> // for code equivalence SPIs
29 #include "SecBridge.h"
33 static inline CssmData
cfData(CFDataRef data
)
35 return CssmData(const_cast<UInt8
*>(CFDataGetBytePtr(data
)),
36 CFDataGetLength(data
));
41 SecTrustedApplicationGetTypeID(void)
45 return gTypes().TrustedApplication
.typeID
;
47 END_SECAPI1(_kCFRuntimeNotATypeID
)
52 SecTrustedApplicationCreateFromPath(const char *path
, SecTrustedApplicationRef
*appRef
)
55 SecPointer
<TrustedApplication
> app
=
56 path
? new TrustedApplication(path
) : new TrustedApplication
;
57 Required(appRef
) = app
->handle();
61 OSStatus
SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef
,
65 const char *path
= TrustedApplication::required(appRef
)->path();
66 Required(dataRef
) = CFDataCreate(NULL
, (const UInt8
*)path
, strlen(path
) + 1);
70 OSStatus
SecTrustedApplicationSetData(SecTrustedApplicationRef appRef
,
74 secdebug("UNIMP", "legacy SecTrustedApplicationSetData not re-implemented");
75 // TrustedApplication::required(appRef)->data(cfData(dataRef));
81 SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef
, const char *path
)
84 TrustedApplication
&app
= *TrustedApplication::required(appRef
);
85 if (!app
.verifyToDisk(path
))
86 return CSSMERR_CSP_VERIFY_FAILED
;
92 // Convert from/to external data representation
94 OSStatus
SecTrustedApplicationCopyExternalRepresentation(
95 SecTrustedApplicationRef appRef
,
96 CFDataRef
*externalRef
)
99 TrustedApplication
&app
= *TrustedApplication::required(appRef
);
100 Required(externalRef
) = app
.externalForm();
104 OSStatus
SecTrustedApplicationCreateWithExternalRepresentation(
105 CFDataRef externalRef
,
106 SecTrustedApplicationRef
*appRef
)
109 Required(appRef
) = (new TrustedApplication(externalRef
))->handle();
115 SecTrustedApplicationMakeEquivalent(SecTrustedApplicationRef oldRef
,
116 SecTrustedApplicationRef newRef
, UInt32 flags
)
119 if (flags
& ~kSecApplicationValidFlags
)
121 SecurityServer::ClientSession
ss(Allocator::standard(), Allocator::standard());
122 TrustedApplication
*oldApp
= TrustedApplication::required(oldRef
);
123 TrustedApplication
*newApp
= TrustedApplication::required(newRef
);
124 ss
.addCodeEquivalence(oldApp
->legacyHash(), newApp
->legacyHash(), oldApp
->path(),
125 flags
& kSecApplicationFlagSystemwide
);
130 SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef
, UInt32 flags
)
133 if (flags
& ~kSecApplicationValidFlags
)
135 SecurityServer::ClientSession
ss(Allocator::standard(), Allocator::standard());
136 TrustedApplication
*app
= TrustedApplication::required(appRef
);
137 ss
.removeCodeEquivalence(app
->legacyHash(), app
->path(),
138 flags
& kSecApplicationFlagSystemwide
);
144 * Check to see if an application at a given path is a candidate for
145 * pre-emptive code equivalency establishment
148 SecTrustedApplicationIsUpdateCandidate(const char *installroot
, const char *path
)
154 size_t rootlen
= strlen(installroot
);
155 if (!strncmp(installroot
, path
, rootlen
))
156 path
+= rootlen
- 1; // keep the slash
159 // look up in database
160 static ModuleNexus
<PathDatabase
> paths
;
161 static ModuleNexus
<RecursiveMutex
> mutex
;
162 StLock
<Mutex
>_(mutex());
165 return CSSMERR_DL_RECORD_NOT_FOUND
; // whatever
171 * Point the system at another system root for equivalence use.
172 * This is for system update installers (only)!
175 SecTrustedApplicationUseAlternateSystem(const char *systemRoot
)
178 Required(systemRoot
);
179 SecurityServer::ClientSession
ss(Allocator::standard(), Allocator::standard());
180 ss
.setAlternateSystemRoot(systemRoot
);
186 * Gateway between traditional SecTrustedApplicationRefs and the Code Signing
187 * subsystem. Invisible to the naked eye, as of 10.5 (Leopard), these reference
188 * may contain Cod e Signing Requirement objects (SecRequirementRefs). For backward
189 * compatibility, these are handled implicitly at the SecAccess/SecACL layer.
190 * However, Those Who Know can bridge the gap for additional functionality.
192 OSStatus
SecTrustedApplicationCreateFromRequirement(const char *description
,
193 SecRequirementRef requirement
, SecTrustedApplicationRef
*appRef
)
196 if (description
== NULL
)
197 description
= "csreq://"; // default to "generic requirement"
198 SecPointer
<TrustedApplication
> app
= new TrustedApplication(description
, requirement
);
199 Required(appRef
) = app
->handle();
203 OSStatus
SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef
,
204 SecRequirementRef
*requirement
)
207 Required(requirement
) = TrustedApplication::required(appRef
)->requirement();
209 CFRetain(*requirement
);
215 * Create an application group reference.
217 OSStatus
SecTrustedApplicationCreateApplicationGroup(const char *groupName
,
218 SecCertificateRef anchor
, SecTrustedApplicationRef
*appRef
)
222 CFRef
<SecRequirementRef
> req
;
223 MacOSError::check(SecRequirementCreateGroup(CFTempString(groupName
), anchor
,
224 kSecCSDefaultFlags
, &req
.aref()));
225 string description
= string("group://") + groupName
;
227 Certificate
*cert
= Certificate::required(anchor
);
228 const CssmData
&hash
= cert
->publicKeyHash();
229 description
= description
+ "?cert=" + cfString(cert
->commonName())
230 + "&hash=" + hash
.toHex();
232 SecPointer
<TrustedApplication
> app
= new TrustedApplication(description
, req
);
233 Required(appRef
) = app
->handle();