/* * Copyright (c) 2002 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. */ // // TrustStore.h - Abstract interface to permanent user trust assignments // #include #include #include #include #include #include namespace Security { namespace KeychainCore { // // Construct a UserTrustItem from attributes and initial content // UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData &trustData) : ItemImpl(CSSM_DL_DB_RECORD_USER_TRUST, reinterpret_cast(NULL), UInt32(sizeof(trustData)), reinterpret_cast(&trustData)), mCertificate(cert), mPolicy(policy) { secdebug("usertrust", "create %p (%p,%p) = %d", this, cert, policy, trustData.trust); } // // Destroy it // UserTrustItem::~UserTrustItem() throw() { secdebug("usertrust", "destroy %p", this); } // // Retrieve the trust value from a UserTrustItem // UserTrustItem::TrustData UserTrustItem::trust() { CssmDataContainer data; getData(data); if (data.length() != sizeof(TrustData)) MacOSError::throwMe(errSecInvalidTrustSetting); return *data.interpretedAs(); } // // Add item to keychain // PrimaryKey UserTrustItem::add(Keychain &keychain) { // If we already have a Keychain we can't be added. if (mKeychain) MacOSError::throwMe(errSecDuplicateItem); populateAttributes(); CSSM_DB_RECORDTYPE recordType = mDbAttributes->recordType(); Db db(keychain->database()); // add the item to the (regular) db try { mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); secdebug("usertrust", "%p inserted", this); } catch (const CssmError &e) { if (e.cssmError() != CSSMERR_DL_INVALID_RECORDTYPE) throw; // Create the cert relation and try again. secdebug("usertrust", "adding schema relation for user trusts"); db->createRelation(CSSM_DL_DB_RECORD_USER_TRUST, "CSSM_DL_DB_RECORD_USER_TRUST", Schema::UserTrustSchemaAttributeCount, Schema::UserTrustSchemaAttributeList, Schema::UserTrustSchemaIndexCount, Schema::UserTrustSchemaIndexList); keychain->resetSchema(); mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); secdebug("usertrust", "%p inserted now", this); } mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); mKeychain = keychain; return mPrimaryKey; } void UserTrustItem::populateAttributes() { CssmAutoData encodedIndex(CssmAllocator::standard()); makeCertIndex(mCertificate, encodedIndex); const CssmOid &policyOid = mPolicy->oid(); mDbAttributes->add(Schema::attributeInfo(kSecTrustCertAttr), encodedIndex.get()); mDbAttributes->add(Schema::attributeInfo(kSecTrustPolicyAttr), policyOid); } // // An ad-hoc hold-and-destroy accessor for a single-valued certificate field // class CertField { public: CertField(Certificate *cert, const CSSM_OID &inField) : certificate(cert), field(inField) { mData = certificate->copyFirstFieldValue(field); } ~CertField() { certificate->releaseFieldValue(field, mData); } Certificate * const certificate; const CSSM_OID &field; operator bool () const { return mData && mData->Data; } CssmData &data() const { return CssmData::overlay(*mData); } private: CSSM_DATA_PTR mData; }; // // Construct a trust item index. // This is an ASN.1 sequence of issuer and serial number. // struct IssuerAndSN { CSSM_DATA issuer; CSSM_DATA serial; }; static const SEC_ASN1Template issuerAndSNTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(IssuerAndSN) }, { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, issuer) }, { SEC_ASN1_OCTET_STRING, offsetof(IssuerAndSN, serial) }, { 0 } }; void UserTrustItem::makeCertIndex(Certificate *cert, CssmOwnedData &encodedIndex) { CertField issuer(cert, CSSMOID_X509V1IssuerName); CertField serial(cert, CSSMOID_X509V1SerialNumber); IssuerAndSN index; index.issuer = issuer.data(); index.serial = serial.data(); if (SecNssEncodeItemOdata(&index, issuerAndSNTemplate, encodedIndex)) CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } } // end namespace KeychainCore } // end namespace Security