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 "aclsupport.h"
26 #include "keychainacl.h"
29 using namespace CssmClient
;
32 // ---------------------------------------------------------------------------
33 // TrustedApplicationImpl
34 // ---------------------------------------------------------------------------
36 TrustedApplicationImpl::TrustedApplicationImpl(const CssmData
&signature
, const CssmData
&comment
, bool enabled
) :
37 mSignature(CssmAllocator::standard(), signature
),
38 mComment(CssmAllocator::standard(), comment
),
43 TrustedApplicationImpl::TrustedApplicationImpl(const char *path
, const CssmData
&comment
, bool enabled
) : mSignature(CssmAllocator::standard(), calcSignature(path
)),
44 mComment(CssmAllocator::standard(), comment
),
50 const CssmData
& TrustedApplicationImpl::signature() const
56 const CssmData
& TrustedApplicationImpl::comment() const
61 bool TrustedApplicationImpl::enabled() const
66 void TrustedApplicationImpl::enabled(bool enabled
)
71 bool TrustedApplicationImpl::sameSignature(const char *path
)
73 // return true if object at given path has same signature
74 return (mSignature
.get() == calcSignature(path
).get());
77 CssmAutoData
TrustedApplicationImpl::calcSignature(const char *path
)
79 // generate a signature for the given object
80 auto_ptr
<CodeSigning::OSXCode
> objToVerify(CodeSigning::OSXCode::at(path
));
81 CodeSigning::OSXSigner signer
;
82 auto_ptr
<CodeSigning::OSXSigner::OSXSignature
> signature(signer
.sign(*objToVerify
));
84 return CssmAutoData(CssmAllocator::standard(), signature
->data(), signature
->length());
87 // ---------------------------------------------------------------------------
89 // ---------------------------------------------------------------------------
91 TrustedApplication::TrustedApplication()
95 TrustedApplication::TrustedApplication(
96 const char *path
, const CssmData
&comment
, bool enabled
) :
97 RefPointer
<TrustedApplicationImpl
>(new TrustedApplicationImpl(path
, comment
, enabled
))
101 TrustedApplication::TrustedApplication(
102 const CssmData
&signature
, const CssmData
&comment
, bool enabled
) :
103 RefPointer
<TrustedApplicationImpl
>(new TrustedApplicationImpl(signature
, comment
, enabled
))
107 // ---------------------------------------------------------------------------
109 // ---------------------------------------------------------------------------
111 KeychainACL::KeychainACL(const Key
&key
) :
112 mLabel(CssmAllocator::standard())
118 void KeychainACL::initialize()
121 mAlwaysAskUser
=false;
123 AutoAclEntryInfoList aclInfos
;
124 mKey
->getAcl(NULL
, aclInfos
);
125 mHandle
= CSSM_INVALID_HANDLE
;
126 const AclEntryInfo
*theInfo
= NULL
;
127 for(uint32 entry
=0; entry
<aclInfos
.size(); entry
++)
129 const AclEntryInfo
&info
= aclInfos
[entry
];
130 const AuthorizationGroup
&authorizationGroup
=info
.proto().authorization();
131 for(uint32 auth
=0; auth
<authorizationGroup
.count(); auth
++)
133 if(authorizationGroup
[auth
]==CSSM_ACL_AUTHORIZATION_DECRYPT
|| authorizationGroup
[auth
]==CSSM_ACL_AUTHORIZATION_ANY
)
135 if (mHandle
!= CSSM_INVALID_HANDLE
&& mHandle
!= info
.handle())
141 mHandle
= info
.handle();
152 TypedList subject
=theInfo
->proto().subject();
153 assert(subject
.isProper());
154 const ListElement
*element
= subject
.first();
158 case CSSM_ACL_SUBJECT_TYPE_ANY
:
159 assert(element
->next() == NULL
);
163 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
:
165 element
= element
->next();
166 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_DATUM
&& element
->next() == NULL
);
167 mLabel
= element
->data();
170 case CSSM_ACL_SUBJECT_TYPE_THRESHOLD
:
178 // OK, it's a threshold acl
179 element
= element
->next();
180 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_WORDID
);
185 element
= element
->next();
186 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_WORDID
);
191 for (uint32 ix
= 0; ix
< n
; ++ix
)
193 element
= element
->next();
194 assert(element
&& element
->type() == CSSM_LIST_ELEMENT_SUBLIST
);
195 const TypedList
&subList
= *element
;
196 assert(subList
.isProper());
197 const ListElement
*subElement
= subList
.first();
201 case CSSM_ACL_SUBJECT_TYPE_ANY
:
202 // Must be first subList in list.
203 assert(ix
== 0 && subElement
->next() == NULL
);
207 case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
:
208 // Must be last subList in list.
211 subElement
= subElement
->next();
212 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_DATUM
&& subElement
->next() == NULL
);
213 mLabel
= subElement
->data();
217 case CSSM_ACL_SUBJECT_TYPE_COMMENT
:
218 case CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE
:
220 // when the app is disabled it is commented out.
221 if(*subElement
==CSSM_ACL_SUBJECT_TYPE_COMMENT
)
224 subElement
= subElement
->next();
226 subElement
= subElement
->next();
227 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_WORDID
);
228 uint32 sigType
= *subElement
;
229 subElement
= subElement
->next();
230 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_DATUM
);
231 const CssmData
&sig
= subElement
->data();
232 subElement
= subElement
->next();
233 assert(subElement
&& subElement
->type() == CSSM_LIST_ELEMENT_DATUM
&& subElement
->next() == NULL
);
234 const CssmData
&comment
= subElement
->data();
235 // Only if sigType is CSSM_ACL_CODE_SIGNATURE_OSX this element is enabled.
236 // @@@ Otherwsie it should be CSSM_ACL_CODE_SIGNATURE_NONE (which is not defined yet).
237 // additionally the enabled flag must be respected.
238 push_back(TrustedApplication(sig
, comment
, (sigType
== CSSM_ACL_CODE_SIGNATURE_OSX
) && isEnabled
));
248 // Since we looked at N values we should be done.
249 assert(element
->next() == NULL
);
252 void KeychainACL::commit()
254 TrackingAllocator
allocator(CssmAllocator::standard());
256 KeychainAclFactory
aclFactory(allocator
);
258 CssmList
&list
= *new(allocator
) CssmList();
260 list
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_THRESHOLD
));
261 list
.append(new(allocator
) ListElement(1));
262 list
.append(new(allocator
) ListElement(size()+mAnyAllow
+mAlwaysAskUser
));
266 CssmList
&sublist
= *new(allocator
) CssmList();
267 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_ANY
));
268 list
.append(new(allocator
) ListElement(sublist
));
272 for (uint32 ix
= 0; ix
< size(); ++ix
)
274 TrustedApplication app
= at(ix
);
275 CssmList
&sublist
= *new(allocator
) CssmList();
276 if(!app
->enabled()) sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT
));
277 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE
));
278 sublist
.append(new(allocator
) ListElement(CSSM_ACL_CODE_SIGNATURE_OSX
));
279 sublist
.append(new(allocator
) ListElement(app
->signature()));
280 sublist
.append(new(allocator
) ListElement(app
->comment()));
281 list
.append(new(allocator
) ListElement(sublist
));
286 CssmList
&sublist
= *new(allocator
) CssmList();
287 sublist
.append(new(allocator
) ListElement(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT
));
288 sublist
.append(new(allocator
) ListElement(mLabel
.get()));
289 list
.append(new(allocator
) ListElement(sublist
));
292 AclEntryPrototype
aclEntry(list
);
293 // @@@ @@@ Force "decrypt" authorization for now -- should take this from input!! @@@
294 AuthorizationGroup
&anyDecryptAuthGroup
= aclEntry
.authorization();
295 CSSM_ACL_AUTHORIZATION_TAG decryptTag
= CSSM_ACL_AUTHORIZATION_DECRYPT
;
296 anyDecryptAuthGroup
.NumberOfAuthTags
= 1;
297 anyDecryptAuthGroup
.AuthTags
= &decryptTag
;
298 const AccessCredentials
*promptCred
= aclFactory
.keychainPromptCredentials();
299 AclEdit
edit(mHandle
, aclEntry
);
300 mKey
->changeAcl(promptCred
, edit
);
303 void KeychainACL::anyAllow(bool allow
)
308 bool KeychainACL::anyAllow() const
313 void KeychainACL::alwaysAskUser(bool ask
)
318 bool KeychainACL::alwaysAskUser() const
320 return mAlwaysAskUser
;
323 bool KeychainACL::isCustomACL() const
328 void KeychainACL::label(const CssmData
&label
)