Replace error codes with exceptions in FileSystem module.
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 23 Jan 2015 15:50:21 +0000 (16:50 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 17 Feb 2015 11:09:27 +0000 (12:09 +0100)
Change-Id: Id099e6a3cb5b6db69dedc19c781db4d85f7518a9

src/include/ckm/ckm-error.h
src/manager/client/client-error.cpp
src/manager/service/ckm-logic.cpp
src/manager/service/file-system.cpp
src/manager/service/file-system.h

index 7688a65..671ec25 100644 (file)
@@ -84,12 +84,15 @@ extern "C" {
 /*! \brief   indicating that a provided file or binary has not a valid format */
 #define CKM_API_ERROR_INVALID_FORMAT -17
 
-/*! \brief   indicating that provided file doesn't exists or cannot be accessed in the file system */
+/*! \brief   deprecated please do not use it. This value was replaced with CKM_API_ERROR_FILE_SYSTEM */
 #define CKM_API_ERROR_FILE_ACCESS_DENIED -18
 
 /*! \brief   indicating that keys are not exportable and could not be returned to client */
 #define CKM_API_ERROR_NOT_EXPORTABLE -19
 
+/*! \brief   indicating that files are corrupted or access to files was denied */
+#define CKM_API_ERROR_FILE_SYSTEM -20
+
 #define CKM_API_OCSP_STATUS_GOOD                (1<<0)
 #define CKM_API_OCSP_STATUS_UNSUPPORTED         (1<<1)
 #define CKM_API_OCSP_STATUS_UNKNOWN             (1<<2)
index 4f41236..79f3103 100644 (file)
@@ -47,11 +47,14 @@ const char * ErrorToString(int error) {
         ERRORDESCRIBE(CKM_API_ERROR_INVALID_FORMAT);
         ERRORDESCRIBE(CKM_API_ERROR_FILE_ACCESS_DENIED);
         ERRORDESCRIBE(CKM_API_ERROR_NOT_EXPORTABLE);
+        ERRORDESCRIBE(CKM_API_ERROR_FILE_SYSTEM);
         ERRORDESCRIBE(CKM_API_ERROR_UNKNOWN);
     default:
         return "Error not defined";
     }
 }
 
+#undef ERRORDESCRIBE
+
 } // namespace CKM
 
