From 025a68daa2d80c3578c67b26e8cdda12f0239a2c Mon Sep 17 00:00:00 2001 From: Bartlomiej Grzelewski Date: Mon, 1 Dec 2014 17:12:26 +0100 Subject: [PATCH] DBDataType refactoring. Change-Id: I080034c971ae5d8f75747d2091fb34ca0a7c78fa --- .../client-async/client-manager-async-impl.cpp | 6 +- src/manager/client-async/storage-receiver.cpp | 81 +++-------- src/manager/client/client-common.cpp | 9 +- src/manager/client/client-manager-impl.cpp | 11 +- src/manager/common/protocols.cpp | 30 ---- src/manager/common/protocols.h | 156 ++++++++++++++++++--- src/manager/service/access-control.cpp | 15 +- src/manager/service/ckm-logic.cpp | 72 +++------- src/manager/service/ckm-service.cpp | 10 +- src/manager/service/db-crypto.cpp | 7 +- 10 files changed, 202 insertions(+), 195 deletions(-) diff --git a/src/manager/client-async/client-manager-async-impl.cpp b/src/manager/client-async/client-manager-async-impl.cpp index e23eca8..30aa462 100644 --- a/src/manager/client-async/client-manager-async-impl.cpp +++ b/src/manager/client-async/client-manager-async-impl.cpp @@ -49,7 +49,11 @@ void ManagerAsync::Impl::saveKey(const ObserverPtr& observer, observer->ReceivedError(CKM_API_ERROR_INPUT_PARAM); return; } - saveBinaryData(observer, alias, toDBDataType(key->getType()), key->getDER(), policy); + Try { + saveBinaryData(observer, alias, DBDataType(key->getType()), key->getDER(), policy); + } Catch(DBDataType::Exception::Base) { + observer->ReceivedError(CKM_API_ERROR_INPUT_PARAM); + } } void ManagerAsync::Impl::saveCertificate(const ObserverPtr& observer, diff --git a/src/manager/client-async/storage-receiver.cpp b/src/manager/client-async/storage-receiver.cpp index e9c5183..cb9560c 100644 --- a/src/manager/client-async/storage-receiver.cpp +++ b/src/manager/client-async/storage-receiver.cpp @@ -28,41 +28,6 @@ namespace CKM { -namespace { - -enum class DataType { - KEY, - CERT, - DATA -}; - -DataType type(int dbDataType) -{ - switch(static_cast(dbDataType)) - { - case DBDataType::KEY_RSA_PUBLIC: - case DBDataType::KEY_RSA_PRIVATE: - case DBDataType::KEY_ECDSA_PUBLIC: - case DBDataType::KEY_ECDSA_PRIVATE: - case DBDataType::KEY_DSA_PUBLIC: - case DBDataType::KEY_DSA_PRIVATE: - case DBDataType::KEY_AES: - return DataType::KEY; - - case DBDataType::CERTIFICATE: - return DataType::CERT; - - case DBDataType::BINARY_DATA: - return DataType::DATA; - - default: - LogError("Unsupported data type: " <ReceivedKey(KeyImpl(rawData)); - break; - case DataType::CERT: + else if (type.isCertificate()) m_observer->ReceivedCertificate(CertificateImpl(rawData, DataFormat::FORM_DER)); - break; - case DataType::DATA: + else if (type.isBinaryData()) m_observer->ReceivedData(std::move(rawData)); - break; - } + else + m_observer->ReceivedError(CKM_API_ERROR_BAD_RESPONSE); } void StorageReceiver::parseGetListCommand() @@ -172,18 +134,16 @@ void StorageReceiver::parseGetListCommand() for(const auto &it : labelNameVector) aliasVector.push_back( AliasSupport::merge(it.first, it.second) ); - switch(type(dataType)) - { - case DataType::KEY: + DBDataType type(dataType); + + if (type.isKey()) m_observer->ReceivedKeyAliasVector(std::move(aliasVector)); - break; - case DataType::CERT: + else if (type.isCertificate()) m_observer->ReceivedCertificateAliasVector(std::move(aliasVector)); - break; - case DataType::DATA: + else if (type.isBinaryData()) m_observer->ReceivedDataAliasVector(std::move(aliasVector)); - break; - } + else + m_observer->ReceivedError(CKM_API_ERROR_BAD_RESPONSE); } void StorageReceiver::parseSaveCommand() @@ -197,18 +157,15 @@ void StorageReceiver::parseSaveCommand() return; } - switch(type(dataType)) - { - case DataType::KEY: + DBDataType type(dataType); + if (type.isKey()) m_observer->ReceivedSaveKey(); - break; - case DataType::CERT: + else if (type.isCertificate()) m_observer->ReceivedSaveCertificate(); - break; - case DataType::DATA: + else if (type.isBinaryData()) m_observer->ReceivedSaveData(); - break; - } + else + m_observer->ReceivedError(CKM_API_ERROR_BAD_RESPONSE); } void StorageReceiver::parseRemoveCommand() diff --git a/src/manager/client/client-common.cpp b/src/manager/client/client-common.cpp index 73cacec..c903c18 100644 --- a/src/manager/client/client-common.cpp +++ b/src/manager/client/client-common.cpp @@ -320,9 +320,11 @@ int try_catch(const std::function& func) int retval = CKM_API_ERROR_UNKNOWN; try { return func(); - } catch (MessageBuffer::Exception::Base &e) { + } catch (const MessageBuffer::Exception::Base &e) { LogError("CKM::MessageBuffer::Exception " << e.DumpToString()); - } catch (std::exception &e) { + } catch (const DBDataType::Exception::Base &e) { + LogError("CKM::DBDataType::Exception " << e.DumpToString()); + } catch (const std::exception &e) { LogError("STD exception " << e.what()); } catch (...) { LogError("Unknown exception occured"); @@ -337,6 +339,9 @@ void try_catch_async(const std::function& func, const std::functiongetType()), key->getDER(), policy); + Try { + return saveBinaryData(alias, DBDataType(key->getType()), key->getDER(), policy); + } Catch (DBDataType::Exception::Base) { + LogError("Error in key conversion. Could not convert KeyType::NONE to DBDataType!"); + } + return CKM_API_ERROR_INPUT_PARAM; } int ManagerImpl::saveCertificate( @@ -158,7 +163,7 @@ int ManagerImpl::getBinaryData( int counter; int tmpDataType; recv.Deserialize(command, counter, retCode, tmpDataType, rawData); - recvDataType = static_cast(tmpDataType); + recvDataType = DBDataType(tmpDataType); if (counter != m_counter) { return CKM_API_ERROR_UNKNOWN; @@ -196,7 +201,7 @@ int ManagerImpl::getKey(const Alias &alias, const Password &password, KeyShPtr & int ManagerImpl::getCertificate(const Alias &alias, const Password &password, CertificateShPtr &cert) { - DBDataType recvDataType = DBDataType::CERTIFICATE; + DBDataType recvDataType; RawBuffer rawData; int retCode = getBinaryData( diff --git a/src/manager/common/protocols.cpp b/src/manager/common/protocols.cpp index a9c9bdc..67cb36c 100644 --- a/src/manager/common/protocols.cpp +++ b/src/manager/common/protocols.cpp @@ -34,36 +34,6 @@ char const * const SERVICE_SOCKET_CKM_STORAGE = "/tmp/.central-key-manager-api-s char const * const SERVICE_SOCKET_OCSP = "/tmp/.central-key-manager-api-ocsp.sock"; char const * const LABEL_NAME_SEPARATOR = " "; -DBDataType toDBDataType(KeyType key) { - switch(key) { - case KeyType::KEY_RSA_PUBLIC: return DBDataType::KEY_RSA_PUBLIC; - case KeyType::KEY_RSA_PRIVATE: return DBDataType::KEY_RSA_PRIVATE; - case KeyType::KEY_DSA_PUBLIC: return DBDataType::KEY_DSA_PUBLIC; - case KeyType::KEY_DSA_PRIVATE: return DBDataType::KEY_DSA_PRIVATE; - case KeyType::KEY_ECDSA_PUBLIC: return DBDataType::KEY_ECDSA_PUBLIC; - case KeyType::KEY_ECDSA_PRIVATE: return DBDataType::KEY_ECDSA_PRIVATE; - case KeyType::KEY_AES: return DBDataType::KEY_AES; - default: - // TODO - throw 1; - } -} - -KeyType toKeyType(DBDataType dbtype) { - switch(dbtype) { - case DBDataType::KEY_RSA_PUBLIC: return KeyType::KEY_RSA_PUBLIC; - case DBDataType::KEY_RSA_PRIVATE: return KeyType::KEY_RSA_PRIVATE; - case DBDataType::KEY_DSA_PUBLIC: return KeyType::KEY_DSA_PUBLIC; - case DBDataType::KEY_DSA_PRIVATE: return KeyType::KEY_DSA_PRIVATE; - case DBDataType::KEY_ECDSA_PRIVATE: return KeyType::KEY_ECDSA_PRIVATE; - case DBDataType::KEY_ECDSA_PUBLIC: return KeyType::KEY_ECDSA_PUBLIC; - case DBDataType::KEY_AES: return KeyType::KEY_AES; - default: - // TODO - throw 1; - } -} - namespace { const char* const DB_PERM_READ = "R"; const char* const DB_PERM_READ_REMOVE = "RD"; diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index fe439f5..7487cbe 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -22,9 +22,12 @@ */ #pragma once +#include #include + #include +#include #include namespace CKM { @@ -62,26 +65,137 @@ enum class LogicCommand : int { // for backward compatibility append new at the end }; -// Do not use DB_KEY_FIRST and DB_KEY_LAST in the code. -// This values are only for db module! -enum class DBDataType : int { - DB_DATA_TYPE_FIRST, - DB_KEY_FIRST = DB_DATA_TYPE_FIRST, - - KEY_RSA_PUBLIC = DB_KEY_FIRST, - KEY_RSA_PRIVATE, - KEY_ECDSA_PUBLIC, - KEY_ECDSA_PRIVATE, - KEY_DSA_PUBLIC, - KEY_DSA_PRIVATE, - KEY_AES, - DB_KEY_LAST = KEY_AES, - CERTIFICATE, - BINARY_DATA, - // add new items here - - // keep in mind to modify DB_DATA_TYPE_LAST when doing changes! - DB_DATA_TYPE_LAST = BINARY_DATA +class DBDataType { +public: + class Exception { + public: + DECLARE_EXCEPTION_TYPE(CKM::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, OutOfRange) + }; + + enum DataType { + KEY_RSA_PUBLIC, + KEY_RSA_PRIVATE, + KEY_ECDSA_PUBLIC, + KEY_ECDSA_PRIVATE, + KEY_DSA_PUBLIC, + KEY_DSA_PRIVATE, + KEY_AES, + CERTIFICATE, + BINARY_DATA, + // Special types to support database, + DB_FIRST = KEY_RSA_PUBLIC, + DB_LAST = BINARY_DATA, + DB_KEY_FIRST = KEY_RSA_PUBLIC, + DB_KEY_LAST = KEY_AES, + }; + + DBDataType() + : m_dataType(BINARY_DATA) + {} + + DBDataType(DataType data) + : m_dataType(data) + { + if (!isInRange(data)) + ThrowMsg(Exception::OutOfRange, "Invalid conversion from DataType to DBDataType"); + } + + explicit DBDataType(KeyType key) { + switch(key) { + case KeyType::KEY_RSA_PUBLIC: m_dataType = DBDataType::KEY_RSA_PUBLIC; break; + case KeyType::KEY_RSA_PRIVATE: m_dataType = DBDataType::KEY_RSA_PRIVATE; break; + case KeyType::KEY_DSA_PUBLIC: m_dataType = DBDataType::KEY_DSA_PUBLIC; break; + case KeyType::KEY_DSA_PRIVATE: m_dataType = DBDataType::KEY_DSA_PRIVATE; break; + case KeyType::KEY_ECDSA_PUBLIC: m_dataType = DBDataType::KEY_ECDSA_PUBLIC; break; + case KeyType::KEY_ECDSA_PRIVATE: m_dataType = DBDataType::KEY_ECDSA_PRIVATE; break; + case KeyType::KEY_AES: m_dataType = DBDataType::KEY_AES; break; + default: + ThrowMsg(Exception::OutOfRange, "Invalid conversion from KeyType to DBDataType"); + } + } + + explicit DBDataType(int data) + : m_dataType(static_cast(data)) + { + if (!isInRange(data)) + ThrowMsg(Exception::OutOfRange, "Invalid conversion from int to DBDataType"); + } + + DBDataType(const DBDataType &) = default; + DBDataType& operator=(const DBDataType &) = default; + + operator int () const { + return static_cast(m_dataType); + } + + operator KeyType () const { + switch(m_dataType) { + case DBDataType::KEY_RSA_PUBLIC: return KeyType::KEY_RSA_PUBLIC; + case DBDataType::KEY_RSA_PRIVATE: return KeyType::KEY_RSA_PRIVATE; + case DBDataType::KEY_DSA_PUBLIC: return KeyType::KEY_DSA_PUBLIC; + case DBDataType::KEY_DSA_PRIVATE: return KeyType::KEY_DSA_PRIVATE; + case DBDataType::KEY_ECDSA_PRIVATE: return KeyType::KEY_ECDSA_PRIVATE; + case DBDataType::KEY_ECDSA_PUBLIC: return KeyType::KEY_ECDSA_PUBLIC; + case DBDataType::KEY_AES: return KeyType::KEY_AES; + default: + ThrowMsg(Exception::OutOfRange, "Invalid conversion from DBDataType to KeyType"); + } + } + + bool operator==(const DBDataType &second) const { + return m_dataType == second.m_dataType; + } + + bool isKey() const { + if (DB_KEY_FIRST <= m_dataType && DB_KEY_LAST >= m_dataType) + return true; + return false; + } + + bool isKeyPrivate() const { + switch (m_dataType) { + case KEY_RSA_PRIVATE: + case KEY_DSA_PRIVATE: + case KEY_ECDSA_PRIVATE: + return true; + default: + return false; + } + } + + bool isKeyPublic() const { + switch (m_dataType) { + case KEY_RSA_PUBLIC: + case KEY_DSA_PUBLIC: + case KEY_ECDSA_PUBLIC: + return true; + default: + return false; + } + } + + bool isCertificate() const { + return m_dataType == CERTIFICATE; + } + + bool isBinaryData() const { + return m_dataType == BINARY_DATA; + } + + static bool isInRange(int data) { + if (data < static_cast(DB_FIRST)) + return false; + if (data > static_cast(DB_LAST)) + return false; + return true; + } + + // it's not virtual with a reason! + ~DBDataType(){} + +private: + DataType m_dataType; }; // (client side) Alias = (service side) Label::Name @@ -90,8 +204,6 @@ typedef std::string Name; typedef std::vector > LabelNameVector; -DBDataType toDBDataType(KeyType key); -KeyType toKeyType(DBDataType dbDataType); const char* toDBPermission(Permission access_right_type); Permission toPermission(const std::string &input_DB_data); diff --git a/src/manager/service/access-control.cpp b/src/manager/service/access-control.cpp index 7cf0e6c..1bfcacf 100644 --- a/src/manager/service/access-control.cpp +++ b/src/manager/service/access-control.cpp @@ -125,19 +125,8 @@ int AccessControl::canExport( return CKM_API_ERROR_NOT_EXPORTABLE; // prevent extracting private keys during cc-mode on - if( isCCMode() ) - { - switch(row.dataType) - { - case DBDataType::KEY_RSA_PRIVATE: - case DBDataType::KEY_ECDSA_PRIVATE: - case DBDataType::KEY_DSA_PRIVATE: - return CKM_API_ERROR_BAD_REQUEST; - - default: - break; - } - } + if (isCCMode() && row.dataType.isKeyPrivate()) + return CKM_API_ERROR_BAD_REQUEST; return CKM_API_SUCCESS; } diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index c736ad4..0029bf0 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -293,34 +293,16 @@ int CKMLogic::saveDataHelper( void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const { // verify the data integrity - switch(dataType) - { - case DBDataType::KEY_RSA_PUBLIC: - case DBDataType::KEY_RSA_PRIVATE: - case DBDataType::KEY_ECDSA_PUBLIC: - case DBDataType::KEY_ECDSA_PRIVATE: - case DBDataType::KEY_DSA_PUBLIC: - case DBDataType::KEY_DSA_PRIVATE: - case DBDataType::KEY_AES: - { - KeyShPtr output_key = CKM::Key::create(input_data); - if(output_key.get() == NULL) - ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data"); - break; - } - - case DBDataType::CERTIFICATE: - { - CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER); - if(cert.get() == NULL) - ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data"); - break; - } - - // TODO: add here BINARY_DATA verification, i.e: max size etc. - - default: break; - } + if (dataType.isKey()) { + KeyShPtr output_key = CKM::Key::create(input_data); + if(output_key.get() == NULL) + ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data"); + } else if (dataType.isCertificate()) { + CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER); + if(cert.get() == NULL) + ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data"); + } + // TODO: add here BINARY_DATA verification, i.e: max size etc. } RawBuffer CKMLogic::saveData( @@ -429,26 +411,15 @@ int CKMLogic::readDataRowHelper(const Name &name, DBCrypto & database, DBRow &row) { - // read row DBCrypto::DBRowOptional row_optional; - // TODO: move this check into request deserialization - if((static_cast(dataType)(DBDataType::DB_DATA_TYPE_FIRST)) || - (static_cast(dataType)>static_cast(DBDataType::DB_DATA_TYPE_LAST))) - { - LogError("Unknown type of requested data: " << (int)dataType); - return CKM_API_ERROR_BAD_REQUEST; - } - // TODO: provide internal type rather than using DB types in socket comms - else if ((dataType >= DBDataType::DB_KEY_FIRST) && - (dataType <= DBDataType::DB_KEY_LAST)) + if (dataType.isKey()) { // read all key types row_optional = database.getDBRow(name, ownerLabel, DBDataType::DB_KEY_FIRST, DBDataType::DB_KEY_LAST); - } - else { + } else { // read anything else row_optional = database.getDBRow(name, ownerLabel, @@ -578,24 +549,13 @@ RawBuffer CKMLogic::getDataList( auto &database = m_userDataMap[cred.uid].database; Try { - // list names - // TODO: move this check into request deserialization - if((static_cast(dataType)(DBDataType::DB_DATA_TYPE_FIRST)) || - (static_cast(dataType)>static_cast(DBDataType::DB_DATA_TYPE_LAST))) - { - LogError("Unknown type of requested data: " << (int)dataType); - retCode = CKM_API_ERROR_BAD_REQUEST; - } - // TODO: provide internal type rather than using DB types in socket comms - else if ((dataType >= DBDataType::DB_KEY_FIRST) && (dataType <= DBDataType::DB_KEY_LAST)) - { + if (dataType.isKey()) { // list all key types database.listNames(cred.smackLabel, labelNameVector, DBDataType::DB_KEY_FIRST, DBDataType::DB_KEY_LAST); - } - else { + } else { // list anything else database.listNames(cred.smackLabel, labelNameVector, @@ -665,7 +625,7 @@ int CKMLogic::createKeyPairHelper( auto &database = m_userDataMap[cred.uid].database; DBCrypto::Transaction transaction(&database); retCode = saveDataHelper(cred, - toDBDataType(prv.getType()), + DBDataType(prv.getType()), namePrivate, labelPrivate, prv.getDER(), @@ -675,7 +635,7 @@ int CKMLogic::createKeyPairHelper( return retCode; retCode = saveDataHelper(cred, - toDBDataType(pub.getType()), + DBDataType(pub.getType()), namePublic, labelPublic, pub.getDER(), diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 1a8cdaf..61ffa43 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -95,8 +95,12 @@ bool CKMService::processOne( LogError("Broken protocol. Closing socket."); } Catch (Exception::BrokenProtocol) { LogError("Broken protocol. Closing socket."); + } catch (const DBDataType::Exception::Base &e) { + LogError("Closing socket. DBDataType::Exception: " << e.DumpToString()); } catch (const std::string &e) { LogError("String exception(" << e << "). Closing socket"); + } catch (const std::exception &e) { + LogError("Std exception:: " << e.what()); } catch (...) { LogError("Unknown exception. Closing socket."); } @@ -193,7 +197,7 @@ RawBuffer CKMService::processStorage(Credentials &cred, MessageBuffer &buffer) return m_logic->saveData( cred, msgID, - static_cast(tmpDataType), + DBDataType(tmpDataType), name, label, rawData, @@ -215,7 +219,7 @@ RawBuffer CKMService::processStorage(Credentials &cred, MessageBuffer &buffer) return m_logic->getData( cred, msgID, - static_cast(tmpDataType), + DBDataType(tmpDataType), name, label, password); @@ -226,7 +230,7 @@ RawBuffer CKMService::processStorage(Credentials &cred, MessageBuffer &buffer) return m_logic->getDataList( cred, msgID, - static_cast(tmpDataType)); + DBDataType(tmpDataType)); } case LogicCommand::CREATE_KEY_PAIR_RSA: case LogicCommand::CREATE_KEY_PAIR_DSA: diff --git a/src/manager/service/db-crypto.cpp b/src/manager/service/db-crypto.cpp index 2ec31e0..f465add 100644 --- a/src/manager/service/db-crypto.cpp +++ b/src/manager/service/db-crypto.cpp @@ -283,7 +283,7 @@ using namespace DB; row.name = name; row.ownerLabel = ownerLabel; row.exportable = selectCommand->GetColumnInteger(0); - row.dataType = static_cast(selectCommand->GetColumnInteger(1)); + row.dataType = DBDataType(selectCommand->GetColumnInteger(1)); row.algorithmType = static_cast(selectCommand->GetColumnInteger(2)); row.encryptionScheme = selectCommand->GetColumnInteger(3); row.iv = selectCommand->GetColumnBlob(4); @@ -318,6 +318,7 @@ using namespace DB; { return getDBRow(name, ownerLabel, type, type); } + DBCrypto::DBRowOptional DBCrypto::getDBRow( const Name &name, const Label &ownerLabel, @@ -327,8 +328,8 @@ using namespace DB; Try { SqlConnection::DataCommandUniquePtr selectCommand = m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL); - selectCommand->BindInteger(1, static_cast(typeRangeStart)); - selectCommand->BindInteger(2, static_cast(typeRangeStop)); + selectCommand->BindInteger(1, typeRangeStart); + selectCommand->BindInteger(2, typeRangeStop); // name table reference selectCommand->BindString (101, name.c_str()); -- 2.7.4