ExtendedAttribute.cpp
1 /* 2 * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 /* 25 * ExtendedAttribute.cpp - Extended Keychain Item Attribute class. 26 * 27 */ 28 29 #include "ExtendedAttribute.h" 30 #include "SecKeychainItemExtendedAttributes.h" 31 #include "SecKeychainItemPriv.h" 32 #include "cssmdatetime.h" 33 #include <security_cdsa_utilities/Schema.h> 34 35 using namespace KeychainCore; 36 37 /* 38 * Construct new ExtendedAttr from API. 39 */ 40 ExtendedAttribute::ExtendedAttribute( 41 CSSM_DB_RECORDTYPE recordType, 42 const CssmData &itemID, 43 const CssmData attrName, 44 const CssmData attrValue) : 45 ItemImpl((SecItemClass) CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, 46 reinterpret_cast<SecKeychainAttributeList *>(NULL), 47 0, NULL), 48 mRecordType(recordType), 49 mItemID(Allocator::standard(), itemID.Data, itemID.Length), 50 mAttrName(Allocator::standard(), attrName.Data, attrName.Length), 51 mAttrValue(Allocator::standard(), attrValue.Data, attrValue.Length) 52 { 53 setupAttrs(); 54 } 55 56 // db item contstructor 57 ExtendedAttribute::ExtendedAttribute( 58 const Keychain &keychain, 59 const PrimaryKey &primaryKey, 60 const CssmClient::DbUniqueRecord &uniqueId) : 61 ItemImpl(keychain, primaryKey, uniqueId), 62 mRecordType(0), 63 mItemID(Allocator::standard()), 64 mAttrName(Allocator::standard()), 65 mAttrValue(Allocator::standard()) 66 { 67 68 } 69 70 // PrimaryKey item contstructor 71 ExtendedAttribute::ExtendedAttribute( 72 const Keychain &keychain, 73 const PrimaryKey &primaryKey) : 74 ItemImpl(keychain, primaryKey), 75 mRecordType(0), 76 mItemID(Allocator::standard()), 77 mAttrName(Allocator::standard()), 78 mAttrValue(Allocator::standard()) 79 { 80 81 } 82 83 ExtendedAttribute* ExtendedAttribute::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) 84 { 85 ExtendedAttribute* ea = new ExtendedAttribute(keychain, primaryKey, uniqueId); 86 keychain->addItem(primaryKey, ea); 87 return ea; 88 } 89 90 91 92 ExtendedAttribute* ExtendedAttribute::make(const Keychain &keychain, const PrimaryKey &primaryKey) 93 { 94 ExtendedAttribute* ea = new ExtendedAttribute(keychain, primaryKey); 95 keychain->addItem(primaryKey, ea); 96 return ea; 97 } 98 99 100 101 // copy - required due to Item's weird constructor/vendor 102 ExtendedAttribute::ExtendedAttribute( 103 ExtendedAttribute &extendedAttr) : 104 ItemImpl(extendedAttr), 105 mRecordType(extendedAttr.mRecordType), 106 mItemID(Allocator::standard()), 107 mAttrName(Allocator::standard()), 108 mAttrValue(Allocator::standard()) 109 { 110 // CssmData cd = extendedAttr.mItemID; 111 mItemID.copy(extendedAttr.mItemID); 112 // cd = extendedAttr.mAttrName; 113 mAttrName.copy(extendedAttr.mAttrName); 114 // cd = extendedAttr.mAttrValue; 115 mAttrValue.copy(extendedAttr.mAttrValue); 116 setupAttrs(); 117 } 118 119 ExtendedAttribute::~ExtendedAttribute() _NOEXCEPT 120 { 121 122 } 123 124 PrimaryKey 125 ExtendedAttribute::add(Keychain &keychain) 126 { 127 StLock<Mutex>_(mMutex); 128 // If we already have a Keychain we can't be added. 129 if (mKeychain) 130 MacOSError::throwMe(errSecDuplicateItem); 131 132 SInt64 date; 133 CSSMDateTimeUtils::GetCurrentMacLongDateTime(date); 134 CssmDbAttributeInfo attrInfo(kSecModDateItemAttr, CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE); 135 setAttribute(attrInfo, date); 136 137 Db db(keychain->database()); 138 // add the item to the (regular) db 139 try 140 { 141 mUniqueId = db->insert(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mDbAttributes.get(), mData.get()); 142 } 143 catch (const CssmError &e) 144 { 145 if (e.osStatus() != CSSMERR_DL_INVALID_RECORDTYPE) 146 throw; 147 148 /* 149 * First exposure of this keychain to the extended attribute record type. 150 * Create the relation and try again. 151 */ 152 db->createRelation(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, 153 "CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE", 154 Schema::ExtendedAttributeSchemaAttributeCount, 155 Schema::ExtendedAttributeSchemaAttributeList, 156 Schema::ExtendedAttributeSchemaIndexCount, 157 Schema::ExtendedAttributeSchemaIndexList); 158 keychain->keychainSchema()->didCreateRelation( 159 CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, 160 "CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE", 161 Schema::ExtendedAttributeSchemaAttributeCount, 162 Schema::ExtendedAttributeSchemaAttributeList, 163 Schema::ExtendedAttributeSchemaIndexCount, 164 Schema::ExtendedAttributeSchemaIndexList); 165 166 mUniqueId = db->insert(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mDbAttributes.get(), mData.get()); 167 } 168 169 mPrimaryKey = keychain->makePrimaryKey(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, mUniqueId); 170 mKeychain = keychain; 171 172 return mPrimaryKey; 173 } 174 175 /* set up DB attrs based on member vars */ 176 void ExtendedAttribute::setupAttrs() 177 { 178 StLock<Mutex>_(mMutex); 179 CssmDbAttributeInfo attrInfo1(kExtendedAttrRecordTypeAttr, CSSM_DB_ATTRIBUTE_FORMAT_UINT32); 180 setAttribute(attrInfo1, (uint32)mRecordType); 181 CssmData cd = mItemID; 182 CssmDbAttributeInfo attrInfo2(kExtendedAttrItemIDAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); 183 setAttribute(attrInfo2, cd); 184 cd = mAttrName; 185 CssmDbAttributeInfo attrInfo3(kExtendedAttrAttributeNameAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); 186 setAttribute(attrInfo3, cd); 187 cd = mAttrValue; 188 CssmDbAttributeInfo attrInfo4(kExtendedAttrAttributeValueAttr, CSSM_DB_ATTRIBUTE_FORMAT_BLOB); 189 setAttribute(attrInfo4, cd); 190 } 191 192