diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp index 54f9089f2..6ec74b96d 100644 --- a/src/lib/SoftHSM.cpp +++ b/src/lib/SoftHSM.cpp @@ -1684,6 +1684,7 @@ CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject { if (!object->attributeExists(attrType)) { + WARNING_MSG("Attribute 0x%lx does not exist even though it was reported as next."); rv = CKR_FUNCTION_FAILED; break; } diff --git a/src/lib/object_store/DBObject.cpp b/src/lib/object_store/DBObject.cpp index a29417343..fb3cce6fe 100644 --- a/src/lib/object_store/DBObject.cpp +++ b/src/lib/object_store/DBObject.cpp @@ -202,6 +202,37 @@ bool DBObject::createTables() return true; } +// update schema to support new features with dbs from previous versions. +bool DBObject::migrateTables() +{ + MutexLocker lock(_mutex); + + if (_connection == NULL) + { + ERROR_MSG("Object is not connected to the database."); + return false; + } + + // attributes + DB::Statement cr_attrs = _connection->prepare( + "create view if not exists attributes as " + "select object_id, type from attribute_array " + "union all select object_id, type from attribute_binary " + "union all select object_id, type from attribute_boolean " + "union all select object_id, type from attribute_datetime " + "union all select object_id, type from attribute_integer " + "union all select object_id, type from attribute_real " + "union all select object_id, type from attribute_text" + ); + if (!_connection->execute(cr_attrs)) + { + ERROR_MSG("Failed to create \"attributes\" view"); + return false; + } + + return true; +} + bool DBObject::dropTables() { MutexLocker lock(_mutex); @@ -212,6 +243,14 @@ bool DBObject::dropTables() return false; } + // attributes + DB::Statement dr_attrs = _connection->prepare("drop view attributes"); + if (!_connection->execute(dr_attrs)) + { + ERROR_MSG("Failed to drop \"attributes\" view"); + return false; + } + // Create the tables inside the database DB::Statement dr_object = _connection->prepare("drop table object"); if (!_connection->execute(dr_object)) @@ -450,6 +489,7 @@ static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type) case CKA_EXPONENT_1: return akBinary; case CKA_EXPONENT_2: return akBinary; case CKA_COEFFICIENT: return akBinary; + case CKA_PUBLIC_KEY_INFO: return akBinary; case CKA_PRIME: return akBinary; case CKA_SUBPRIME: return akBinary; case CKA_BASE: return akBinary; @@ -464,6 +504,7 @@ static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type) case CKA_KEY_GEN_MECHANISM: return akInteger; case CKA_MODIFIABLE: return akBoolean; case CKA_COPYABLE: return akBoolean; + case CKA_DESTROYABLE: return akBoolean; case CKA_ECDSA_PARAMS: return akBinary; case CKA_EC_POINT: return akBinary; case CKA_SECONDARY_AUTH: return akBoolean; @@ -1082,7 +1123,7 @@ ByteString DBObject::getByteStringValue(CK_ATTRIBUTE_TYPE type) } } -CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE) +CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE last) { MutexLocker lock(_mutex); @@ -1097,8 +1138,21 @@ CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE) return false; } - // FIXME: implement for C_CopyObject - return CKA_CLASS; + DB::Statement stmt = _connection->prepare("select MIN(type) from attributes where object_id=%lld and type>%ld", _objectId, last); + + if (!stmt.isValid()) + { + WARNING_MSG("Failed to prepare next attribute query"); + return CKA_CLASS; + } + + DB::Result result = _connection->perform(stmt); + if (!result.isValid()) + { + return CKA_CLASS; + } + + return result.getULongLong(1); } // Set the specified attribute diff --git a/src/lib/object_store/DBObject.h b/src/lib/object_store/DBObject.h index 4dc1249f1..5a81c254c 100644 --- a/src/lib/object_store/DBObject.h +++ b/src/lib/object_store/DBObject.h @@ -62,6 +62,9 @@ class DBObject : public OSObject // create tables to support storage of attributes for the object. bool createTables(); + // update schema to support new features with dbs from previous versions. + bool migrateTables(); + // drop tables that support storage of attributes for the object. bool dropTables(); diff --git a/src/lib/object_store/DBToken.cpp b/src/lib/object_store/DBToken.cpp index 53b91f478..498eb58ef 100644 --- a/src/lib/object_store/DBToken.cpp +++ b/src/lib/object_store/DBToken.cpp @@ -122,7 +122,7 @@ DBToken::DBToken(const std::string &baseDir, const std::string &tokenName, int u // First create the tables that support storage of object attributes and then insert the object containing // the token info into the database. - if (!tokenObject.createTables() || !tokenObject.insert() || tokenObject.objectId()!=DBTOKEN_OBJECT_TOKENINFO) + if (!tokenObject.createTables() || !tokenObject.migrateTables() || !tokenObject.insert() || tokenObject.objectId()!=DBTOKEN_OBJECT_TOKENINFO) { tokenObject.dropConnection(); @@ -211,7 +211,7 @@ DBToken::DBToken(const std::string &baseDir, const std::string &tokenName, int u DBObject tokenObject(_connection); // First find the token obect that indicates the token is properly initialized. - if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO)) + if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO) || !tokenObject.migrateTables()) { tokenObject.dropConnection();