2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // aclsupport.h - support for special Keychain style acls
23 #include <Security/osxsigning.h>
24 #include <Security/osxsigner.h>
25 #include <Security/trackingallocator.h>
26 #include "aclsupport.h"
27 #include "keychainacl.h"
30 using namespace CssmClient
;
33 // ---------------------------------------------------------------------------
34 // TrustedApplicationImpl
35 // ---------------------------------------------------------------------------
37 TrustedApplicationImpl::TrustedApplicationImpl(const CssmData
&signature
, const CssmData
&comment
, bool enabled
) :
38 mSignature(CssmAllocator::standard(), signature
),
39 mComment(CssmAllocator::standard(), comment
),
44 TrustedApplicationImpl::TrustedApplicationImpl(const char *path
, const CssmData
&comment
, bool enabled
) : mSignature(CssmAllocator::standard()),
45 mComment(CssmAllocator::standard(), comment
),
48 calcSignature(path
, mSignature
);
52 const CssmData
& TrustedApplicationImpl::signature() const
58 const CssmData
& TrustedApplicationImpl::comment() const
63 bool TrustedApplicationImpl::enabled() const
68 void TrustedApplicationImpl::enabled(bool enabled
)
73 bool TrustedApplicationImpl::sameSignature(const char *path
)
75 // return true if object at given path has same signature
76 CssmAutoData
otherSignature(CssmAllocator::standard());
77 calcSignature(path
, otherSignature
);
78 return (mSignature
.get() == otherSignature
);
81 void TrustedApplicationImpl::calcSignature(const char *path
, CssmOwnedData
&signature
)
83 // generate a signature for the given object
84 RefPointer
<CodeSigning::OSXCode
> objToVerify(CodeSigning::OSXCode::at(path
));
85 CodeSigning::OSXSigner signer
;
86 auto_ptr
<CodeSigning::OSXSigner::OSXSignature
> osxSignature(signer
.sign(*objToVerify
));
87 signature
.copy(osxSignature
->data(), osxSignature
->length());
90 // ---------------------------------------------------------------------------
92 // ---------------------------------------------------------------------------
94 TrustedApplication::TrustedApplication()
98 TrustedApplication::TrustedApplication(
99 const char *path
, const CssmData
&comment
, bool enabled
) :
100 RefPointer
<TrustedApplicationImpl
>(new TrustedApplicationImpl(path
, comment
, enabled
))
104 TrustedApplication::TrustedApplication(
105 const CssmData
&signature
, const CssmData
&comment
, bool enabled
) :
106 RefPointer
<TrustedApplicationImpl
>(new TrustedApplicationImpl(signature
, comment
, enabled
))
110 // ---------------------------------------------------------------------------
112 // ---------------------------------------------------------------------------
114 KeychainACL::KeychainACL(const Key
&key
) :
115 mLabel(CssmAllocator::standard()), mSelector(CssmAllocator::standard())
121 void KeychainACL::initialize()
124 mAlwaysAskUser
=false;
126 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector
127 = { CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
, 0 };
128 mSelector
.copy(&defaultSelector
, sizeof(defaultSelector
));
130 AutoAclEntryInfoList aclInfos
;
131 mKey
->getAcl(aclInfos
);
132 mHandle
= CSSM_INVALID_HANDLE
;
133 const AclEntryInfo
*theInfo
= NULL
;
134 for(uint32 entry
=0; entry
<aclInfos
.size(); entry
++)
136 const AclEntryInfo
&info
= aclInfos
[entry
];
137 const AuthorizationGroup
&authorizationGroup
=info
.proto().authorization();
138 for(uint32 auth
=0; auth
<authorizationGroup
.count(); auth
++)
140 if(authorizationGroup
[auth
]==CSSM_ACL_AUTHORIZATION_DECRYPT
|| authorizationGroup
[auth
]==CSSM_ACL_AUTHORIZATION_ANY
)
142 if (mHandle
!= CSSM_INVALID_HANDLE
&& mHandle
!= info
.handle())
148 mHandle
= info
.handle();
159 TypedList subject
=theInfo
->proto().subject();
160 assert(subject
.isProper());
161 const ListElement
*element
= subject
.first();
165 case CSSM_ACL_SUBJECT_TYPE_ANY
:
166 assert(element
->next() == NULL
);
170 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
:
172 assert(subject
.length() == 3);
173 mSelector
= subject
[1].data();
174 mLabel
= subject
[2].data();
177 case CSSM_ACL_SUBJECT_TYPE_THRESHOLD
:
185 // OK, it's a threshold acl
186 element
= element
->next();
187 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_WORDID
);
192 element
= element
->next();
193 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_WORDID
);
198 for (uint32 ix
= 0; ix
< n
; ++ix
)
200 element
= element
->next();
201 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_SUBLIST
);
202 const TypedList
&subList
= *element
;
203 assert(subList
.isProper());
204 const ListElement
*subElement
= subList
.first();
208 case CSSM_ACL_SUBJECT_TYPE_ANY
:
209 // Must be first subList in list.
210 assert(ix
== 0 && subElement
->next() == NULL
);
214 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
:
215 // Must be last subList in list.
218 assert(subList
.length() == 3);
219 mSelector
= subList
[1].data();
220 mLabel
= subList
[2].data();
224 case CSSM_ACL_SUBJECT_TYPE_COMMENT
:
225 case CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE
:
227 // when the app is disabled it is commented out.
228 if(*subElement
==CSSM_ACL_SUBJECT_TYPE_COMMENT
)
231 subElement
= subElement
->next();
233 subElement
= subElement
->next();
234 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_WORDID
);
235 uint32 sigType
= *subElement
;
236 subElement
= subElement
->next();
237 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_DATUM
);
238 const CssmData
&sig
= subElement
->data();
239 subElement
= subElement
->next();
240 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_DATUM
&& subElement
->next() == NULL
);
241 const CssmData
&comment
= subElement
->data();
242 // Only if sigType is CSSM_ACL_CODE_SIGNATURE_OSX this element is enabled.
243 // @@@ Otherwsie it should be CSSM_ACL_CODE_SIGNATURE_NONE (which is not defined yet).
244 // additionally the enabled flag must be respected.
245 push_back(TrustedApplication(sig
, comment
, (sigType
== CSSM_ACL_CODE_SIGNATURE_OSX
) && isEnabled
));
255 // Since we looked at N values we should be done.
256 assert(element
->next() == NULL
);
259 void KeychainACL::commit()
261 TrackingAllocator
allocator(CssmAllocator::standard());
263 // hhs replaced with new aclFactory
264 AclFactory aclFactory
;
266 CssmList
&list
= *new(allocator
) CssmList();
268 list
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_THRESHOLD
));
269 list
.append(new(allocator
) ListElement(1));
270 list
.append(new(allocator
) ListElement(size()+mAnyAllow
+mAlwaysAskUser
));
274 CssmList
&sublist
= *new(allocator
) CssmList();
275 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_ANY
));
276 list
.append(new(allocator
) ListElement(sublist
));
280 for (uint32 ix
= 0; ix
< size(); ++ix
)
282 TrustedApplication app
= at(ix
);
283 CssmList
&sublist
= *new(allocator
) CssmList();
284 if(!app
->enabled()) sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT
));
285 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE
));
286 sublist
.append(new(allocator
) ListElement(CSSM_ACL_CODE_SIGNATURE_OSX
));
287 sublist
.append(new(allocator
) ListElement(app
->signature()));
288 sublist
.append(new(allocator
) ListElement(app
->comment()));
289 list
.append(new(allocator
) ListElement(sublist
));
294 CssmList
&sublist
= *new(allocator
) CssmList();
295 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
));
296 sublist
.append(new(allocator
) ListElement(mSelector
.get()));
297 sublist
.append(new(allocator
) ListElement(mLabel
.get()));
298 list
.append(new(allocator
) ListElement(sublist
));
301 AclEntryPrototype
aclEntry(list
);
302 // @@@ @@@ Force "decrypt" authorization for now -- should take this from input!! @@@
303 AuthorizationGroup
&anyDecryptAuthGroup
= aclEntry
.authorization();
304 CSSM_ACL_AUTHORIZATION_TAG decryptTag
= CSSM_ACL_AUTHORIZATION_DECRYPT
;
305 anyDecryptAuthGroup
.NumberOfAuthTags
= 1;
306 anyDecryptAuthGroup
.AuthTags
= &decryptTag
;
307 const AccessCredentials
*promptCred
= aclFactory
.promptCred ();
308 AclEdit
edit(mHandle
, aclEntry
);
309 mKey
->changeAcl(edit
, promptCred
);
312 void KeychainACL::anyAllow(bool allow
)
317 bool KeychainACL::anyAllow() const
322 void KeychainACL::alwaysAskUser(bool ask
)
327 bool KeychainACL::alwaysAskUser() const
329 return mAlwaysAskUser
;
332 bool KeychainACL::isCustomACL() const
337 void KeychainACL::label(const CssmData
&label
)