2  * Copyright (c) 2000-2001,2007 Apple 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. 
  22 #include <security_cdsa_client/cssmclient.h> 
  23 #include <security_cdsa_client/aclclient.h> 
  24 #include <security_cdsa_client/keychainacl.h>  
  25 #include <security_cdsa_utilities/cssmwalkers.h> 
  26 #include <security_cdsa_utilities/cssmdata.h> 
  30 namespace CssmClient 
{ 
  32 static inline void check(CSSM_RETURN rc
) 
  34         ObjectImpl::check(rc
); 
  39 // AclBearer methods (trivial) 
  41 AclBearer::~AclBearer() 
  46 // Variant forms of AclBearer implemented in terms of its canonical virtual methods 
  48 void AclBearer::addAcl(const AclEntryInput 
&input
, const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  50         changeAcl(AclEdit(input
), cred
); 
  53 void AclBearer::changeAcl(CSSM_ACL_HANDLE handle
, const AclEntryInput 
&input
, 
  54         const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  56         changeAcl(AclEdit(handle
, input
), cred
); 
  59 void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle
, const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  61         changeAcl(AclEdit(handle
), cred
); 
  64 void AclBearer::deleteAcl(const char *tag
, const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  66         AutoAclEntryInfoList entries
; 
  68         for (uint32 n 
= 0; n 
< entries
.count(); n
++) 
  69                 deleteAcl(entries
[n
].handle(), cred
); 
  74 // KeyAclBearer implementation 
  76 void KeyAclBearer::getAcl(AutoAclEntryInfoList 
&aclInfos
, const char *selectionTag
) const 
  78         aclInfos
.allocator(allocator
); 
  79         check(CSSM_GetKeyAcl(csp
, &key
, reinterpret_cast<const CSSM_STRING 
*>(selectionTag
), aclInfos
, aclInfos
)); 
  82 void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT 
&aclEdit
, const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  84         check(CSSM_ChangeKeyAcl(csp
, AccessCredentials::needed(cred
), &aclEdit
, &key
)); 
  87 void KeyAclBearer::getOwner(AutoAclOwnerPrototype 
&owner
) const 
  89         owner
.allocator(allocator
); 
  90         check(CSSM_GetKeyOwner(csp
, &key
, owner
)); 
  93 void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE 
&newOwner
, 
  94         const CSSM_ACCESS_CREDENTIALS 
*cred
) 
  96         check(CSSM_ChangeKeyOwner(csp
, AccessCredentials::needed(cred
), &key
, &newOwner
)); 
 101 // A single global structure containing pseudo-static data 
 107         AutoCredentials nullCred
; 
 108         AutoCredentials promptCred
; 
 109         AutoCredentials unlockCred
; 
 110         AutoCredentials cancelCred
; 
 111         AutoCredentials promptedPINCred
; 
 112         AutoCredentials promptedPINItemCred
; 
 114         AclOwnerPrototype anyOwner
; 
 119         ModuleNexus
<Statics
> statics
; 
 124 // Make pseudo-statics. 
 125 // Note: This is an eternal object. It is not currently destroyed 
 126 // if the containing code is unloaded. 
 129         : alloc(Allocator::standard()), 
 131           promptCred(alloc
, 3), 
 132           unlockCred(alloc
, 1), 
 133           cancelCred(alloc
, 1), 
 134           promptedPINCred(alloc
, 1), 
 135           promptedPINItemCred(alloc
, 1), 
 136           anyOwner(TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_ANY
)), 
 137           anyAcl(AclEntryPrototype(TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_ANY
), 1)) 
 139         // nullCred: nothing at all 
 141         //  an empty THRESHOLD sample to match threshold subjects with "free" subjects 
 142         nullCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_THRESHOLD
); 
 144         // promptCred: a credential permitting user prompt confirmations 
 146         //  a KEYCHAIN_PROMPT sample, both by itself and in a THRESHOLD 
 147         //  a PROMPTED_PASSWORD sample 
 148         promptCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
); 
 149         promptCred
.sample(1) = TypedList(alloc
, CSSM_SAMPLE_TYPE_THRESHOLD
, 
 150                 new(alloc
) ListElement(TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
))); 
 151         promptCred
.sample(2) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
, 
 152                 new(alloc
) ListElement(alloc
, CssmData())); 
 155         unlockCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
, 
 156                 new(alloc
) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
)); 
 158         cancelCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
, 
 159                                                                          new(alloc
) ListElement(CSSM_WORDID_CANCELED
)); 
 164                         promptedPINCred.tag("PIN1"); 
 166                 here to avoid triggering code in TokenDatabase::getAcl in securityd that 
 167                 would always show a PIN unlock dialog. This credential is used for an 
 168                 unlock of the database, i.e. a dbauthenticate call to unlock the card. 
 170         promptedPINCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
, 
 171                                                                                   new(alloc
) ListElement(alloc
, CssmData())); 
 174                 This credential is used for items like non-repudiation keys that always 
 175                 require an explicit entry of the PIN. We set this so that Token::authenticate 
 176                 will recognize the number of the PIN we need to unlock. 
 178         promptedPINItemCred
