[EXIF] Fix privilege issue 86/137786/5
authorPawel Wasowski <p.wasowski2@partner.samsung.com>
Fri, 7 Jul 2017 16:02:53 +0000 (18:02 +0200)
committerPawel Wasowski <p.wasowski2@partner.samsung.com>
Tue, 18 Jul 2017 08:56:07 +0000 (10:56 +0200)
Problem: implementation of getExifInfo() used Web API filesystem
resolve() function to check, if file exists on the device. Use of this
function required declaring http://tizen.org/privilege/filesystem.read.

File existence checking has been implemented in EXIF plugin and does not
require declaring any additional privileges.

[Verification] TCT EXIF: 100% pass rate,
        manuall tests with Chrome DevTools did not show any problems

Change-Id: Id9d19965eddb31902f14817eac0bd5ad897f1568
Signed-off-by: Pawel Wasowski <p.wasowski2@partner.samsung.com>
src/common/tools.cc
src/common/tools.h
src/exif/exif_api.js
src/exif/exif_instance.cc

index 638352f6400d2681c1d42f8abf07b800001ca9d3..cd8beeaa9e6dd4d24a636ae2ded35f9b65b5e478 100644 (file)
@@ -19,6 +19,7 @@
 #include <privilegemgr/privilege_manager.h>
 #include <app_manager.h>
 #include <pkgmgr-info.h>
+#include <sys/stat.h>
 
 #ifdef PRIVILEGE_USE_DB
 #include <sqlite3.h>
@@ -480,5 +481,59 @@ char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size) {
   return hex;
 }
 
+bool IsPathValid(const std::string& path) {
+  LoggerD("Enter");
+
+  /*
+   * Directory dot-referencing is not allowed
+   */
+  return std::string::npos == path.find("/../") &&
+       std::string::npos == path.find("/./") &&
+       0 != path.find("./") &&
+       0 != path.find("../") &&
+       path.length() - 2 != path.rfind("/.") &&
+       path.length() - 3 != path.rfind("/..");
+}
+
+PlatformResult CheckFileStatus(const std::string& path) {
+  LoggerD("Enter");
+
+  struct stat buf;
+
+  if (stat(path.c_str(), &buf)) {
+    LoggerD("Failed to stat path: %s", path.c_str());
+
+    if (ENOENT == errno) {
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "File does not exist: " + path);
+    } else if (EACCES == errno) {
+      return PlatformResult(ErrorCode::IO_ERR, "The user cannot access the file: " + path);
+    }
+
+    LoggerD("stat() error: %s", common::tools::GetErrorString(errno).c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get status of the file: " + path);
+  }
+
+  if (!S_ISREG(buf.st_mode)) {
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Path does not point to a regular file: "
+              + path);
+  }
+
+  if (!(S_IRUSR & buf.st_mode)) {
+    return PlatformResult(ErrorCode::IO_ERR, "The user cannot read the file: " + path);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CheckFileAvailability(const std::string& path) {
+  LoggerD("Enter");
+
+  if (!IsPathValid(path)) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid path: " + path);
+  }
+
+  return CheckFileStatus(path);
+}
+
 }  // namespace tools
 }  // namespace common
index 5d8eec64400feee492d1f0996756b5611f69bfe6..fc905ec1cfcc95c8c388d5e36a0f8bf677743c64 100644 (file)
@@ -85,6 +85,12 @@ int HexToInt(char c);
 unsigned char* HexToBin(const char* hex, int size, unsigned char* bin, int bin_size);
 char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size);
 
+bool IsPathValid(const std::string& path);
+
+PlatformResult CheckFileStatus(const std::string& path);
+
+PlatformResult CheckFileAvailability(const std::string& path);
+
 }  // namespace tools
 }  // namespace common
 
index d209d8acc63bcb39acb6853bd9a1691d1c408ff0..3040336f35b9e9666c0619ead2fc4d526d843c4f 100644 (file)
@@ -205,7 +205,6 @@ ExifManager.prototype.getExifInfo = function() {
     if (native_.isFailure(result)) {
       native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
     } else {
-
       // call to c++ code. Fields that do not exist are undefined.
       var exifInfoNative = native_.getResultObject(result);
 
@@ -218,15 +217,7 @@ ExifManager.prototype.getExifInfo = function() {
     }
   };
 
-  tizen.filesystem.resolve(args.uri,
-      function() {
-        native_.call('ExifManager_getExifInfo', {'uri': args.uri}, callback);
-      },
-      function() {
-        native_.callIfPossible(args.errorCallback, new WebAPIException(
-            WebAPIException.NOT_FOUND_ERR,
-            'File can not be found.'));
-      });
+  native_.call('ExifManager_getExifInfo', {'uri': args.uri}, callback);
 };
 
 ExifManager.prototype.saveExifInfo = function() {
@@ -316,15 +307,7 @@ ExifManager.prototype.getThumbnail = function() {
     }
   };
 
-  tizen.filesystem.resolve(args.uri,
-      function() {
-        native_.call('ExifManager_getThumbnail', {'uri': args.uri}, _callback);
-      },
-      function() {
-        native_.callIfPossible(args.errorCallback, new WebAPIException(
-            WebAPIException.NOT_FOUND_ERR,
-            'File can not be found.'));
-      });
+  native_.call('ExifManager_getThumbnail', {'uri': args.uri}, _callback);
 };
 
 tizen.ExifInformation = function() {
index 8be6a26ef995e8c3f84c80cb3ade4e358740af35..6f0101af2402b000d9da18975baa55bfc4093a20 100755 (executable)
@@ -26,6 +26,7 @@
 #include "common/logger.h"
 #include "common/platform_result.h"
 #include "common/task-queue.h"
+#include "common/tools.h"
 
 #include "exif/exif_information.h"
 #include "exif/exif_util.h"
@@ -62,6 +63,13 @@ void ExifInstance::ExifManagerGetExifInfo(const picojson::value& args, picojson:
       PlatformResult status(ErrorCode::NO_ERROR);
 
       const std::string &file_path = ExifUtil::convertUriToPath(uri);
+
+      PlatformResult fileAvailability(common::tools::CheckFileAvailability(file_path));
+      if (!fileAvailability) {
+        LogAndReportError(fileAvailability, &response->get<picojson::object>());
+        return;
+      }
+
       LoggerD("file_path = %s", file_path.c_str());
 
       status = GetExifInfo::LoadFromURI(uri, &result);
@@ -128,6 +136,14 @@ void ExifInstance::ExifManagerGetThumbnail(const picojson::value& args,
       JsonValue result = JsonValue(JsonObject());
       JsonObject &result_obj = result.get<JsonObject>();
 
+      PlatformResult fileAvailability(common::tools::CheckFileAvailability(file_path));
+      if (!fileAvailability) {
+        LogAndReportError(fileAvailability, &response->get<picojson::object>());
+        return;
+      }
+
+      LoggerD("file_path = %s", file_path.c_str());
+
       std::string ext = file_path.substr(file_path.find_last_of(".") + 1);
       std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);