[Common] Adding macro to check file access 77/167077/10
authorSzymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
Mon, 15 Jan 2018 08:19:22 +0000 (09:19 +0100)
committerSzymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
Thu, 1 Feb 2018 13:36:26 +0000 (14:36 +0100)
[Verification] The macro works as intended on applications with required
version 4.0 and 5.0.

Change-Id: I2d530cd6c2447616bb963fb3640bd16b8b1b8fd9
Signed-off-by: Szymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
src/common/tools.cc
src/common/tools.h

index c1d4998..5ef95ca 100644 (file)
@@ -446,6 +446,23 @@ bool IsAppVersionEarlierThan(const std::string& ver) {
   return false;
 }
 
+/*
+ * RequestStoragePrivilegeChecker structure is used to check whether the file stating is needed.
+ * File stating is done to ensure that the application has given access to files on
+ * internal/external memory. The checking is done since Tizen 5.0 for applications, which
+ * require at least 5.0 version of Tizen.
+ * */
+struct RequestStoragePrivilegeChecker {
+  bool isStorageAccessCheckNeeded;
+  RequestStoragePrivilegeChecker() : isStorageAccessCheckNeeded(!IsAppVersionEarlierThan("5.0")) {
+  }
+};
+
+bool IsStoragePrivilegeCheckNeeded() {
+  static RequestStoragePrivilegeChecker checker{};
+  return checker.isStorageAccessCheckNeeded;
+}
+
 std::string GetErrorString(int error_code) {
   static const size_t kSize = 1024;
   char msg[kSize] = {0};
@@ -491,6 +508,39 @@ bool IsPathValid(const std::string& path) {
          path.length() - 3 != path.rfind("/..");
 }
 
+PlatformResult CheckStorageAccess(const std::string& path) {
+  ScopeLogger("path: [%s]", path.c_str());
+  struct stat buf {};
+  char* real_path = realpath(path.c_str(), nullptr);
+  SCOPE_EXIT {
+    free(real_path);
+  };
+  if ((nullptr == real_path && EACCES == errno) ||
+      (-1 == stat(real_path, &buf) && EACCES == errno)) {
+    LoggerE("The application does not have necessary privilege to access given file: [%s]",
+            path.c_str());
+    return PlatformResult(ErrorCode::SECURITY_ERR,
+                          "Permission denied: accessing files requires proper storage privilege");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+TizenResult CheckStorageAccessAndReturn(const std::string& path) {
+  ScopeLogger("path: [%s]", path.c_str());
+  struct stat buf {};
+  char* real_path = realpath(path.c_str(), nullptr);
+  SCOPE_EXIT {
+    free(real_path);
+  };
+  if ((nullptr == real_path && EACCES == errno) ||
+      (-1 == stat(real_path, &buf) && EACCES == errno)) {
+    LoggerE("The application does not have necessary privilege to access given file: [%s]",
+            path.c_str());
+    return SecurityError("Permission denied: accessing files requires proper storage privilege");
+  }
+  return TizenSuccess();
+}
+
 PlatformResult CheckFileStatus(const std::string& path) {
   ScopeLogger();
 
index d72a09b..88136c4 100644 (file)
@@ -23,6 +23,7 @@
 #include "common/picojson.h"
 #include "common/platform_exception.h"
 #include "common/platform_result.h"
+#include "common/tizen_result.h"
 
 namespace common {
 namespace tools {
@@ -35,8 +36,10 @@ void ReportError(const PlatformResult& error, picojson::object* out);
 
 common::PlatformResult CheckAccess(const std::string& privilege);
 common::PlatformResult CheckAccess(const std::vector<std::string>& privileges);
+common::PlatformResult CheckStorageAccess(const std::string& path);
+common::TizenResult CheckStorageAccessAndReturn(const std::string& path);
 common::PlatformResult GetPkgApiVersion(std::string* api_version);
-
+bool IsStoragePrivilegeCheckNeeded();
 bool IsAppVersionEarlierThan(const std::string& ver);
 
 // it is used for modules which return TizenResult objects to JS layer
@@ -57,6 +60,29 @@ bool IsAppVersionEarlierThan(const std::string& ver);
     }                                               \
   } while (0)
 
+// The below macro is designed to check, whether the application has necessary privilege in order
+// to access resource on internal or external memory.
+#define CHECK_STORAGE_ACCESS(path, out)                   \
+  do {                                                    \
+    if (common::tools::IsStoragePrivilegeCheckNeeded()) { \
+      auto ret = common::tools::CheckStorageAccess(path); \
+      if (!ret) {                                         \
+        common::tools::ReportError(ret, out);             \
+        return;                                           \
+      }                                                   \
+    }                                                     \
+  } while (0)
+
+#define CHECK_STORAGE_ACCESS_AND_RETURN(path)                      \
+  do {                                                             \
+    if (common::tools::IsStoragePrivilegeCheckNeeded()) {          \
+      auto ret = common::tools::CheckStorageAccessAndReturn(path); \
+      if (!ret) {                                                  \
+        return ret;                                                \
+      }                                                            \
+    }                                                              \
+  } while (0)
+
 #define CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(current_priv, prev_priv, out) \
   do {                                                                            \
     auto ret = common::tools::CheckAccess(current_priv);                          \