.tag("PIN1"); 
 179         promptedPINItemCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
, 
 180                                                                                   new(alloc
) ListElement(alloc
, CssmData())); 
 185 // Make and break AclFactories 
 187 AclFactory::AclFactory() 
 190 AclFactory::~AclFactory() 
 195 // Return basic pseudo-static values 
 197 const AccessCredentials 
*AclFactory::nullCred() const 
 198 { return &statics().nullCred
; } 
 200 const AccessCredentials 
*AclFactory::promptCred() const 
 201 { return &statics().promptCred
; } 
 203 const AccessCredentials 
*AclFactory::unlockCred() const 
 204 { return &statics().unlockCred
; } 
 207 const AccessCredentials 
*AclFactory::cancelCred() const 
 208 { return &statics().cancelCred
; } 
 210 const AccessCredentials 
*AclFactory::promptedPINCred() const 
 211 { return &statics().promptedPINCred
; } 
 213 const AccessCredentials 
*AclFactory::promptedPINItemCred() const 
 214 { return &statics().promptedPINItemCred
; } 
 218 // Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain. 
 219 // Use the eternal unlockCred() for normal (protected prompt) unlocking. 
 221 AclFactory::KeychainCredentials::~KeychainCredentials () 
 223     DataWalkers::chunkFree(mCredentials
, allocator
); 
 226 AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData
& password
, 
 227         Allocator
& allocator
) : KeychainCredentials(allocator
) 
 229     mCredentials
->sample(0) = TypedList(allocator
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
, 
 230                 new (allocator
) ListElement (CSSM_SAMPLE_TYPE_PASSWORD
), 
 231                 new (allocator
) ListElement (CssmAutoData(allocator
, password
).release())); 
 236 // Manage the (pseudo) credentials used to explicitly change a keychain's passphrase 
 238 AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData
& password
, 
 239         Allocator
& allocator
) : KeychainCredentials(allocator
) 
 241     mCredentials
->sample(0) = TypedList(allocator
, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK
, 
 242                 new (allocator
) ListElement (CSSM_SAMPLE_TYPE_PASSWORD
), 
 243                 new (allocator
) ListElement (CssmAutoData(allocator
, password
).release())); 
 248 // Wide open ("ANY") CSSM forms for owner and ACL entry 
 250 const AclOwnerPrototype 
&AclFactory::anyOwner() const 
 251 { return statics().anyOwner
; } 
 253 const AclEntryInfo 
&AclFactory::anyAcl() const 
 254 { return statics().anyAcl
; } 
 258 // Create an ANY style AclEntryInput. 
 259 // This can be used to explicitly request wide-open authorization on a new CSSM object. 
 261 AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS 
*cred
) 
 262         : mAny(CSSM_ACL_SUBJECT_TYPE_ANY
), mTag(CSSM_ACL_AUTHORIZATION_ANY
) 
 264         // set up an ANY/EVERYTHING AclEntryInput 
 265         input().proto().subject() += &mAny
; 
 266         AuthorizationGroup 
&authGroup 
= input().proto().authorization(); 
 267         authGroup
.NumberOfAuthTags 
= 1; 
 268         authGroup
.AuthTags 
= &mTag
; 
 270         // install the cred (not copied) 
 278 AclFactory::Subject::Subject(Allocator 
&alloc
, CSSM_ACL_SUBJECT_TYPE type
) 
 279         : TypedList(alloc
, type
) 
 283 AclFactory::PWSubject::PWSubject(Allocator 
&alloc
) 
 284         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PASSWORD
) 
 287 AclFactory::PWSubject::PWSubject(Allocator 
&alloc
, const CssmData 
&secret
) 
 288         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PASSWORD
) 
 290         append(new(alloc
) ListElement(alloc
, secret
)); 
 293 AclFactory::PromptPWSubject::PromptPWSubject(Allocator 
&alloc
, const CssmData 
&prompt
) 
 294         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD
) 
 296         append(new(alloc
) ListElement(alloc
, prompt
)); 
 299 AclFactory::PromptPWSubject::PromptPWSubject(Allocator 
&alloc
, const CssmData 
&prompt
, const CssmData 
&secret
) 
 300         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD
) 
 302         append(new(alloc
) ListElement(alloc
, prompt
)); 
 303         append(new(alloc
) ListElement(alloc
, secret
)); 
 306 AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator 
&alloc
) 
 307         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD
) 
 310 AclFactory::PinSubject::PinSubject(Allocator 
&alloc
, uint32 slot
) 
 311         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH
) 
 313         append(new(alloc
) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot
))); 
 316 AclFactory::PinSourceSubject::PinSourceSubject(Allocator 
&alloc
, const TypedList 
&form
) 
 317         : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE
) 
 319         append(new(alloc
) ListElement(form
)); 
 323 } // end namespace CssmClient 
 324 } // end namespace Security