/ OSX / libsecurity_keychain / lib / ExtendedAttribute.cpp
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