index 445660a..86ce228 100644 (file)
@@ -68,7 +68,7 @@ void CKMLogic::loadDKEKFile(uid_t user, const Password &password, bool apiReq) {
     auto wrappedDKEKMain = fs.getDKEK();
     auto wrappedDKEKBackup = fs.getDKEKBackup();
 
-    if (wrappedDKEKMain.empty() && wrappedDKEKBackup.empty()) {
+    if (wrappedDKEKMain.empty()) {
         wrappedDKEKMain = KeyProvider::generateDomainKEK(std::to_string(user), password);
         fs.saveDKEK(wrappedDKEKMain);
     }
@@ -95,6 +95,7 @@ void CKMLogic::chooseDKEKFile(
         handle.keyProvider = KeyProvider(first, password);
         handle.isMainDKEK = true;
     } catch (const KeyProvider::Exception::Base &e) {
+        // Second buffer is empty. Lets rethrow first error
         if (second.empty())
             throw;
         handle.keyProvider = KeyProvider(second, password);
@@ -107,7 +108,7 @@ void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
 
     FileSystem fs(user);
     if (handle.isMainDKEK)
-        fs.saveDKEKBackup(fs.getDKEK());
+        fs.createDKEKBackup();
 
     fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
 
@@ -116,7 +117,6 @@ void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
 }
 
 RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password, bool apiRequest) {
-    // TODO try catch for all errors that should be supported by error code
     int retCode = CKM_API_SUCCESS;
 
     try {
@@ -155,6 +155,9 @@ RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password, bool api
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic error: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("FileSystem error: " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
     } catch (const CKM::Exception &e) {
         LogError("CKM::Exception: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
@@ -209,6 +212,9 @@ RawBuffer CKMLogic::changeUserPassword(
     } catch (const KeyProvider::Exception::Base &e) {
         LogError("Error in KeyProvider " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
     } catch (const CKM::Exception &e) {
         LogError("CKM::Exception: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
@@ -222,11 +228,19 @@ RawBuffer CKMLogic::resetUserPassword(
     const Password &newPassword)
 {
     int retCode = CKM_API_SUCCESS;
-    // TODO try-catch
-    if (0 == m_userDataMap.count(user)) {
-        retCode = CKM_API_ERROR_BAD_REQUEST;
-    } else {
-        saveDKEKFile(user, newPassword);
+
+    try {
+        if (0 == m_userDataMap.count(user)) {
+            retCode = CKM_API_ERROR_BAD_REQUEST;
+        } else {
+            saveDKEKFile(user, newPassword);
+        }
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     return MessageBuffer::Serialize(retCode).Pop();
@@ -258,6 +272,12 @@ RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
     } catch (const DBCrypto::Exception::TransactionError &e) {
         LogError("DBCrypto transaction failed with message " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     return MessageBuffer::Serialize(retCode).Pop();
@@ -386,6 +406,12 @@ RawBuffer CKMLogic::saveData(
         } catch (const DBCrypto::Exception::TransactionError &e) {
             LogError("DBCrypto transaction failed with message " << e.GetMessage());
             retCode = CKM_API_ERROR_DB_ERROR;
+        } catch (const FileSystem::Exception::Base &e) {
+            LogError("Error in FileSystem " << e.GetMessage());
+            retCode = CKM_API_ERROR_FILE_SYSTEM;
+        } catch (const CKM::Exception &e) {
+            LogError("CKM::Exception: " << e.GetMessage());
+            retCode = CKM_API_ERROR_SERVER_ERROR;
         }
     }
 
@@ -469,6 +495,9 @@ RawBuffer CKMLogic::savePKCS12(
         } catch (const DBCrypto::Exception::TransactionError &e) {
             LogError("DBCrypto transaction failed with message " << e.GetMessage());
             retCode = CKM_API_ERROR_DB_ERROR;
+        } catch (const CKM::Exception &e) {
+            LogError("CKM::Exception: " << e.GetMessage());
+            retCode = CKM_API_ERROR_SERVER_ERROR;
         }
     }
 
@@ -751,6 +780,9 @@ RawBuffer CKMLogic::getData(
     } catch (const DBCrypto::Exception::Base &e) {
         LogError("DBCrypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     if (CKM_API_SUCCESS != retCode) {
@@ -834,6 +866,9 @@ RawBuffer CKMLogic::getPKCS12(
     } catch (const DBCrypto::Exception::Base &e) {
         LogError("DBCrypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
@@ -1063,6 +1098,9 @@ RawBuffer CKMLogic::createKeyPair(
     } catch (DBCrypto::Exception::InternalError &e) {
         LogDebug("DBCrypto internal error: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
index 084372b..7a02fe1 100644 (file)
@@ -91,9 +91,16 @@ std::string FileSystem::getRemovedAppsPath() const {
 RawBuffer FileSystem::loadFile(const std::string &path) const {
     std::ifstream is(path);
 
-    if (is.fail())
+    if (is.fail() && ENOENT == errno)
         return RawBuffer();
 
+    if (is.fail()) {
+        auto description = GetErrnoString(errno);
+        LogError("Error opening file: " << path << " Reason: " << description);
+        ThrowMsg(Exception::OpenFailed,
+                 "Error opening file: " << path << " Reason: " << description);
+    }
+
     std::istreambuf_iterator<char> begin(is),end;
     std::vector<char> buff(begin,end); // This trick does not work with boost vector
 
@@ -117,54 +124,66 @@ RawBuffer FileSystem::getDBDEK() const
     return loadFile(getDBDEKPath());
 }
 
-bool FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
+void FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
     std::ofstream os(path, std::ios::out | std::ofstream::binary | std::ofstream::trunc);
     std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
-    if (os.fail())
-        return false;
 
     // Prevent desynchronization in batter remove test.
     os.flush();
     fsync(FstreamAccessors<std::ofstream>::GetFd(os)); // flush kernel space buffer
     os.close();
-    return !os.fail();
+
+    if (os.fail())
+        ThrowMsg(Exception::SaveFailed, "Failed to save file: " << path);
 }
 
-bool FileSystem::saveDKEK(const RawBuffer &buffer) const {
-    return saveFile(getDKEKPath(), buffer);
+void FileSystem::saveDKEK(const RawBuffer &buffer) const {
+    saveFile(getDKEKPath(), buffer);
 }
 
-bool FileSystem::saveDKEKBackup(const RawBuffer &buffer) const {
-    return saveFile(getDKEKBackupPath(), buffer);
+void FileSystem::moveFile(const std::string &from, const std::string &to) const {
+    if (0 == ::rename(from.c_str(), to.c_str())) {
+        return;
+    }
+    auto description = GetErrnoString(errno);
+    LogError("Error during rename file DKEKBackup to DKEK: " << description);
+    ThrowMsg(Exception::RenameFailed,
+             "Error during rename file DKEKBackup to DKEK: " << description);
 }
 
-bool FileSystem::restoreDKEK() const {
-    if (0 == ::rename(getDKEKBackupPath().c_str(), getDKEKPath().c_str()))
-        return true;
-    int err = errno;
-    LogError("Error in rename file DKEKBackup to DKEK: " << GetErrnoString(err));
-    return false;
+void FileSystem::restoreDKEK() const {
+    moveFile(getDKEKBackupPath(), getDKEKPath());
 }
 
-bool FileSystem::removeDKEKBackup() const {
-    if (0 == unlink(getDKEKBackupPath().c_str()))
-        return true;
-    int err = errno;
-    LogError("Error in unlink file DKEKBackup: " << GetErrnoString(err));
-    return false;
+void FileSystem::createDKEKBackup() const {
+    moveFile(getDKEKPath(), getDKEKBackupPath());
 }
 
-bool FileSystem::saveDBDEK(const RawBuffer &buffer) const {
-    return saveFile(getDBDEKPath(), buffer);
+void FileSystem::removeDKEKBackup() const {
+    if (0 == unlink(getDKEKBackupPath().c_str())) {
+        return;
+    }
+    // Backup is accessible only during "change password transaction"
+    auto description = GetErrnoString(errno);
+    LogDebug("Error in unlink file DKEKBackup: " << description);
+}
+
+void FileSystem::saveDBDEK(const RawBuffer &buffer) const {
+    saveFile(getDBDEKPath(), buffer);
 }
 
-bool FileSystem::addRemovedApp(const std::string &smackLabel) const
+void FileSystem::addRemovedApp(const std::string &smackLabel) const
 {
     std::ofstream outfile;
     outfile.open(getRemovedAppsPath(), std::ios_base::app);
     outfile << smackLabel << std::endl;
     outfile.close();
-    return !outfile.fail();
+    if (outfile.fail()) {
+        auto desc = GetErrnoString(errno);
+        LogError("Could not update file: " << getRemovedAppsPath() << " Reason: " << desc);
+        ThrowMsg(Exception::SaveFailed,
+                 "Could not update file: " << getRemovedAppsPath() << " Reason: " << desc);
+    }
 }
 
 AppLabelVector FileSystem::clearRemovedsApps() const
@@ -192,8 +211,7 @@ int FileSystem::init() {
     errno = 0;
     if ((mkdir(CKM_DATA_PATH.c_str(), 0700)) && (errno != EEXIST)) {
         int err = errno;
-        LogError("Error in mkdir. Data directory could not be created. Errno: "
-            << err << " (" << GetErrnoString(err) << ")");
+        LogError("Error in mkdir " << CKM_DATA_PATH << ". Reason: " << GetErrnoString(err));
         return -1; // TODO set up some error code
     }
     return 0;
@@ -222,7 +240,6 @@ UidVector FileSystem::getUIDsFromDBFile() {
     struct dirent* pDirEntry = NULL;
 
     while ( (!readdir_r(dirp.get(), pEntry.get(), &pDirEntry)) && pDirEntry ) {
-
         // Ignore files with diffrent prefix
         if (strncmp(pDirEntry->d_name, CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size())) {
             continue;
@@ -263,7 +280,7 @@ int FileSystem::removeUserData() const {
     if (unlink(getDKEKBackupPath().c_str())) {
         retCode = -1;
         err = errno;
-        LogError("Error in unlink user backup DKEK: " << getDKEKBackupPath()
+        LogDebug("Unlink user backup DKEK failed (file probably does not exists): " << getDKEKBackupPath()
             << "Errno: " << errno << " " << GetErrnoString(err));
     }
 
index 4bc44ad..9058c42 100644 (file)
@@ -32,6 +32,14 @@ typedef std::vector<uid_t> UidVector;
 
 class FileSystem {
 public:
+    class Exception {
+    public:
+        DECLARE_EXCEPTION_TYPE(CKM::Exception, Base)
+        DECLARE_EXCEPTION_TYPE(Base, OpenFailed)
+        DECLARE_EXCEPTION_TYPE(Base, SaveFailed)
+        DECLARE_EXCEPTION_TYPE(Base, RenameFailed)
+    };
+
     FileSystem(uid_t uid);
 
     std::string getDBPath() const;
@@ -39,21 +47,21 @@ public:
     // Domain Key Encryption Key
     RawBuffer getDKEK() const;
     RawBuffer getDKEKBackup() const;
-    bool saveDKEK(const RawBuffer &buffer) const;
+    void saveDKEK(const RawBuffer &buffer) const;
 
     // Functions required in "password change transaction"
-    bool saveDKEKBackup(const RawBuffer &buffer) const;
-    bool restoreDKEK() const; // delete DKEK and move DKEKBackup -> DKEK
-    bool removeDKEKBackup() const;  // delete DKEKBackup
+    void createDKEKBackup() const;
+    void restoreDKEK() const; // delete DKEK and move DKEKBackup -> DKEK
+    void removeDKEKBackup() const;  // delete DKEKBackup
 
     // Database Data Encryption Key
     RawBuffer getDBDEK() const;
-    bool saveDBDEK(const RawBuffer &buffer) const;
+    void saveDBDEK(const RawBuffer &buffer) const;
 
     // Remove all ckm data related to user
     int removeUserData() const;
 
-    bool addRemovedApp(const std::string &smackLabel) const;
+    void addRemovedApp(const std::string &smackLabel) const;
     AppLabelVector clearRemovedsApps() const;
 
     static int init();
@@ -66,8 +74,9 @@ protected:
     std::string getDKEKBackupPath() const;
     std::string getDBDEKPath() const;
     RawBuffer loadFile(const std::string &path) const;
-    bool saveFile(const std::string &path, const RawBuffer &buffer) const;
+    void saveFile(const std::string &path, const RawBuffer &buffer) const;
     std::string getRemovedAppsPath() const;
+    void moveFile(const std::string &from, const std::string &to) const;
 
     uid_t m_uid;
 };