From: Kyungwook Tak Date: Mon, 2 May 2016 02:13:51 +0000 (+0900) Subject: Impl logic of getting scannable files list X-Git-Tag: accepted/tizen/common/20160614.143943^2~170 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7b9bc120017d7116575ee9b71b6371be4e5a4bc;p=platform%2Fupstream%2Fcsr-framework.git Impl logic of getting scannable files list Change-Id: Iff585fff152059bc555637bdbef6a9e670dc7469 Signed-off-by: Kyungwook Tak --- diff --git a/engine/content-screening/sample-engine.cpp b/engine/content-screening/sample-engine.cpp index 4cf2301..8d0633d 100644 --- a/engine/content-screening/sample-engine.cpp +++ b/engine/content-screening/sample-engine.cpp @@ -280,9 +280,6 @@ int csret_cs_detect_malware(csret_cs_context_s *context, const RawBuffer &data, if (context == nullptr) return CSRE_ERROR_INVALID_HANDLE; - if (data.empty()) - return CSRE_ERROR_INVALID_PARAMETER; - if (g_virus_sig.empty()) return CSRE_ERROR_ENGINE_NOT_ACTIVATED; diff --git a/src/framework/client/async-logic.cpp b/src/framework/client/async-logic.cpp index b0ac593..0167ebf 100644 --- a/src/framework/client/async-logic.cpp +++ b/src/framework/client/async-logic.cpp @@ -71,38 +71,10 @@ AsyncLogic::Ending AsyncLogic::scanDirs(const std::shared_ptr &dirs) AsyncLogic::Ending AsyncLogic::scanDir(const std::string &dir) { - // For in case of there's already detected malware for dir - StrSet dirset; - dirset.insert(dir); - - auto retResults = - m_dispatcher->methodCall>>( - CommandId::GET_DETECTED_LIST, dirset); - - if (retResults.first != CSR_ERROR_NONE) { - ERROR("[Error] ret: " << retResults.first); - - for (auto r : retResults.second) - delete r; - - auto ec = retResults.first; - return std::make_pair(Callback::Id::OnError, [this, ec] { - if (this->m_cb.onError) - this->m_cb.onError(this->m_userdata, ec); - }); - } - - // Register already detected malwares to context to be freed with context. - for (auto r : retResults.second) { - m_results.emplace_back(r); - - if (m_cb.onDetected) - m_cb.onDetected(m_userdata, reinterpret_cast(r)); - } - - // Already scanned files are excluded according to history + // Already scanned files are included in history. it'll be skipped later + // on server side by every single scan_file request. auto retFiles = m_dispatcher->methodCall>( - CommandId::DIR_GET_FILES, m_ctx, dir); + CommandId::GET_SCANNABLE_FILES, dir); if (retFiles.first != CSR_ERROR_NONE) { ERROR("[Error] ret: " << retFiles.first); @@ -136,7 +108,7 @@ AsyncLogic::Ending AsyncLogic::scanFiles(const std::shared_ptr &fileSet) CommandId::SCAN_FILE, m_ctx, file); if (ret.first != CSR_ERROR_NONE) { - ERROR("[Error] ret: " << ret.first); + ERROR("[Error] ret: " << ret.first << " while scan file: " << file); delete ret.second; auto ec = ret.first; return std::make_pair(Callback::Id::OnError, [this, ec] { diff --git a/src/framework/common/command-id.h b/src/framework/common/command-id.h index c8a4f7b..ca3f5ac 100644 --- a/src/framework/common/command-id.h +++ b/src/framework/common/command-id.h @@ -33,7 +33,7 @@ enum class CommandId : int { GET_DETECTED_LIST = 0x1102, GET_IGNORED = 0x1103, GET_IGNORED_LIST = 0x1104, - DIR_GET_FILES = 0x1105, + GET_SCANNABLE_FILES = 0x1105, // handle result JUDGE_STATUS = 0x1201, diff --git a/src/framework/common/cs-detected.h b/src/framework/common/cs-detected.h index 8dce1ec..df4c813 100644 --- a/src/framework/common/cs-detected.h +++ b/src/framework/common/cs-detected.h @@ -44,7 +44,7 @@ struct CsDetected : public IResult { bool hasValue(void) const noexcept; - std::string targetName; // file path or app id which contains malware + std::string targetName; // file(app) path which contains malware std::string malwareName; std::string detailedUrl; diff --git a/src/framework/service/logic.cpp b/src/framework/service/logic.cpp index dd70d6a..c9b9fd8 100644 --- a/src/framework/service/logic.cpp +++ b/src/framework/service/logic.cpp @@ -35,30 +35,6 @@ namespace Csr { -namespace { - -// temporal function for debugging until modules integrated to logic. -void printCsContext(const CsContext &context) -{ - std::string popupMessage; - int askUser; - int coreUsage; - bool scanOnCloud; - - context.get(static_cast(CsContext::Key::PopupMessage), popupMessage); - context.get(static_cast(CsContext::Key::AskUser), askUser); - context.get(static_cast(CsContext::Key::CoreUsage), coreUsage); - context.get(static_cast(CsContext::Key::ScanOnCloud), scanOnCloud); - - INFO("Context info:" - " PopupMessage: " << popupMessage << - " AskUser: " << askUser << - " CoreUsage: " << coreUsage << - " ScanOnCloud: " << scanOnCloud); -} - -} - Logic::Logic() : m_cs(new CsLoader(CS_ENGINE_PATH)), m_wp(new WpLoader(WP_ENGINE_PATH)), @@ -127,11 +103,10 @@ RawBuffer Logic::dispatch(const RawBuffer &in) return scanFile(*cptr, filepath); } - case CommandId::DIR_GET_FILES: { - CsContextShPtr cptr; + case CommandId::GET_SCANNABLE_FILES: { std::string dir; - info.second.Deserialize(cptr, dir); - return dirGetFiles(*cptr, dir); + info.second.Deserialize(dir); + return getScannableFiles(dir); } case CommandId::JUDGE_STATUS: { @@ -284,61 +259,79 @@ RawBuffer Logic::scanFileHelper(const CsContext &context, RawBuffer Logic::scanFile(const CsContext &context, const std::string &filepath) { + DEBUG("Scan request on file: " << filepath); auto history = m_db->getDetectedMalware(filepath); if (!history) return scanFileHelper(context, filepath); - // history exist of malware detected for the file. - // let's check file modified since the detected time. - auto file = File::create(filepath, static_cast(history->ts)); - - // file is modified since the detected time. let's remove history! - if (!file) { + DEBUG("Scan history exist on file: " << filepath); + if (File::create(filepath, static_cast(history->ts))) { + DEBUG("file[" << filepath << "] is modified since the detected time. " + "let's remove history and re-scan"); m_db->deleteDetectedMalware(filepath); return scanFileHelper(context, filepath); } - // file isn't modified since the detected time. history can be used. - if (!context.askUser) + DEBUG("file[" << filepath << "] isn't modified since the detected time. " + "history can be used."); + if (!context.askUser) { return BinaryQueue::Serialize(CSR_ERROR_NONE, history).pop(); - - if (history->isIgnored) { + } else if (history->isIgnored) { history->response = CSR_CS_IGNORE; - } else { - switch (history->response = getUserResponse(context, *history)) { - case CSR_CS_IGNORE: - m_db->setDetectedMalwareIgnored(filepath, true); - break; - - case CSR_CS_REMOVE: - if (!file->remove()) { - ERROR("Failed to remove filepath: " << filepath); - return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED, CsDetected()).pop(); - } - - m_db->deleteDetectedMalware(filepath); - break; - - case CSR_CS_SKIP: - break; - - default: - ThrowExc(InternalError, "Invalid response from popup: " << - static_cast(history->response)); + return BinaryQueue::Serialize(CSR_ERROR_NONE, history).pop(); + } + + DEBUG("user response is needed."); + + switch (history->response = getUserResponse(context, *history)) { + case CSR_CS_IGNORE: + m_db->setDetectedMalwareIgnored(filepath, true); + break; + + case CSR_CS_REMOVE: { + auto file = File::create(filepath); + if (!file && !file->remove()) { + ERROR("Failed to remove filepath: " << filepath); + return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED, CsDetected()).pop(); } + + m_db->deleteDetectedMalware(filepath); + break; + } + + case CSR_CS_SKIP: + break; + + default: + ThrowExc(InternalError, "Invalid response from popup: " << + static_cast(history->response)); } + DEBUG("file[" << filepath << "] user response: " << static_cast(history->response)); + return BinaryQueue::Serialize(CSR_ERROR_NONE, history).pop(); } -RawBuffer Logic::dirGetFiles(const CsContext &context, const std::string &dir) +RawBuffer Logic::getScannableFiles(const std::string &dir) { - INFO("Dir[" << dir << "] get files"); + auto lastScanTime = m_db->getLastScanTime(dir, m_csDataVersion); + auto visitor = (lastScanTime == -1) ? + FsVisitor::create(dir) : FsVisitor::create(dir, lastScanTime); + + StrSet fileset; + while (auto file = visitor->next()) { + DEBUG("In dir[" << dir << "], Scannable file[" << file->getPath() << "]"); + fileset.insert(file->getPath()); + } - printCsContext(context); + if (lastScanTime != -1) { + // for case: scan history exist and not modified. + for (auto &row : m_db->getDetectedMalwares(dir)) + fileset.insert(row->targetName); + } - return BinaryQueue::Serialize(CSR_ERROR_NONE, StrSet()).pop(); + return BinaryQueue::Serialize(CSR_ERROR_NONE, fileset).pop(); } RawBuffer Logic::judgeStatus(const std::string &filepath, @@ -351,25 +344,24 @@ RawBuffer Logic::judgeStatus(const std::string &filepath, return BinaryQueue::Serialize(CSR_ERROR_INVALID_PARAMETER).pop(); } - auto file = File::create(filepath, static_cast(history->ts)); - - if (!file) { - ERROR("Target doesn't exist on target path on filesystem or " - "modified since db delta inserted. name: " << filepath); + if (File::create(filepath, static_cast(history->ts))) { + ERROR("Target modified since db delta inserted. name: " << filepath); m_db->deleteDetectedMalware(filepath); // TODO: is it okay to just refresh db and return success? return BinaryQueue::Serialize(CSR_ERROR_NONE).pop(); } switch (action) { - case CSR_CS_ACTION_REMOVE: - if (!file->remove()) { + case CSR_CS_ACTION_REMOVE: { + auto file = File::create(filepath); + if (!file && !file->remove()) { ERROR("Failed to remove filepath: " << filepath); return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED).pop(); } m_db->deleteDetectedMalware(filepath); break; + } case CSR_CS_ACTION_IGNORE: m_db->setDetectedMalwareIgnored(filepath, true); diff --git a/src/framework/service/logic.h b/src/framework/service/logic.h index 3ad467b..0986ed1 100644 --- a/src/framework/service/logic.h +++ b/src/framework/service/logic.h @@ -53,7 +53,7 @@ private: RawBuffer scanData(const CsContext &context, const RawBuffer &data); RawBuffer scanFile(const CsContext &context, const std::string &filepath); RawBuffer scanFileHelper(const CsContext &context, const std::string &filepath); - RawBuffer dirGetFiles(const CsContext &context, const std::string &dir); + RawBuffer getScannableFiles(const std::string &dir); RawBuffer judgeStatus(const std::string &filepath, csr_cs_action_e action); RawBuffer getDetected(const std::string &filepath); RawBuffer getDetectedList(const StrSet &dirSet); diff --git a/test/test-api-content-screening-async.cpp b/test/test-api-content-screening-async.cpp index 775ff03..b795646 100644 --- a/test/test-api-content-screening-async.cpp +++ b/test/test-api-content-screening-async.cpp @@ -54,13 +54,6 @@ void on_scanned(void *userdata, const char *file) ctx->scannedCnt++; } -void on_error(void *userdata, int ec) -{ - BOOST_MESSAGE("on_error. async request done with error code[" << ec << "]"); - auto ctx = reinterpret_cast(userdata); - ctx->errorCnt++; -} - void on_detected(void *userdata, csr_cs_detected_h detected) { (void) detected; @@ -69,6 +62,14 @@ void on_detected(void *userdata, csr_cs_detected_h detected) ctx->detectedCnt++; } +void on_error(void *userdata, int ec) +{ + BOOST_MESSAGE("on_error. async request done with error code[" << ec << "]"); + auto ctx = reinterpret_cast(userdata); + ctx->errorCnt++; + ctx->cv.notify_one(); +} + void on_completed(void *userdata) { BOOST_MESSAGE("on_completed. async request completed succesfully."); @@ -82,6 +83,7 @@ void on_cancelled(void *userdata) BOOST_MESSAGE("on_cancelled. async request canceled!"); auto ctx = reinterpret_cast(userdata); ctx->cancelledCnt++; + ctx->cv.notify_one(); } } @@ -181,15 +183,14 @@ BOOST_AUTO_TEST_CASE(scan_dir_positive) AsyncTestContext testCtx; - ASSERT_IF(csr_cs_scan_dir_async(context, TEST_DIR, &testCtx), CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_dir_async(context, TEST_DIR "/test_dir", &testCtx), CSR_ERROR_NONE); std::unique_lock l(testCtx.m); testCtx.cv.wait(l); l.unlock(); ASSERT_IF(testCtx.completedCnt, 1); - ASSERT_IF(testCtx.scannedCnt, 0); // should be 1 after dir_get_files implemented - ASSERT_IF(testCtx.detectedCnt, 2); + ASSERT_IF(testCtx.scannedCnt + testCtx.detectedCnt, 8); ASSERT_IF(testCtx.cancelledCnt, 0); ASSERT_IF(testCtx.errorCnt, 0); @@ -212,7 +213,7 @@ BOOST_AUTO_TEST_CASE(scan_dirs_positive) AsyncTestContext testCtx; const char *dirs[1] = { - TEST_DIR + TEST_DIR "/test_dir" }; ASSERT_IF( @@ -225,8 +226,7 @@ BOOST_AUTO_TEST_CASE(scan_dirs_positive) l.unlock(); ASSERT_IF(testCtx.completedCnt, 1); - ASSERT_IF(testCtx.scannedCnt, 0); // should be 1 after dir_get_files implemented - ASSERT_IF(testCtx.detectedCnt, 2); + ASSERT_IF(testCtx.scannedCnt + testCtx.detectedCnt, 8); ASSERT_IF(testCtx.cancelledCnt, 0); ASSERT_IF(testCtx.errorCnt, 0); diff --git a/test/test-api-content-screening.cpp b/test/test-api-content-screening.cpp index 16ec3e6..91340db 100644 --- a/test/test-api-content-screening.cpp +++ b/test/test-api-content-screening.cpp @@ -56,15 +56,12 @@ BOOST_AUTO_TEST_CASE(set_values_to_context_positive) ASSERT_IF(csr_cs_set_ask_user(context, CSR_CS_NOT_ASK_USER), CSR_ERROR_NONE); ASSERT_IF(csr_cs_set_ask_user(context, CSR_CS_ASK_USER), CSR_ERROR_NONE); - ASSERT_IF(csr_cs_set_popup_message(context, "Test popup message"), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_set_popup_message(context, "Test popup message"), CSR_ERROR_NONE); - ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_DEFAULT), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_DEFAULT), CSR_ERROR_NONE); ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_ALL), CSR_ERROR_NONE); ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_HALF), CSR_ERROR_NONE); - ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_SINGLE), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_set_core_usage(context, CSR_CS_USE_CORE_SINGLE), CSR_ERROR_NONE); ASSERT_IF(csr_cs_set_scan_on_cloud(context), CSR_ERROR_NONE); @@ -81,8 +78,7 @@ BOOST_AUTO_TEST_CASE(set_values_to_context_negative) ASSERT_IF(csr_cs_set_ask_user(context, static_cast(0x926ce)), CSR_ERROR_INVALID_PARAMETER); - ASSERT_IF(csr_cs_set_popup_message(context, nullptr), - CSR_ERROR_INVALID_PARAMETER); + ASSERT_IF(csr_cs_set_popup_message(context, nullptr), CSR_ERROR_INVALID_PARAMETER); ASSERT_IF(csr_cs_set_popup_message(context, ""), CSR_ERROR_INVALID_PARAMETER); ASSERT_IF(csr_cs_set_core_usage(context, @@ -101,8 +97,7 @@ BOOST_AUTO_TEST_CASE(scan_data) csr_cs_detected_h detected; unsigned char data[100] = {0, }; - ASSERT_IF(csr_cs_scan_data(context, data, sizeof(data), &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_data(context, data, sizeof(data), &detected), CSR_ERROR_NONE); // no malware detected CHECK_IS_NULL(detected); @@ -118,8 +113,7 @@ BOOST_AUTO_TEST_CASE(scan_file_normal) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_NORMAL, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_NORMAL, &detected), CSR_ERROR_NONE); // no malware detected CHECK_IS_NULL(detected); @@ -135,8 +129,7 @@ BOOST_AUTO_TEST_CASE(scan_file_malware) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); @@ -151,8 +144,7 @@ BOOST_AUTO_TEST_CASE(scan_file_risky) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); @@ -167,8 +159,7 @@ BOOST_AUTO_TEST_CASE(get_detected_malware) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); ASSERT_IF(csr_cs_get_detected_malware(context, TEST_FILE_RISKY, &detected), @@ -192,18 +183,18 @@ BOOST_AUTO_TEST_CASE(get_detected_malwares) TEST_DIR }; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); ASSERT_IF(csr_cs_get_detected_malwares(context, dirs, sizeof(dirs) / sizeof(const char *), &detected_list, &cnt), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected_list); - ASSERT_IF(cnt, static_cast(2)); + + BOOST_REQUIRE_MESSAGE(cnt >= 2, "Detected malware count is invalid. " + "expected: >= 2, cnt: " << cnt); EXCEPTION_GUARD_END } @@ -216,11 +207,11 @@ BOOST_AUTO_TEST_CASE(get_ignored_malware) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); - ASSERT_IF(csr_cs_judge_detected_malware(context, detected, - CSR_CS_ACTION_IGNORE), CSR_ERROR_NONE); + + ASSERT_IF(csr_cs_judge_detected_malware(context, detected, CSR_CS_ACTION_IGNORE), + CSR_ERROR_NONE); ASSERT_IF(csr_cs_get_ignored_malware(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); @@ -247,13 +238,13 @@ BOOST_AUTO_TEST_CASE(get_ignored_malwares) ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); - ASSERT_IF(csr_cs_judge_detected_malware(context, detected, - CSR_CS_ACTION_IGNORE), CSR_ERROR_NONE); + ASSERT_IF(csr_cs_judge_detected_malware(context, detected, CSR_CS_ACTION_IGNORE), + CSR_ERROR_NONE); ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_RISKY, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); - ASSERT_IF(csr_cs_judge_detected_malware(context, detected, - CSR_CS_ACTION_IGNORE), CSR_ERROR_NONE); + ASSERT_IF(csr_cs_judge_detected_malware(context, detected, CSR_CS_ACTION_IGNORE), + CSR_ERROR_NONE); ASSERT_IF(csr_cs_get_ignored_malwares(context, dirs, sizeof(dirs) / sizeof(const char *), @@ -272,11 +263,10 @@ BOOST_AUTO_TEST_CASE(judge_detected_malware) auto context = c.get(); csr_cs_detected_h detected; - ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), - CSR_ERROR_NONE); + ASSERT_IF(csr_cs_scan_file(context, TEST_FILE_MALWARE, &detected), CSR_ERROR_NONE); CHECK_IS_NOT_NULL(detected); - ASSERT_IF(csr_cs_judge_detected_malware(context, detected, - CSR_CS_ACTION_UNIGNORE), CSR_ERROR_NONE); + ASSERT_IF(csr_cs_judge_detected_malware(context, detected, CSR_CS_ACTION_UNIGNORE), + CSR_ERROR_NONE); EXCEPTION_GUARD_END }