/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ // // aclsupport.h - support for special Keychain style acls // #include #include #include #include "aclsupport.h" #include "keychainacl.h" #include using namespace CssmClient; // --------------------------------------------------------------------------- // TrustedApplicationImpl // --------------------------------------------------------------------------- TrustedApplicationImpl::TrustedApplicationImpl(const CssmData &signature, const CssmData &comment, bool enabled) : mSignature(CssmAllocator::standard(), signature), mComment(CssmAllocator::standard(), comment), mEnabled(enabled) { } TrustedApplicationImpl::TrustedApplicationImpl(const char *path, const CssmData &comment, bool enabled) : mSignature(CssmAllocator::standard()), mComment(CssmAllocator::standard(), comment), mEnabled(enabled) { calcSignature(path, mSignature); } const CssmData & TrustedApplicationImpl::signature() const { return mSignature; } const CssmData & TrustedApplicationImpl::comment() const { return mComment; } bool TrustedApplicationImpl::enabled() const { return mEnabled; } void TrustedApplicationImpl::enabled(bool enabled) { mEnabled = enabled; } bool TrustedApplicationImpl::sameSignature(const char *path) { // return true if object at given path has same signature CssmAutoData otherSignature(CssmAllocator::standard()); calcSignature(path, otherSignature); return (mSignature.get() == otherSignature); } void TrustedApplicationImpl::calcSignature(const char *path, CssmOwnedData &signature) { // generate a signature for the given object RefPointer objToVerify(CodeSigning::OSXCode::at(path)); CodeSigning::OSXSigner signer; auto_ptr osxSignature(signer.sign(*objToVerify)); signature.copy(osxSignature->data(), osxSignature->length()); } // --------------------------------------------------------------------------- // TrustedApplication // --------------------------------------------------------------------------- TrustedApplication::TrustedApplication() { } TrustedApplication::TrustedApplication( const char *path, const CssmData &comment, bool enabled) : RefPointer(new TrustedApplicationImpl(path, comment, enabled)) { } TrustedApplication::TrustedApplication( const CssmData &signature, const CssmData &comment, bool enabled) : RefPointer(new TrustedApplicationImpl(signature, comment, enabled)) { } // --------------------------------------------------------------------------- // KeychainACL // --------------------------------------------------------------------------- KeychainACL::KeychainACL(const Key &key) : mLabel(CssmAllocator::standard()), mSelector(CssmAllocator::standard()) { mKey = key; initialize(); } void KeychainACL::initialize() { mAnyAllow=false; mAlwaysAskUser=false; CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector = { CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION, 0 }; mSelector.copy(&defaultSelector, sizeof(defaultSelector)); AutoAclEntryInfoList aclInfos; mKey->getAcl(aclInfos); mHandle = CSSM_INVALID_HANDLE; const AclEntryInfo *theInfo = NULL; for(uint32 entry=0; entryproto().subject(); assert(subject.isProper()); const ListElement *element = subject.first(); switch(*element) { case CSSM_ACL_SUBJECT_TYPE_ANY: assert(element->next() == NULL); mAnyAllow=true; return; case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT: mAlwaysAskUser=true; assert(subject.length() == 3); mSelector = subject[1].data(); mLabel = subject[2].data(); return; case CSSM_ACL_SUBJECT_TYPE_THRESHOLD: break; default: mIsCustomACL = true; return; } // OK, it's a threshold acl element = element->next(); assert(element && element->type() == CSSM_LIST_ELEMENT_WORDID); if (*element != 1) { mIsCustomACL = true; return; } element = element->next(); assert(element && element->type() == CSSM_LIST_ELEMENT_WORDID); uint32 n = *element; assert(n > 0); int isEnabled=1; for (uint32 ix = 0; ix < n; ++ix) { element = element->next(); assert(element && element->type() == CSSM_LIST_ELEMENT_SUBLIST); const TypedList &subList = *element; assert(subList.isProper()); const ListElement *subElement = subList.first(); switch(*subElement) { case CSSM_ACL_SUBJECT_TYPE_ANY: // Must be first subList in list. assert(ix == 0 && subElement->next() == NULL); mAnyAllow=true; break; case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT: // Must be last subList in list. assert(ix == n - 1); mAlwaysAskUser=true; assert(subList.length() == 3); mSelector = subList[1].data(); mLabel = subList[2].data(); break; case CSSM_ACL_SUBJECT_TYPE_COMMENT: case CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE: { // when the app is disabled it is commented out. if(*subElement==CSSM_ACL_SUBJECT_TYPE_COMMENT) { isEnabled=0; subElement = subElement->next(); } subElement = subElement->next(); assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_WORDID); uint32 sigType = *subElement; subElement = subElement->next(); assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_DATUM); const CssmData &sig = subElement->data(); subElement = subElement->next(); assert(subElement && subElement->type() == CSSM_LIST_ELEMENT_DATUM && subElement->next() == NULL); const CssmData &comment = subElement->data(); // Only if sigType is CSSM_ACL_CODE_SIGNATURE_OSX this element is enabled. // @@@ Otherwsie it should be CSSM_ACL_CODE_SIGNATURE_NONE (which is not defined yet). // additionally the enabled flag must be respected. push_back(TrustedApplication(sig, comment, (sigType == CSSM_ACL_CODE_SIGNATURE_OSX) && isEnabled)); break; } default: mIsCustomACL = true; return; } } // Since we looked at N values we should be done. assert(element->next() == NULL); } void KeychainACL::commit() { TrackingAllocator allocator(CssmAllocator::standard()); // hhs replaced with new aclFactory AclFactory aclFactory; CssmList &list = *new(allocator) CssmList(); list.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_THRESHOLD)); list.append(new(allocator) ListElement(1)); list.append(new(allocator) ListElement(size()+mAnyAllow+mAlwaysAskUser)); if(mAnyAllow) { CssmList &sublist = *new(allocator) CssmList(); sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_ANY)); list.append(new(allocator) ListElement(sublist)); } for (uint32 ix = 0; ix < size(); ++ix) { TrustedApplication app = at(ix); CssmList &sublist = *new(allocator) CssmList(); if(!app->enabled()) sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT)); sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE)); sublist.append(new(allocator) ListElement(CSSM_ACL_CODE_SIGNATURE_OSX)); sublist.append(new(allocator) ListElement(app->signature())); sublist.append(new(allocator) ListElement(app->comment())); list.append(new(allocator) ListElement(sublist)); } if(mAlwaysAskUser) { CssmList &sublist = *new(allocator) CssmList(); sublist.append(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT)); sublist.append(new(allocator) ListElement(mSelector.get())); sublist.append(new(allocator) ListElement(mLabel.get())); list.append(new(allocator) ListElement(sublist)); } AclEntryPrototype aclEntry(list); // @@@ @@@ Force "decrypt" authorization for now -- should take this from input!! @@@ AuthorizationGroup &anyDecryptAuthGroup = aclEntry.authorization(); CSSM_ACL_AUTHORIZATION_TAG decryptTag = CSSM_ACL_AUTHORIZATION_DECRYPT; anyDecryptAuthGroup.NumberOfAuthTags = 1; anyDecryptAuthGroup.AuthTags = &decryptTag; const AccessCredentials *promptCred = aclFactory.promptCred (); AclEdit edit(mHandle, aclEntry); mKey->changeAcl(edit, promptCred); } void KeychainACL::anyAllow(bool allow) { mAnyAllow=allow; } bool KeychainACL::anyAllow() const { return mAnyAllow; } void KeychainACL::alwaysAskUser(bool ask) { mAlwaysAskUser=ask; } bool KeychainACL::alwaysAskUser() const { return mAlwaysAskUser; } bool KeychainACL::isCustomACL() const { return mIsCustomACL; } void KeychainACL::label(const CssmData &label) { mLabel = label; }