1/* 2 * Copyright (c) 2000-2001,2007,2011 Apple Inc. All Rights Reserved. 3 * 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 8 * using this file. 9 * 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. 16 */ 17 18 19// 20// aclclient 21// 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> 27 28 29namespace Security { 30namespace CssmClient { 31 32static inline void check(CSSM_RETURN rc) 33{ 34 ObjectImpl::check(rc); 35} 36 37 38// 39// AclBearer methods (trivial) 40// 41AclBearer::~AclBearer() 42{ } 43 44 45// 46// Variant forms of AclBearer implemented in terms of its canonical virtual methods 47// 48void AclBearer::addAcl(const AclEntryInput &input, const CSSM_ACCESS_CREDENTIALS *cred) 49{ 50 changeAcl(AclEdit(input), cred); 51} 52 53void AclBearer::changeAcl(CSSM_ACL_HANDLE handle, const AclEntryInput &input, 54 const CSSM_ACCESS_CREDENTIALS *cred) 55{ 56 changeAcl(AclEdit(handle, input), cred); 57} 58 59void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle, const CSSM_ACCESS_CREDENTIALS *cred) 60{ 61 changeAcl(AclEdit(handle), cred); 62} 63 64void AclBearer::deleteAcl(const char *tag, const CSSM_ACCESS_CREDENTIALS *cred) 65{ 66 AutoAclEntryInfoList entries; 67 getAcl(entries, tag); 68 for (uint32 n = 0; n < entries.count(); n++) 69 deleteAcl(entries[n].handle(), cred); 70} 71 72 73// 74// KeyAclBearer implementation 75// 76void KeyAclBearer::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const 77{ 78 aclInfos.allocator(allocator); 79 check(CSSM_GetKeyAcl(csp, &key, reinterpret_cast<const CSSM_STRING *>(selectionTag), aclInfos, aclInfos)); 80} 81 82void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT &aclEdit, const CSSM_ACCESS_CREDENTIALS *cred) 83{ 84 check(CSSM_ChangeKeyAcl(csp, AccessCredentials::needed(cred), &aclEdit, &key)); 85} 86 87void KeyAclBearer::getOwner(AutoAclOwnerPrototype &owner) const 88{ 89 owner.allocator(allocator); 90 check(CSSM_GetKeyOwner(csp, &key, owner)); 91} 92 93void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, 94 const CSSM_ACCESS_CREDENTIALS *cred) 95{ 96 check(CSSM_ChangeKeyOwner(csp, AccessCredentials::needed(cred), &key, &newOwner)); 97} 98 99 100// 101// A single global structure containing pseudo-static data 102// 103struct Statics { 104 Statics(); 105 Allocator &alloc; 106 107 AutoCredentials nullCred; 108 AutoCredentials promptCred; 109 AutoCredentials unlockCred; 110 AutoCredentials cancelCred; 111 AutoCredentials promptedPINCred; 112 AutoCredentials promptedPINItemCred; 113 114 AclOwnerPrototype anyOwner; 115 AclEntryInfo anyAcl; 116}; 117 118namespace { 119 ModuleNexus<Statics> statics; 120} 121 122 123// 124// Make pseudo-statics. 125// Note: This is an eternal object. It is not currently destroyed 126// if the containing code is unloaded. 127// 128Statics::Statics() 129 : alloc(Allocator::standard()), 130 nullCred(alloc, 1), 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)) 138{ 139 // nullCred: nothing at all 140 // contains: 141 // an empty THRESHOLD sample to match threshold subjects with "free" subjects 142 nullCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD); 143 144 // promptCred: a credential permitting user prompt confirmations 145 // contains: 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())); 153 154 // unlockCred: ??? 155 unlockCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, 156 new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT)); 157 158 cancelCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, 159 new(alloc) ListElement(CSSM_WORDID_CANCELED)); 160 161 /* 162 We don't set this: 163 164 promptedPINCred.tag("PIN1"); 165 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. 169 */ 170 promptedPINCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, 171 new(alloc) ListElement(alloc, CssmData())); 172 173 /* 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. 177 */ 178 promptedPINItemCred.tag("PIN1"); 179 promptedPINItemCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, 180 new(alloc) ListElement(alloc, CssmData())); 181} 182 183 184// 185// Make and break AclFactories 186// 187AclFactory::AclFactory() 188{ } 189 190AclFactory::~AclFactory() 191{ } 192 193 194// 195// Return basic pseudo-static values 196// 197const AccessCredentials *AclFactory::nullCred() const 198{ return &statics().nullCred; } 199 200const AccessCredentials *AclFactory::promptCred() const 201{ return &statics().promptCred; } 202 203const AccessCredentials *AclFactory::unlockCred() const 204{ return &statics().unlockCred; } 205 206 207const AccessCredentials *AclFactory::cancelCred() const 208{ return &statics().cancelCred; } 209 210const AccessCredentials *AclFactory::promptedPINCred() const 211{ return &statics().promptedPINCred; } 212 213const AccessCredentials *AclFactory::promptedPINItemCred() const 214{ return &statics().promptedPINItemCred; } 215 216 217// 218// Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain. 219// Use the eternal unlockCred() for normal (protected prompt) unlocking. 220// 221AclFactory::KeychainCredentials::~KeychainCredentials () 222{ 223 DataWalkers::chunkFree(mCredentials, allocator); 224} 225 226AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData& password, 227 Allocator& allocator) : KeychainCredentials(allocator) 228{ 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())); 232} 233 234 235// 236// Manage the (pseudo) credentials used to explicitly change a keychain's passphrase 237// 238AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData& password, 239 Allocator& allocator) : KeychainCredentials(allocator) 240{ 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())); 244} 245 246 247// 248// Wide open ("ANY") CSSM forms for owner and ACL entry 249// 250const AclOwnerPrototype &AclFactory::anyOwner() const 251{ return statics().anyOwner; } 252 253const AclEntryInfo &AclFactory::anyAcl() const 254{ return statics().anyAcl; } 255 256 257// 258// Create an ANY style AclEntryInput. 259// This can be used to explicitly request wide-open authorization on a new CSSM object. 260// 261AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS *cred) 262 : mAny(CSSM_ACL_SUBJECT_TYPE_ANY), mTag(CSSM_ACL_AUTHORIZATION_ANY) 263{ 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; 269 270 // install the cred (not copied) 271 credentials(cred); 272} 273 274 275// 276// CSSM ACL makers 277// 278AclFactory::Subject::Subject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type) 279 : TypedList(alloc, type) 280{ } 281 282 283AclFactory::PWSubject::PWSubject(Allocator &alloc) 284 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD) 285{ } 286 287AclFactory::PWSubject::PWSubject(Allocator &alloc, const CssmData &secret) 288 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD) 289{ 290 append(new(alloc) ListElement(alloc, secret)); 291} 292 293AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt) 294 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD) 295{ 296 append(new(alloc) ListElement(alloc, prompt)); 297} 298 299AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt, const CssmData &secret) 300 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD) 301{ 302 append(new(alloc) ListElement(alloc, prompt)); 303 append(new(alloc) ListElement(alloc, secret)); 304} 305 306AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator &alloc) 307 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD) 308{ } 309 310AclFactory::PinSubject::PinSubject(Allocator &alloc, uint32 slot) 311 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH) 312{ 313 append(new(alloc) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot))); 314} 315 316AclFactory::PinSourceSubject::PinSourceSubject(Allocator &alloc, const TypedList &form) 317 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE) 318{ 319 append(new(alloc) ListElement(form)); 320} 321 322 323} // end namespace CssmClient 324} // end namespace Security 325