return apath;
}
-void canonicalizeDirSet(StrSet &dirset)
+void eraseSubdirectories(StrSet &dirset)
{
if (dirset.size() < 2)
return;
std::string getAbsolutePath(const std::string &path);
// input directory set should contains resolved path only
-void canonicalizeDirSet(StrSet &dirset);
+void eraseSubdirectories(StrSet &dirset);
} // namespace Client
} // namespace Csr
}
hExt->dispatchAsync([hExt, user_data, fileSet] {
+ auto ret = hExt->dispatch<std::pair<int, std::shared_ptr<StrSet>>>(
+ CommandId::CANONICALIZE_PATHS, *fileSet);
+
+ if (ret.first != CSR_ERROR_NONE) {
+ if (hExt->m_cb.onError)
+ hExt->m_cb.onError(ret.first, user_data);
+
+ return;
+ }
+
+ std::shared_ptr<StrSet> canonicalizedFiles;
+
+ if (ret.second == nullptr)
+ canonicalizedFiles = std::make_shared<StrSet>();
+ else
+ canonicalizedFiles = std::move(ret.second);
+
Client::AsyncLogic l(hExt, user_data, [&hExt] { return hExt->isStopped(); });
- l.scanFiles(*fileSet).second();
+ l.scanFiles(*canonicalizedFiles).second();
});
return CSR_ERROR_NONE;
dirSet->insert(Client::getAbsolutePath(dir_paths[i]));
}
- Client::canonicalizeDirSet(*dirSet);
-
hExt->dispatchAsync([hExt, user_data, dirSet] {
+ auto ret = hExt->dispatch<std::pair<int, std::shared_ptr<StrSet>>>(
+ CommandId::CANONICALIZE_PATHS, *dirSet);
+
+ if (ret.first != CSR_ERROR_NONE) {
+ if (hExt->m_cb.onError)
+ hExt->m_cb.onError(ret.first, user_data);
+
+ return;
+ }
+
+ std::shared_ptr<StrSet> canonicalizedDirs;
+
+ if (ret.second == nullptr)
+ canonicalizedDirs = std::make_shared<StrSet>();
+ else
+ canonicalizedDirs = std::move(ret.second);
+
+ Client::eraseSubdirectories(*canonicalizedDirs);
+
Client::AsyncLogic l(hExt, user_data, [&hExt] { return hExt->isStopped(); });
- l.scanDirs(*dirSet).second();
+ l.scanDirs(*canonicalizedDirs).second();
});
return CSR_ERROR_NONE;
GET_IGNORED = 0x1103,
GET_IGNORED_LIST = 0x1104,
GET_SCANNABLE_FILES = 0x1105,
- SET_DIR_TIMESTAMP = 0x1106,
+ CANONICALIZE_PATHS = 0x1106,
+ SET_DIR_TIMESTAMP = 0x1107,
// handle result
JUDGE_STATUS = 0x1201,
#include <algorithm>
#include <ctime>
#include <climits>
+#include <cerrno>
+#include <unistd.h>
#include "common/audit/logger.h"
#include "service/type-converter.h"
EXCEPTION_GUARD_END
}
+RawBuffer CsLogic::canonicalizePaths(const StrSet &paths)
+{
+ EXCEPTION_GUARD_START
+
+ if (this->m_db.getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
+ ThrowExc(EngineDisabled, "engine is disabled");
+
+ StrSet canonicalized;
+
+ for (const auto &path : paths) {
+ auto target = File::getPkgPath(path);
+ auto resolved = ::realpath(target.c_str(), nullptr);
+
+ if (resolved == nullptr) {
+ const int err = errno;
+ if (err == ENOENT)
+ ThrowExc(FileDoNotExist, "File do not exist: " << target);
+ else if (err == EACCES)
+ ThrowExc(PermDenied, "Perm denied to get real path: " << target);
+ else
+ ThrowExc(FileSystemError, "Failed to get real path: " << target <<
+ " with errno: " << err);
+ }
+
+ std::string resolvedStr(resolved);
+ free(resolved);
+
+ if (canonicalized.find(resolvedStr) == canonicalized.end()) {
+ INFO("Insert to canonicalized list: " << resolvedStr);
+ canonicalized.emplace(std::move(resolvedStr));
+ }
+ }
+
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, canonicalized).pop();
+
+ EXCEPTION_GUARD_END
+}
+
RawBuffer CsLogic::setDirTimestamp(const std::string &dir, time_t ts)
{
EXCEPTION_GUARD_START
RawBuffer scanData(const CsContext &context, const RawBuffer &data);
RawBuffer scanFile(const CsContext &context, const std::string &filepath);
RawBuffer getScannableFiles(const std::string &dir);
+ RawBuffer canonicalizePaths(const StrSet &paths);
RawBuffer setDirTimestamp(const std::string &dir, time_t ts);
RawBuffer judgeStatus(const std::string &filepath, csr_cs_action_e action);
RawBuffer getDetected(const std::string &filepath);
CID_TOSTRING(GET_IGNORED);
CID_TOSTRING(GET_IGNORED_LIST);
CID_TOSTRING(GET_SCANNABLE_FILES);
+ CID_TOSTRING(CANONICALIZE_PATHS);
CID_TOSTRING(SET_DIR_TIMESTAMP);
CID_TOSTRING(JUDGE_STATUS);
return m_cslogic.getScannableFiles(dir);
}
+ case CommandId::CANONICALIZE_PATHS: {
+ hasPermission(conn);
+
+ StrSet paths;
+ q.Deserialize(paths);
+
+ return m_cslogic.canonicalizePaths(paths);
+ }
+
case CommandId::SET_DIR_TIMESTAMP: {
hasPermission(conn);
${CSR_FW_SRC_PATH}/service/cs-loader.cpp
${CSR_FW_SRC_PATH}/service/wp-loader.cpp
${CSR_FW_SRC_PATH}/service/engine-error-converter.cpp
- ${CSR_FW_SRC_PATH}/client/canonicalize.cpp
${CSR_FW_SRC_PATH}/ui/popup/package-info.cpp
test-db.cpp
test-api-engine-web-protection.cpp
test-cs-loader.cpp
test-wp-loader.cpp
- test-canonicalize.cpp
test-package-info.cpp
test-main.cpp
+++ /dev/null
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file test-canonicalize.cpp
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief file / directory set canonicalize unit test
- */
-#include <client/canonicalize.h>
-
-#include <system_error>
-#include <cerrno>
-#include <unistd.h>
-
-#include <boost/test/unit_test.hpp>
-
-#include "test-common.h"
-
-using namespace Csr;
-
-namespace {
-
-class ScopedChDir {
-public:
- ScopedChDir(const std::string &dirpath)
- {
- if (getcwd(cdbuf, PATH_MAX + 1) == nullptr)
- throw std::system_error(errno, std::system_category(), "getcwd failed");
-
- if (::chdir(dirpath.c_str()) == -1)
- throw std::system_error(errno, std::system_category(),
- dirpath + " chdir failed");
- }
-
- ~ScopedChDir()
- {
- if (::chdir(cdbuf) == -1)
- throw std::system_error(errno, std::system_category(),
- std::string(cdbuf) + " chdir failed");
- }
-
-private:
- char cdbuf[PATH_MAX + 1];
-};
-
-} // namespace anonymous
-
-BOOST_AUTO_TEST_SUITE(CANONICALIZE)
-
-BOOST_AUTO_TEST_CASE(get_absolute_path_file)
-{
- EXCEPTION_GUARD_START
-
- ScopedChDir chdir("/usr/bin");
-
- std::string absolutePath = "/usr/bin/csr-server";
-
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/csr-server"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/../bin/csr-server"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/./csr-server"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("csr-server"), absolutePath);
-
- EXCEPTION_GUARD_END
-}
-
-BOOST_AUTO_TEST_CASE(get_absolute_path_dir)
-{
- EXCEPTION_GUARD_START
-
- ScopedChDir chdir("/usr/bin");
-
- std::string absolutePath = "/usr/bin";
-
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("."), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/../bin"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("/usr/bin/./"), absolutePath);
- ASSERT_IF(Client::getAbsolutePath("../bin/"), absolutePath);
-
- EXCEPTION_GUARD_END
-}
-
-BOOST_AUTO_TEST_CASE(dir_set_1)
-{
- EXCEPTION_GUARD_START
-
- ScopedChDir chdir("/usr/bin");
-
- StrSet dirset;
-
- dirset.insert(Client::getAbsolutePath("/var/lib"));
- dirset.insert(Client::getAbsolutePath("/bin"));
- dirset.insert(Client::getAbsolutePath("/"));
- dirset.insert(Client::getAbsolutePath("/opt"));
- dirset.insert(Client::getAbsolutePath("/usr/bin"));
-
- Client::canonicalizeDirSet(dirset);
-
- ASSERT_IF(dirset.size(), std::size_t(1));
- ASSERT_IF(dirset.count("/"), std::size_t(1));
-
- EXCEPTION_GUARD_END
-}
-
-BOOST_AUTO_TEST_CASE(dir_set_2)
-{
- EXCEPTION_GUARD_START
-
- ScopedChDir chdir("/usr/bin");
-
- StrSet dirset;
-
- dirset.insert(Client::getAbsolutePath("/usr/share"));
- dirset.insert(Client::getAbsolutePath("/usr/lib"));
- dirset.insert(Client::getAbsolutePath("/usr"));
- dirset.insert(Client::getAbsolutePath("/usr/etc"));
- dirset.insert(Client::getAbsolutePath("/opt/share"));
- dirset.insert(Client::getAbsolutePath("/opt/dbspace"));
-
- Client::canonicalizeDirSet(dirset);
-
- ASSERT_IF(dirset.size(), std::size_t(3));
- ASSERT_IF(dirset.count("/usr"), std::size_t(1));
- ASSERT_IF(dirset.count("/opt/share"), std::size_t(1));
- ASSERT_IF(dirset.count("/opt/dbspace"), std::size_t(1));
-
- EXCEPTION_GUARD_END
-}
-
-BOOST_AUTO_TEST_SUITE_END()
* limitations under the License
*/
/*
- * @file test-api-content-screening.cpp
+ * @file test-api-content-screening-async.cpp
* @author Kyungwook Tak (k.tak@samsung.com)
* @version 1.0
- * @brief CSR Content screening API test
+ * @brief CSR Content screening async API test
*/
#include <csr-content-screening.h>
#include <condition_variable>
#include <thread>
#include <mutex>
+#include <vector>
#include <boost/test/unit_test.hpp>
#include "test-common.h"
struct AsyncTestContext {
std::mutex m;
+ std::mutex m_vec;
std::condition_variable cv;
int scannedCnt;
int detectedCnt;
int completedCnt;
int cancelledCnt;
int errorCnt;
+ std::vector<std::string> scannedList;
std::vector<csr_cs_malware_h> detectedList;
int errorCode;
{
BOOST_MESSAGE("on_scanned. file[" << file << "] scanned!");
auto ctx = reinterpret_cast<AsyncTestContext *>(userdata);
+
+ std::lock_guard<std::mutex> l(ctx->m_vec);
+
ctx->scannedCnt++;
+ ctx->scannedList.push_back(file);
}
void on_detected(csr_cs_malware_h detected, void *userdata)
ASSERT_IF(csr_cs_malware_get_file_name(detected, &file_name.ptr), CSR_ERROR_NONE);
BOOST_MESSAGE("on_detected. file[" << file_name.ptr << "] detected!");
auto ctx = reinterpret_cast<AsyncTestContext *>(userdata);
+
+ std::lock_guard<std::mutex> l(ctx->m_vec);
+
ctx->detectedCnt++;
ctx->detectedList.push_back(detected);
}
{
BOOST_MESSAGE("on_error. async request done with error code[" << ec << "]");
auto ctx = reinterpret_cast<AsyncTestContext *>(userdata);
+
ctx->errorCnt++;
ctx->errorCode = ec;
ctx->cv.notify_one();
EXCEPTION_GUARD_END
}
+BOOST_AUTO_TEST_CASE(canonicalize_files_absolute_path)
+{
+ EXCEPTION_GUARD_START
+
+ Test::initialize_db();
+
+ auto c = Test::Context<csr_cs_context_h>();
+ auto context = c.get();
+
+ install_test_files();
+
+ set_default_callback(context);
+
+ // four files are all same as realpath.
+ const char *files[4] = {
+ TEST_FILE_NORMAL,
+ TEST_DIR "/./test_normal_file",
+ TEST_DIR "/.././././csr-test/test_normal_file",
+ TEST_DIR "/././.././csr-test/test_normal_file"
+ };
+
+ AsyncTestContext testCtx;
+
+ ASSERT_IF(csr_cs_scan_files_async(context, files, sizeof(files) / sizeof(const char *),
+ &testCtx),
+ CSR_ERROR_NONE);
+
+ std::unique_lock<std::mutex> l(testCtx.m);
+ testCtx.cv.wait(l);
+ l.unlock();
+
+ ASSERT_CALLBACK(testCtx, 1, 0, 1, 0, 0);
+ ASSERT_IF(testCtx.scannedList.size(), static_cast<std::size_t>(1));
+ ASSERT_IF(testCtx.scannedList.front(), static_cast<const char *>(TEST_FILE_NORMAL));
+
+ EXCEPTION_GUARD_END
+}
+
+BOOST_AUTO_TEST_CASE(canonicalize_files_relative_path)
+{
+ EXCEPTION_GUARD_START
+
+ Test::initialize_db();
+
+ auto c = Test::Context<csr_cs_context_h>();
+ auto context = c.get();
+
+ install_test_files();
+
+ set_default_callback(context);
+
+ // four files are all same as realpath.
+ const char *files[4] = {
+ "test_normal_file",
+ "./test_normal_file",
+ ".././././csr-test/test_normal_file",
+ "././.././csr-test/test_normal_file"
+ };
+
+ AsyncTestContext testCtx;
+
+ Test::ScopedChDir scopedCd(TEST_DIR);
+
+ ASSERT_IF(csr_cs_scan_files_async(context, files, sizeof(files) / sizeof(const char *),
+ &testCtx),
+ CSR_ERROR_NONE);
+
+ std::unique_lock<std::mutex> l(testCtx.m);
+ testCtx.cv.wait(l);
+ l.unlock();
+
+ ASSERT_CALLBACK(testCtx, 1, 0, 1, 0, 0);
+ ASSERT_IF(testCtx.scannedList.size(), static_cast<std::size_t>(1));
+ ASSERT_IF(testCtx.scannedList.front(), static_cast<const char *>(TEST_FILE_NORMAL));
+
+ EXCEPTION_GUARD_END
+}
+
BOOST_AUTO_TEST_CASE(multiple_async_dispatch_negative)
{
EXCEPTION_GUARD_START
#include <typeinfo>
#include <string>
#include <cstring>
+#include <cerrno>
+#include <system_error>
+#include <unistd.h>
#include <boost/test/unit_test.hpp>
}
};
+class ScopedChDir {
+public:
+ ScopedChDir(const std::string &dirpath)
+ {
+ if (::getcwd(cdbuf, PATH_MAX + 1) == nullptr)
+ throw std::system_error(errno, std::system_category(), "getcwd failed");
+
+ if (::chdir(dirpath.c_str()) == -1)
+ throw std::system_error(errno, std::system_category(),
+ dirpath + " chdir failed");
+ }
+
+ ~ScopedChDir()
+ {
+ if (::chdir(cdbuf) == -1)
+ throw std::system_error(errno, std::system_category(),
+ std::string(cdbuf) + " chdir failed");
+ }
+
+private:
+ char cdbuf[PATH_MAX + 1];
+};
+
template <typename T>
class Context {
public: