Added security checks for symlinks

Added security checks which prevents service from interacting with
symlinks. It is not possible to list/delete/read/write to symlinks.

Tested:
Added unit tests which confirm that:
- Symlinks cannot be removed
- Symlinks are not listed
- Symlinks cannot be overwritten
- Symlinks cannot be read

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I50d6d10dac81fd454e7e30520a7c47d5146be58c
diff --git a/src/persistent_json_storage.cpp b/src/persistent_json_storage.cpp
index 896c8a9..0dc66ad 100644
--- a/src/persistent_json_storage.cpp
+++ b/src/persistent_json_storage.cpp
@@ -5,6 +5,8 @@
 #include <fstream>
 #include <stdexcept>
 
+using namespace std::literals::string_literals;
+
 PersistentJsonStorage::PersistentJsonStorage(const DirectoryPath& directory) :
     directory(directory)
 {}
@@ -28,6 +30,8 @@
                 ", ec=" + std::to_string(ec.value()) + ": " + ec.message());
         }
 
+        assertThatPathIsNotSymlink(path);
+
         std::ofstream file(path);
         file << data;
         if (!file)
@@ -48,6 +52,12 @@
 bool PersistentJsonStorage::remove(const FilePath& filePath)
 {
     const auto path = join(directory, filePath);
+
+    if (std::filesystem::is_symlink(path))
+    {
+        return false;
+    }
+
     std::error_code ec;
 
     auto removed = std::filesystem::remove(path, ec);
@@ -79,6 +89,7 @@
 
     try
     {
+        assertThatPathIsNotSymlink(path);
         std::ifstream file(path);
         file >> result;
     }
@@ -103,7 +114,7 @@
     for (const auto& p :
          std::filesystem::recursive_directory_iterator(directory))
     {
-        if (p.is_regular_file())
+        if (p.is_regular_file() && !p.is_symlink())
         {
             auto item = std::filesystem::relative(p.path(), directory);
             result.emplace_back(std::move(item));
@@ -134,3 +145,14 @@
 {
     return std::filesystem::exists(join(directory, subPath));
 }
+
+void PersistentJsonStorage::assertThatPathIsNotSymlink(
+    const std::filesystem::path& path)
+{
+    if (std::filesystem::is_symlink(path))
+    {
+        throw std::runtime_error(
+            "Source/Target file is a symlink! Operation canceled on path "s +
+            path.c_str());
+    }
+}