#include "common/exception.h"
#include "common/cs-detected.h"
+#include "common/async-protocol.h"
#include "common/audit/logger.h"
namespace Csr {
namespace Client {
AsyncLogic::AsyncLogic(HandleExt *handle, void *userdata) :
- m_handle(handle),
- m_ctx(new CsContext),
- m_cb(handle->m_cb),
- m_userdata(userdata)
+ m_handle(handle), m_userdata(userdata)
{
- // disable ask user option for async request for now
- copyKvp<int>(CsContext::Key::CoreUsage);
- copyKvp<std::string>(CsContext::Key::PopupMessage);
- copyKvp<bool>(CsContext::Key::ScanOnCloud);
}
AsyncLogic::~AsyncLogic()
{
- for (auto &resultPtr : this->m_results)
- this->m_handle->add(std::move(resultPtr));
}
void AsyncLogic::scanDirs(const StrSet &dirs)
{
- for (const auto &dir : dirs)
- this->scanDir(dir);
+ this->scanHelper(CommandId::SCAN_DIRS_ASYNC, dirs);
}
-void AsyncLogic::scanDir(const std::string &dir)
+void AsyncLogic::scanFiles(const StrSet &files)
{
- auto startTime = ::time(nullptr);
+ this->scanHelper(CommandId::SCAN_FILES_ASYNC, files);
+}
- if (this->m_handle->isStopped())
- ThrowExcInfo(-999, "Async operation cancelled!");
+void AsyncLogic::scanHelper(const CommandId &id, const StrSet &s)
+{
+ auto ret = this->m_handle->dispatch<int>(id, *(this->m_handle->getContext()), s);
- // Already scanned files are included in history. it'll be skipped later
- // on server side by every single scan_file request.
- auto retFiles = this->m_handle->dispatch<std::pair<int, std::shared_ptr<StrSet>>>(
- CommandId::GET_SCANNABLE_FILES, dir);
+ if (ret != ASYNC_EVENT_START)
+ ThrowExc(ret, "Error on async scan. ret: " << ret);
- if (retFiles.first == -999) {
- ThrowExcInfo(-999, "Async op cancelled!");
- } else if (retFiles.first != CSR_ERROR_NONE) {
- ThrowExc(retFiles.first, "Error to get scannalbe files. "
- "dir: " << dir << " ret: " << retFiles.first);
- }
+ bool isDone = false;
- if (retFiles.second == nullptr) {
- INFO("No scannable file exist on dir: " << dir);
- return;
- }
+ DEBUG("loop for waiting server event start!!");
-#ifdef TIZEN_DEBUG_ENABLE
- DEBUG("scannable file list in dir[" << dir <<
- "], count[" << retFiles.second->size() << "]:");
- size_t count = 0;
- for (const auto &file : *(retFiles.second))
- DEBUG(std::to_string(++count) << " : " << file);
-#endif
-
- // Let's start scan files!
- this->scanFiles(*(retFiles.second));
-
- auto ts64 = static_cast<int64_t>(startTime);
-
- auto ret = this->m_handle->dispatch<int>(CommandId::SET_DIR_TIMESTAMP, dir, ts64);
- if (ret != CSR_ERROR_NONE)
- ERROR("Failed to set dir timestamp after scan dir[" << dir << "] with "
- "ec[" << ret << "] This is server error and not affects to "
- "client / scan result when it doesn't comes to delta scanning... "
- "So just ignore this error on client side.");
-}
+ while (!isDone) {
+ auto event = this->m_handle->revent<int>();
-void AsyncLogic::scanFiles(const StrSet &fileSet)
-{
- for (const auto &file : fileSet) {
- if (this->m_handle->isStopped())
- ThrowExcInfo(-999, "Async op cancelled!");
-
- auto ret = this->m_handle->dispatch<std::pair<int, CsDetected *>>(
- CommandId::SCAN_FILE, this->m_ctx, file);
-
- // for auto memory deleting in case of exception
- ResultPtr resultPtr(ret.second);
-
- // ignore all file-system related error in async operation.
- if (ret.first == CSR_ERROR_FILE_DO_NOT_EXIST ||
- ret.first == CSR_ERROR_FILE_CHANGED ||
- ret.first == CSR_ERROR_FILE_SYSTEM) {
- WARN("File system related error code returned when scan files async."
- " Ignore all file-system related error in async operation because"
- " scan file list has been provided by server."
- " file: " << file << " ret: " << ret.first);
- continue;
+ DEBUG("event received: " << event);
+
+ switch (event) {
+ case ASYNC_EVENT_MALWARE_NONE: {
+ DEBUG("ASYNC_EVENT_MALWARE_NONE comes in!");
+ auto targetName = this->m_handle->revent<std::string>();
+
+ if (targetName.empty()) {
+ ERROR("scanned event received but target name is empty");
+ break;
+ }
+
+ if (this->m_handle->m_cb.onScanned != nullptr)
+ this->m_handle->m_cb.onScanned(targetName.c_str(), this->m_userdata);
+
+ break;
}
- if (ret.first != CSR_ERROR_NONE)
- ThrowExc(ret.first, "Error on async scan. ret: " << ret.first <<
- " while scan file: " << file);
+ case ASYNC_EVENT_MALWARE_DETECTED: {
+ DEBUG("ASYNC_EVENT_MALWARE_DETECTED comes in!");
+ auto malware = this->m_handle->revent<CsDetected *>();
+
+ if (malware == nullptr) {
+ ERROR("malware detected event received but handle is null");
+ break;
+ }
- if (ret.second) {
- INFO("[Detected] file[" << file << "]");
- this->m_results.emplace_back(std::move(resultPtr));
+ ResultPtr resultPtr(malware);
- if (this->m_cb.onDetected != nullptr)
- this->m_cb.onDetected(reinterpret_cast<csr_cs_malware_h>(ret.second),
- this->m_userdata);
- } else {
- DEBUG("[Scanned] file[" << file << "]");
+ if (this->m_handle->m_cb.onDetected != nullptr) {
+ this->m_handle->add(std::move(resultPtr));
+ this->m_handle->m_cb.onDetected(
+ reinterpret_cast<csr_cs_malware_h>(malware), this->m_userdata);
+ }
+
+ break;
+ }
- if (this->m_cb.onScanned != nullptr)
- this->m_cb.onScanned(file.c_str(), this->m_userdata);
+ case ASYNC_EVENT_COMPLETE: {
+ DEBUG("Async operation completed");
+ isDone = true;
+ break;
}
+
+ default:
+ ThrowExc(event, "Error on async scan! ec: " << event);
+ }
+
+ if (this->m_handle->isStopped())
+ ThrowExcInfo(ASYNC_EVENT_CANCEL, "Async op cancelled!");
}
}
*/
#pragma once
-#include <memory>
-#include <atomic>
-
#include "common/types.h"
-#include "common/cs-context.h"
-#include "client/callback.h"
+#include "common/command-id.h"
#include "client/handle-ext.h"
namespace Csr {
virtual ~AsyncLogic();
void scanFiles(const StrSet &files);
- void scanDir(const std::string &dir);
void scanDirs(const StrSet &dirs);
void stop(void);
private:
- template<typename T>
- void copyKvp(CsContext::Key);
+ void scanHelper(const CommandId &id, const StrSet &s);
HandleExt *m_handle; // for registering results for auto-release
- ContextPtr m_ctx;
- std::vector<ResultPtr> m_results;
-
- Callback m_cb;
void *m_userdata;
};
-template<typename T>
-void AsyncLogic::copyKvp(CsContext::Key key)
-{
- T value;
-
- this->m_handle->getContext()->get(static_cast<int>(key), value);
- this->m_ctx->set(static_cast<int>(key), value);
-}
-
}
}
return apath;
}
-void eraseSubdirectories(StrSet &dirset)
-{
- if (dirset.size() < 2)
- return;
-
- for (auto it = dirset.begin(); it != dirset.end(); ++it) {
- auto itsub = it;
- ++itsub;
- while (true) {
- if (itsub == dirset.end())
- break;
-
- auto itl = it->length();
- auto itsubl = itsub->length();
-
- if (itl + 1 >= itsubl || // to short to be sub-directory
- itsub->compare(0, itl, *it) != 0 || // prefix isn't matched
- (*it != "/" && itsub->at(itl) != '/')) { // has '/' at the end of prefix
- ++itsub;
- continue;
- }
-
- itsub = dirset.erase(itsub);
- }
- }
-}
-
}
}
// based on linux function: realpath
std::string getAbsolutePath(const std::string &path);
-// input directory set should contains resolved path only
-void eraseSubdirectories(StrSet &dirset);
-
} // namespace Client
} // namespace Csr
#include "common/cs-context.h"
#include "common/cs-detected.h"
#include "common/command-id.h"
+#include "common/async-protocol.h"
#include "common/audit/logger.h"
using namespace Csr;
hExt->getContext(),
RawBuffer(data, data + length));
- if (ret.second)
- hExt->add(ResultPtr(ret.second));
+ ResultPtr resultPtr(ret.second);
- *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ if (ret.second && !ret.second->malwareName.empty()) {
+ hExt->add(std::move(resultPtr));
+ *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ } else {
+ *malware = nullptr;
+ }
return ret.first;
hExt->getContext(),
Client::getAbsolutePath(file_path));
- if (ret.second)
- hExt->add(ResultPtr(ret.second));
+ ResultPtr resultPtr(ret.second);
- *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ if (ret.second && !ret.second->malwareName.empty()) {
+ hExt->add(std::move(resultPtr));
+ *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ } else {
+ *malware = nullptr;
+ }
return ret.first;
auto hExt = reinterpret_cast<Client::HandleExt *>(handle);
hExt->m_cb.onScanned = callback;
+ hExt->getContext()->set(static_cast<int>(CsContext::Key::ScannedCbRegistered), true);
return CSR_ERROR_NONE;
EXCEPTION_ASYNC_SAFE_START(hExt->m_cb, user_data)
if (hExt->isStopped())
- ThrowExcInfo(-999, "Async operation cancelled!");
-
- auto ret = hExt->dispatch<std::pair<int, std::shared_ptr<StrSet>>>(
- CommandId::CANONICALIZE_PATHS, *fileSet);
-
- if (ret.first != CSR_ERROR_NONE)
- ThrowExc(ret.first, "Error on getting canonicalized paths in subthread. "
- "ret: " << ret.first);
-
- std::shared_ptr<StrSet> canonicalizedFiles;
-
- if (ret.second == nullptr)
- canonicalizedFiles = std::make_shared<StrSet>();
- else
- canonicalizedFiles = std::move(ret.second);
+ ThrowExcInfo(ASYNC_EVENT_CANCEL, "Async operation cancelled!");
Client::AsyncLogic l(hExt, user_data);
- l.scanFiles(*canonicalizedFiles);
+ l.scanFiles(*fileSet);
EXCEPTION_SAFE_END
});
int csr_cs_scan_dir_async(csr_cs_context_h handle, const char *dir_path,
void *user_data)
{
- EXCEPTION_SAFE_START
-
- if (handle == nullptr)
- return CSR_ERROR_INVALID_HANDLE;
- else if (dir_path == nullptr || dir_path[0] == '\0')
- return CSR_ERROR_INVALID_PARAMETER;
-
- auto hExt = reinterpret_cast<Client::HandleExt *>(handle);
-
- if (hExt->isRunning()) {
- ERROR("Async scanning already running with this handle.");
- return CSR_ERROR_BUSY;
- }
-
- auto dir = std::make_shared<std::string>(Client::getAbsolutePath(dir_path));
-
- auto task = std::make_shared<Task>([hExt, user_data, dir] {
- EXCEPTION_ASYNC_SAFE_START(hExt->m_cb, user_data)
+ const char *dir_paths[1] = { dir_path };
- Client::AsyncLogic l(hExt, user_data);
-
- l.scanDir(*dir);
-
- EXCEPTION_SAFE_END
- });
-
- std::lock_guard<std::mutex> l(hExt->m_dispatchMutex);
-
- hExt->dispatchAsync(task);
-
- return CSR_ERROR_NONE;
-
- EXCEPTION_SAFE_END
+ return ::csr_cs_scan_dirs_async(handle, dir_paths, 1, user_data);
}
API
EXCEPTION_ASYNC_SAFE_START(hExt->m_cb, user_data)
if (hExt->isStopped())
- ThrowExcInfo(-999, "Async operation cancelled!");
-
- auto ret = hExt->dispatch<std::pair<int, std::shared_ptr<StrSet>>>(
- CommandId::CANONICALIZE_PATHS, *dirSet);
-
- if (ret.first != CSR_ERROR_NONE)
- ThrowExc(ret.first, "Error on getting canonicalized paths in subthread. "
- "ret: " << ret.first);
-
- std::shared_ptr<StrSet> canonicalizedDirs;
-
- if (ret.second == nullptr)
- canonicalizedDirs = std::make_shared<StrSet>();
- else
- canonicalizedDirs = std::move(ret.second);
-
- Client::eraseSubdirectories(*canonicalizedDirs);
+ ThrowExcInfo(ASYNC_EVENT_CANCEL, "Async operation cancelled!");
Client::AsyncLogic l(hExt, user_data);
- l.scanDirs(*canonicalizedDirs);
+ l.scanDirs(*dirSet);
EXCEPTION_SAFE_END
});
auto ret = hExt->dispatch<std::pair<int, CsDetected *>>(
CommandId::GET_DETECTED, Client::getAbsolutePath(file_path));
- if (ret.second)
- hExt->add(ResultPtr(ret.second));
+ ResultPtr resultPtr(ret.second);
- *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ if (ret.second && !ret.second->malwareName.empty()) {
+ hExt->add(std::move(resultPtr));
+ *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ } else {
+ *malware = nullptr;
+ }
return ret.first;
auto ret = hExt->dispatch<std::pair<int, CsDetected *>>(
CommandId::GET_IGNORED, Client::getAbsolutePath(file_path));
- if (ret.second)
- hExt->add(ResultPtr(ret.second));
+ ResultPtr resultPtr(ret.second);
- *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ if (ret.second && !ret.second->malwareName.empty()) {
+ hExt->add(std::move(resultPtr));
+ *malware = reinterpret_cast<csr_cs_malware_h>(ret.second);
+ } else {
+ *malware = nullptr;
+ }
return ret.first;
template<typename ...Args>
void ping(Args &&...);
+ template<typename Type>
+ Type revent(void);
+
virtual void add(ResultPtr &&);
virtual void add(ResultListPtr &&);
this->m_dispatcher->methodPing(std::forward<Args>(args)...);
}
+template<typename Type>
+Type Handle::revent()
+{
+ return this->m_dispatcher->receiveEvent<Type>();
+}
+
} // namespace Client
} // namespace Csr
#include "common/audit/logger.h"
#include "common/exception.h"
+#include "common/async-protocol.h"
+
#include <csr-error.h>
__attribute__((constructor))
if (callbacks.onCompleted != nullptr)
callbacks.onCompleted(userdata);
} catch (const Exception &e) {
- if (e.error() == -999) {
+ if (e.error() == ASYNC_EVENT_CANCEL) {
INFO("Async operation cancel exception!");
if (callbacks.onCancelled != nullptr)
callbacks.onCancelled(userdata);
--- /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 async-protocol.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Protocol for asynchronous scanning operations
+ */
+#pragma once
+
+namespace Csr {
+
+// should be positive values not to be conflicted with error code in csr-error.h
+typedef enum {
+ ASYNC_EVENT_START = 0x10, // operation started
+ ASYNC_EVENT_COMPLETE = 0x20, // operation completed
+ ASYNC_EVENT_CANCEL = 0x30, // operation cancelled
+ ASYNC_EVENT_MALWARE_NONE = 0x40, // target scanned and no malware detected
+ ASYNC_EVENT_MALWARE_DETECTED = 0x50, // target scanned and malware detected
+} async_op_protocol_e;
+
+}
GET_DETECTED_LIST = 0x1102,
GET_IGNORED = 0x1103,
GET_IGNORED_LIST = 0x1104,
- GET_SCANNABLE_FILES = 0x1105,
- CANONICALIZE_PATHS = 0x1106,
- SET_DIR_TIMESTAMP = 0x1107,
+ SCAN_DIRS_ASYNC = 0x1105,
+ SCAN_FILES_ASYNC = 0x1106,
CANCEL_OPERATION = 0x1108,
// handle result
JUDGE_STATUS = 0x1201,
CsContext::CsContext() noexcept :
askUser(CSR_CS_ASK_USER_NO),
coreUsage(CSR_CS_CORE_USAGE_DEFAULT),
- isScanOnCloud(false)
+ isScanOnCloud(false),
+ isScannedCbRegistered(false)
{
}
{
int intAskUser;
int intCoreUsage;
- Deserializer<std::string, int, int, bool>::Deserialize(stream,
- this->popupMessage, intAskUser, intCoreUsage, this->isScanOnCloud);
+ Deserializer<std::string, int, int, bool, bool>::Deserialize(stream,
+ this->popupMessage, intAskUser, intCoreUsage, this->isScanOnCloud,
+ this->isScannedCbRegistered);
this->askUser = static_cast<csr_cs_ask_user_e>(intAskUser);
this->coreUsage = static_cast<csr_cs_core_usage_e>(intCoreUsage);
void CsContext::Serialize(IStream &stream) const
{
- Serializer<std::string, int, int, bool>::Serialize(stream,
+ Serializer<std::string, int, int, bool, bool>::Serialize(stream,
this->popupMessage, static_cast<int>(this->askUser),
- static_cast<int>(this->coreUsage), this->isScanOnCloud);
+ static_cast<int>(this->coreUsage), this->isScanOnCloud,
+ this->isScannedCbRegistered);
}
void CsContext::set(int key, int value)
this->isScanOnCloud = value;
break;
+ case Key::ScannedCbRegistered:
+ this->isScannedCbRegistered = value;
+ break;
+
default:
ThrowExc(CSR_ERROR_SERVER, "Invalid key[" << key << "] comes in to set as bool.");
}
value = this->isScanOnCloud;
break;
+ case Key::ScannedCbRegistered:
+ value = this->isScannedCbRegistered;
+ break;
+
default:
ThrowExc(CSR_ERROR_SERVER, "Invalid key[" << key << "] comes in to get as bool.");
}
CoreUsage = 0x11, // int
ScanOnCloud = 0x20, // bool
+ ScannedCbRegistered = 0x21,
};
CsContext() noexcept;
csr_cs_ask_user_e askUser;
csr_cs_core_usage_e coreUsage;
bool isScanOnCloud;
+ bool isScannedCbRegistered;
};
}
template<typename ...Args>
void methodPing(Args &&...args);
+ template<typename Type>
+ Type receiveEvent(void);
+
private:
void connect(void);
this->m_connection->send(BinaryQueue::Serialize(std::forward<Args>(args)...).pop());
}
+template<typename Type>
+Type Dispatcher::receiveEvent()
+{
+ this->connect();
+
+ BinaryQueue q;
+ q.push(this->m_connection->receive());
+
+ Type response;
+ q.Deserialize(response);
+
+ return response;
+}
+
}
object.reset(new T(stream));
}
+ template <typename T>
+ static void Deserialize(IStream &stream, std::unique_ptr<T> &object)
+ {
+ if (stream.empty())
+ object.reset();
+ else
+ object.reset(new T(stream));
+ }
+
// char
static void Deserialize(IStream &stream, char &value)
{
}
}
+ template <typename T, typename R, typename A>
+ static void Deserialize(IStream &stream, std::unique_ptr<std::basic_string<T, R, A>> &str)
+ {
+ if (stream.empty()) {
+ str.reset();
+ } else {
+ int length;
+ stream.read(sizeof(length), &length);
+ std::vector<T> buf(length);
+ stream.read(length * sizeof(T), buf.data());
+ str.reset(new std::basic_string<T, R, A>(buf.data(), buf.data() + length));
+ }
+ }
+
// STL templates
// std::list
Deserialize(stream, *list);
}
}
+ template <typename T>
+ static void Deserialize(IStream &stream, std::unique_ptr<std::list<T>> &list)
+ {
+ if (stream.empty()) {
+ list.reset();
+ } else {
+ list.reset(new std::list<T>);
+ Deserialize(stream, *list);
+ }
+ }
template <typename T>
static void Deserialize(IStream &stream, std::set<T> &set)
Deserialize(stream, *set);
}
}
+ template <typename T>
+ static void Deserialize(IStream &stream, std::unique_ptr<std::set<T>> &set)
+ {
+ if (stream.empty()) {
+ set.reset();
+ } else {
+ set.reset(new std::set<T>);
+ Deserialize(stream, *set);
+ }
+ }
// RawBuffer
template <typename A>
Deserialize(stream, *vec);
}
}
+ template <typename A>
+ static void Deserialize(IStream &stream, std::unique_ptr<std::vector<unsigned char, A>> &vec)
+ {
+ if (stream.empty()) {
+ vec.reset();
+ } else {
+ vec.reset(new std::vector<unsigned char, A>);
+ Deserialize(stream, *vec);
+ }
+ }
// std::vector
template <typename T, typename A>
size_t total = 0;
size_t size = 0;
- DEBUG("Read data from stream on socket fd[" << this->m_fd << "]");
-
auto bytes = ::read(this->m_fd, &size, sizeof(size));
if (bytes < 0)
- ThrowExc(CSR_ERROR_SOCKET, "Socket data size read failed with errno: " << errno);
+ ThrowExc(CSR_ERROR_SOCKET, "Socket data size read failed on fd[" << this->m_fd <<
+ "] with errno: " << errno);
RawBuffer data(size, 0);
auto buf = reinterpret_cast<char *>(data.data());
auto buf = reinterpret_cast<const char *>(data.data());
auto size = data.size();
- DEBUG("Write data to stream on socket fd[" << this->m_fd << "]");
-
auto bytes = ::write(this->m_fd, &size, sizeof(size));
if (bytes < 0)
- ThrowExc(CSR_ERROR_SOCKET, "Socket data size write failed with errno: " << errno);
+ ThrowExc(CSR_ERROR_SOCKET, "Socket data size write failed on fd[" << this->m_fd <<
+ "] with errno: " << errno);
while (total < size) {
bytes = ::write(this->m_fd, buf + total, size - total);
return row;
}
-void Manager::insertDetectedFile(const std::string &filepath, const CsDetected &d,
- const std::string &dataVersion)
+void Manager::insertDetectedFile(const CsDetected &d, const std::string &dataVersion)
{
std::lock_guard<std::mutex> l(this->m_mutex);
- this->insertName(filepath);
- this->insertDetected(d, filepath, dataVersion);
+ this->insertName(d.targetName);
+ this->insertDetected(d, d.targetName, dataVersion);
}
-void Manager::insertDetectedFileInApp(const std::string &pkgpath, const std::string &filepath,
+void Manager::insertDetectedFileInApp(const std::string &filepath,
const CsDetected &d, const std::string &dataVersion)
{
std::lock_guard<std::mutex> l(this->m_mutex);
- this->insertName(pkgpath);
+ this->insertName(d.targetName);
this->insertDetected(d, filepath, dataVersion);
}
RowShPtrs getDetectedByFilepathOnDir(const std::string &dir, time_t since);
RowShPtr getWorstByPkgPath(const std::string &pkgPath, time_t since);
- void insertDetectedFile(const std::string &filepath, const CsDetected &d,
- const std::string &dataVersion);
- void insertDetectedFileInApp(const std::string &pkgpath, const std::string &filepath,
+ void insertDetectedFile(const CsDetected &d, const std::string &dataVersion);
+ void insertDetectedFileInApp(const std::string &filepath,
const CsDetected &d, const std::string &dataVersion);
void insertDetectedAppByCloud(const std::string &name, const std::string &pkgId,
const CsDetected &d, const std::string &dataVersion);
#include "service/cs-logic.h"
#include <utility>
+#include <cstdlib>
#include <climits>
#include <cerrno>
#include <unistd.h>
#include "common/audit/logger.h"
#include "common/exception.h"
+#include "common/async-protocol.h"
#include "service/type-converter.h"
#include "service/core-usage.h"
#include "service/dir-blacklist.h"
{
auto resolved = resolvePath(path);
- auto fileptr = File::create(path, nullptr);
+ auto fileptr = File::create(resolved, nullptr);
if (!isReadable(fileptr->getName()))
ThrowExcWarn(CSR_ERROR_FILE_DO_NOT_EXIST, "File is not readable: " << fileptr->getName());
return fileptr;
}
+void eraseSubdirectories(StrSet &dirset)
+{
+ if (dirset.size() < 2)
+ return;
+
+ for (auto it = dirset.begin(); it != dirset.end(); ++it) {
+ auto itsub = it;
+ ++itsub;
+ while (true) {
+ if (itsub == dirset.end())
+ break;
+
+ auto itl = it->length();
+ auto itsubl = itsub->length();
+
+ if (itl + 1 >= itsubl || // to short to be sub-directory
+ itsub->compare(0, itl, *it) != 0 || // prefix isn't matched
+ (*it != "/" && itsub->at(itl) != '/')) { // has '/' at the end of prefix
+ ++itsub;
+ continue;
+ }
+
+ itsub = dirset.erase(itsub);
+ }
+ }
+}
+
} // namespace anonymous
CsLogic::CsLogic(const std::shared_ptr<CsLoader> &loader,
if (result == nullptr)
return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
- auto d = this->convert(result, std::string(), timestamp);
+ auto malware = this->convert(result, std::string(), timestamp);
- return this->handleAskUser(context, d);
+ return BinaryQueue::Serialize(this->handleAskUser(context, *malware), malware).pop();
}
-RawBuffer CsLogic::scanAppOnCloud(const CsContext &context,
- const std::string &pkgPath,
- const std::string &pkgId)
+int CsLogic::scanAppOnCloud(const CsContext &context, const FilePtr &pkgPtr,
+ CsDetectedPtr &malware)
{
+ const auto &pkgPath = pkgPtr->getName();
+ const auto &pkgId = pkgPtr->getAppPkgId();
+
CsEngineContext engineContext(this->m_loader);
auto &c = engineContext.get();
this->m_loader->scanAppOnCloud(c, pkgPath, &result);
if (!result)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
- auto detected = this->convert(result, pkgPath, timestamp);
- detected.isApp = true;
- detected.pkgId = pkgId;
+ malware = this->convert(result, pkgPath, timestamp);
+ malware->isApp = true;
+ malware->pkgId = pkgId;
- this->m_db->insertDetectedAppByCloud(pkgPath, pkgId, detected, this->m_dataVersion);
+ this->m_db->insertDetectedAppByCloud(pkgPath, pkgId, *malware, this->m_dataVersion);
- return this->handleAskUser(context, detected);
+ return this->handleAskUser(context, *malware, pkgPtr);
}
-CsDetectedPtr CsLogic::scanAppDelta(const std::string &pkgPath, const std::string &pkgId,
- std::string &riskiestPath)
+CsDetectedPtr CsLogic::scanAppDelta(const FilePtr &pkgPtr, std::string &riskiestPath)
{
+ const auto &pkgPath = pkgPtr->getName();
+ const auto &pkgId = pkgPtr->getAppPkgId();
+
auto starttime = ::time(nullptr);
CsEngineContext engineContext(this->m_loader);
INFO("New malware detected on file: " << file->getPath());
auto candidate = this->convert(result, pkgPath, timestamp);
- candidate.isApp = true;
- candidate.pkgId = pkgId;
+ candidate->isApp = true;
+ candidate->pkgId = pkgId;
- this->m_db->insertDetectedFileInApp(pkgPath, file->getPath(), candidate,
- this->m_dataVersion);
+ this->m_db->insertDetectedFileInApp(file->getPath(), *candidate, this->m_dataVersion);
- if (!riskiest) {
- riskiest.reset(new CsDetected(std::move(candidate)));
- riskiestPath = file->getPath();
- } else if (*riskiest < candidate) {
- *riskiest = std::move(candidate);
+ if (riskiest == nullptr || *riskiest < *candidate) {
+ riskiest = std::move(candidate);
riskiestPath = file->getPath();
}
}, pkgPath, false, lastScanTime);
return riskiest;
}
-RawBuffer CsLogic::scanApp(const CsContext &context, const FilePtr &pkgPtr)
+int CsLogic::scanApp(const CsContext &context, const FilePtr &pkgPtr,
+ CsDetectedPtr &malware)
{
const auto &pkgPath = pkgPtr->getName();
const auto &pkgId = pkgPtr->getAppPkgId();
if (context.isScanOnCloud && this->m_loader->scanAppOnCloudSupported())
- return this->scanAppOnCloud(context, pkgPath, pkgId);
+ return this->scanAppOnCloud(context, pkgPtr, malware);
CsEngineContext engineContext(this->m_loader);
auto since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
auto history = this->m_db->getWorstByPkgPath(pkgPath, since);
// riskiest detected among newly scanned files
std::string riskiestPath;
- auto riskiest = this->scanAppDelta(pkgPath, pkgId, riskiestPath);
+ auto riskiest = this->scanAppDelta(pkgPtr, riskiestPath);
// history after delta scan. if worst file is changed, it's rescanned in scanAppDelta
// and deleted from db if it's cured. if history != nullptr && after == nullptr,
// it means worst detected item is cured anyway.
this->m_db->insertWorst(pkgId, pkgPath, riskiestPath);
- return this->handleAskUser(context, *riskiest);
+ malware.reset(new CsDetected());
+ *malware = std::move(*riskiest);
+ return this->handleAskUser(context, *malware);
} else {
INFO("worst case is remained and can be re-used on pkg[" << pkgPath << "]");
if (history->isIgnored)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
- return this->handleAskUser(context, *history);
+ malware.reset(new CsDetected());
+ *malware = std::move(*history);
+ return this->handleAskUser(context, *malware);
}
} else if (history && after && !riskiest) {
INFO("worst case is remained and NO new detected. history can be re-used. "
"on pkg[" << pkgPath << "]");
if (history->isIgnored)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
- return this->handleAskUser(context, *history);
+ malware.reset(new CsDetected());
+ *malware = std::move(*history);
+ return this->handleAskUser(context, *malware);
} else if (history && !after && riskiest) {
INFO("worst case is deleted but new detected. we have to find out "
"worse case in db and compare it with riskiest first. on pkg[" << pkgPath <<
if (!worse) {
INFO("No detected malware found in db.... Newly detected malware is removed by "
"other client. Handle it as fully clean case.");
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
}
if (*riskiest < *worse) {
this->m_db->insertWorst(pkgId, pkgPath, riskiestPath);
- return this->handleAskUser(context, *riskiest);
+ malware.reset(new CsDetected());
+ *malware = std::move(*riskiest);
+ return this->handleAskUser(context, *malware);
} else {
INFO("worst case is deleted but same or less level newly detected. on pkg[" <<
pkgPath << "]");
this->m_db->insertWorst(pkgId, pkgPath, riskiestPath);
if (history->isIgnored)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
- return this->handleAskUser(context, *riskiest);
+ malware.reset(new CsDetected());
+ *malware = std::move(*riskiest);
+ return this->handleAskUser(context, *malware);
}
} else if (history && !after && !riskiest) {
since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
this->m_db->insertWorst(pkgId, pkgPath, worse->fileInAppPath);
if (worse->isIgnored)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
- return this->handleAskUser(context, *worse);
+ malware.reset(new CsDetected());
+ *malware = std::move(*worse);
+ return this->handleAskUser(context, *malware);
}
}
"NO worse case. the pkg[" << pkgPath << "] is clean.");
this->m_db->deleteDetectedByNameOnPath(pkgPath);
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
} else if (!history && riskiest) {
INFO("no history and new detected");
this->m_db->insertWorst(pkgId, pkgPath, riskiestPath);
- return this->handleAskUser(context, *riskiest);
+ malware.reset(new CsDetected());
+ *malware = std::move(*riskiest);
+ return this->handleAskUser(context, *malware);
} else {
DEBUG("no history and no new detected");
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
}
}
-RawBuffer CsLogic::scanFile(const CsContext &context, const std::string &filepath)
+int CsLogic::scanFileInternal(const CsContext &context, const FilePtr &target,
+ CsDetectedPtr &malware)
{
- if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
- ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
-
- setCoreUsage(context.coreUsage);
-
- auto target = canonicalizePathWithFile(filepath);
-
if (target->isInApp())
- return this->scanApp(context, target);
+ return this->scanApp(context, target, malware);
const auto &name = target->getName();
DEBUG("Scan request on file: " << name);
if (isInBlackList(name))
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
CsEngineContext engineContext(this->m_loader);
auto &c = engineContext.get();
// detected handle is null if it's safe
if (result == nullptr)
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return CSR_ERROR_NONE;
INFO("Malware detected on file: " << name);
- auto d = this->convert(result, name, timestamp);
+ malware = this->convert(result, name, timestamp);
// check malware detected history for inherit ignored flag
auto since = this->m_loader->getEngineLatestUpdateTime(c);
auto history = this->m_db->getDetectedAllByNameOnPath(name, since);
- this->m_db->insertDetectedFile(d.targetName, d, this->m_dataVersion);
+ this->m_db->insertDetectedFile(*malware, this->m_dataVersion);
- if (history != nullptr && history->isIgnored && !(d > *history))
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
- else
- return this->handleAskUser(context, d, std::move(target));
+ if (history != nullptr && history->isIgnored && !(*malware > *history)) {
+ INFO("Ignore malware on file: " << name);
+ malware.reset();
+ return CSR_ERROR_NONE;
+ } else {
+ return this->handleAskUser(context, *malware, target);
+ }
}
-// Application in input param directory will be treated as one item.
-// Application base directory path is inserted to file set.
-// e.g., input param dir : "/opt/usr" (applications in "/opt/usr/apps")
-// ls /opt/usr/ :
-// /opt/usr/file-not-in-app1
-// /opt/usr/file-not-in-app2
-// /opt/usr/apps/org.tizen.tutorial
-// /opt/usr/apps/org.tizen.tutorial/file-in-app1
-// /opt/usr/apps/org.tizen.tutorial/file-in-app2
-// /opt/usr/apps/org.tizen.message/file-in-app1
-// /opt/usr/apps/org.tizen.message/file-in-app2
-// /opt/usr/apps/org.tizen.flash/file-in-app1
-// /opt/usr/apps/org.tizen.flash/file-in-app2
-//
-// and detected history exist on...
-// /opt/usr/apps/org.tizen.message/file-in-app2
-// /opt/usr/apps/org.tizen.flash (If target name is app base directory path,
-// it's detected by scan on cloud)
-//
-// output scannable file set will be:
-// 1) /opt/usr/file-not-in-app1
-// 2) /opt/usr/file-not-in-app2
-// 3) /opt/usr/apps/org.tizen.tutorial (app base directory path)
-// 4) /opt/usr/apps/org.tizen.message (app base directory path)
-// 5) /opt/usr/apps/org.tizen.flash (app base directory path)
-// % items which has detected history is included in list as well.
-RawBuffer CsLogic::getScannableFiles(const std::string &dir, const std::function<void()> &isCancelled)
+RawBuffer CsLogic::scanFile(const CsContext &context, const std::string &filepath)
{
if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
- auto targetdir = canonicalizePath(dir, true);
+ setCoreUsage(context.coreUsage);
- CsEngineContext csEngineContext(this->m_loader);
- auto since = this->m_loader->getEngineLatestUpdateTime(csEngineContext.get());
+ CsDetectedPtr malware;
+ auto ret = this->scanFileInternal(context, canonicalizePathWithFile(filepath), malware);
+ if (malware != nullptr)
+ return BinaryQueue::Serialize(ret, malware).pop();
+ else
+ return BinaryQueue::Serialize(ret).pop();
+}
- auto lastScanTime = this->m_db->getLastScanTime(targetdir, since);
+RawBuffer CsLogic::scanFilesAsync(const ConnShPtr &conn, const CsContext &context,
+ StrSet &paths, const std::function<void()> &isCancelled)
+{
+ if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
+ ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
- StrSet fileset;
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_START).pop());
- auto visitor = FsVisitor::create([&](const FilePtr &file) {
+ StrSet canonicalized;
+
+ for (const auto &path : paths) {
isCancelled();
- DEBUG("Scannable item: " << file->getName());
- fileset.insert(file->getName());
- }, targetdir, true, lastScanTime);
+ FilePtr target;
+ try {
+ target = canonicalizePathWithFile(path);
- visitor->run();
+ if (canonicalized.find(target->getName()) != canonicalized.end())
+ continue;
+
+ INFO("Insert to canonicalized list: " << target->getName());
+ canonicalized.insert(target->getName());
+ } catch (const Exception &e) {
+ if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST ||
+ e.error() == CSR_ERROR_FILE_SYSTEM) {
+ WARN("File-system related exception occured while getting "
+ "canonicalize path of path: " << path << " " << e.what() <<
+ ". Ignore this exception.");
+ continue;
+ } else {
+ ERROR("Non-file-system related exception occured while getting "
+ "canonicalize path of path: " << path << " " << e.what());
+ throw;
+ }
+ }
- isCancelled();
+ CsDetectedPtr malware;
+ auto retcode = this->scanFileInternal(context, target, malware);
+
+ switch (retcode) {
+ case CSR_ERROR_NONE:
+ case CSR_ERROR_FILE_DO_NOT_EXIST:
+ case CSR_ERROR_FILE_CHANGED:
+ case CSR_ERROR_FILE_SYSTEM:
+ if (malware != nullptr) {
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_DETECTED).pop());
+ conn->send(BinaryQueue::Serialize(malware).pop());
+ } else if (context.isScannedCbRegistered) {
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_NONE).pop());
+ conn->send(BinaryQueue::Serialize(target->getName()).pop());
+ }
+
+ break;
- if (lastScanTime != -1) {
- // for case: scan history exist and not modified.
- for (auto &row : this->m_db->getDetectedAllByNameOnDir(targetdir, since)) {
+ default:
+ ThrowExc(retcode, "Error on async scanning: " << retcode);
+ }
+ }
+
+ return BinaryQueue::Serialize(ASYNC_EVENT_COMPLETE).pop();
+}
+
+RawBuffer CsLogic::scanDirsAsync(const ConnShPtr &conn, const CsContext &context,
+ StrSet &paths, const std::function<void()> &isCancelled)
+{
+ if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
+ ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
+
+ StrSet dirs;
+
+ for (const auto &path : paths) {
+ try {
+ auto target = canonicalizePath(File::getPkgPath(path), true);
+
+ if (dirs.find(target) == dirs.end()) {
+ INFO("Insert to canonicalized list: " << target);
+ dirs.emplace(std::move(target));
+ }
+ } catch (const Exception &e) {
+ if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST ||
+ e.error() == CSR_ERROR_FILE_SYSTEM) {
+ WARN("File-system related exception occured while getting "
+ "canonicalize path of path: " << path << " " << e.what() <<
+ ". Ignore this exception.");
+ continue;
+ } else {
+ ERROR("Non-file-system related exception occured while getting "
+ "canonicalize path of path: " << path << " " << e.what());
+ throw;
+ }
+ }
+ }
+
+ eraseSubdirectories(dirs);
+
+ DEBUG("send error none to client before starting scanning");
+
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_START).pop());
+
+ CsEngineContext engineContext(this->m_loader);
+ auto t = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
+
+ DEBUG("Start async scanning!!!!!");
+
+ StrSet malwareList;
+ for (const auto &dir : dirs) {
+ isCancelled();
+
+ DEBUG("Start async scanning for dir: " << dir);
+
+ for (auto &row : this->m_db->getDetectedAllByNameOnDir(dir, t)) {
isCancelled();
try {
auto fileptr = File::create(row->targetName, nullptr);
- fileset.insert(fileptr->getName());
+ CsDetectedPtr malware;
+ auto retcode = this->scanFileInternal(context, fileptr, malware);
+
+ switch (retcode) {
+ case CSR_ERROR_NONE:
+ case CSR_ERROR_FILE_DO_NOT_EXIST:
+ case CSR_ERROR_FILE_CHANGED:
+ case CSR_ERROR_FILE_SYSTEM:
+ if (malware != nullptr) {
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_DETECTED).pop());
+ conn->send(BinaryQueue::Serialize(malware).pop());
+ malwareList.insert(row->targetName);
+ } else if (context.isScannedCbRegistered) {
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_NONE).pop());
+ conn->send(BinaryQueue::Serialize(row->targetName).pop());
+ this->m_db->deleteDetectedByNameOnPath(row->targetName);
+ }
+
+ break;
+
+ default:
+ ERROR("Error on rescanning detected malwares in db: " << retcode <<
+ " file: " << fileptr->getName());
+ this->m_db->deleteDetectedByNameOnPath(row->targetName);
+ return BinaryQueue::Serialize(retcode).pop();
+ }
} catch (const Exception &e) {
if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST ||
e.error() == CSR_ERROR_FILE_SYSTEM)
throw;
}
}
- }
- return BinaryQueue::Serialize(CSR_ERROR_NONE, fileset).pop();
-}
+ auto startTime = ::time(nullptr);
+ auto lastScanTime = this->m_db->getLastScanTime(dir, t);
+ auto visitor = FsVisitor::create([&](const FilePtr &file) {
+ isCancelled();
-RawBuffer CsLogic::canonicalizePaths(const StrSet &paths)
-{
- if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
- ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
+ CsDetectedPtr malware;
+ auto retcode = this->scanFileInternal(context, file, malware);
+
+ DEBUG("scanFileInternal done. file: " << file->getName() <<
+ " retcode: " << retcode);
+
+ switch (retcode) {
+ case CSR_ERROR_NONE:
+ case CSR_ERROR_FILE_DO_NOT_EXIST:
+ case CSR_ERROR_FILE_CHANGED:
+ case CSR_ERROR_FILE_SYSTEM:
+ if (malware != nullptr) {
+ auto it = malwareList.find(file->getName());
+ if (it != malwareList.end()) {
+ malwareList.erase(it);
+ break;
+ }
+
+ DEBUG("Malware detected!!!");
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_DETECTED).pop());
+ conn->send(BinaryQueue::Serialize(malware).pop());
+ } else if (context.isScannedCbRegistered) {
+ DEBUG("File scanned!!!");
+ conn->send(BinaryQueue::Serialize(ASYNC_EVENT_MALWARE_NONE).pop());
+ conn->send(BinaryQueue::Serialize(file->getName()).pop());
+ }
+
+ break;
+
+ default:
+ ThrowExc(retcode, "Error on async scanning: " << retcode);
+ }
+ }, dir, true, lastScanTime);
- StrSet canonicalized;
+ visitor->run();
- for (const auto &path : paths) {
- auto target = canonicalizePath(path, true);
+ this->m_db->insertLastScanTime(dir, this->m_dataVersion, startTime);
- if (canonicalized.find(target) == canonicalized.end()) {
- INFO("Insert to canonicalized list: " << target);
- canonicalized.emplace(std::move(target));
- }
+ if (lastScanTime == -1)
+ continue;
}
- return BinaryQueue::Serialize(CSR_ERROR_NONE, canonicalized).pop();
-}
-
-RawBuffer CsLogic::setDirTimestamp(const std::string &dir, time_t ts)
-{
- this->m_db->insertLastScanTime(dir, this->m_dataVersion, ts);
-
- return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+ return BinaryQueue::Serialize(ASYNC_EVENT_COMPLETE).pop();
}
RawBuffer CsLogic::judgeStatus(const std::string &filepath, csr_cs_action_e action)
return BinaryQueue::Serialize(CSR_ERROR_NONE, rows).pop();
}
-RawBuffer CsLogic::handleAskUser(const CsContext &c, CsDetected &d, FilePtr &&fileptr)
+int CsLogic::handleAskUser(const CsContext &c, CsDetected &d, const FilePtr &fileptr)
{
if (c.askUser == CSR_CS_ASK_USER_NO) {
d.response = CSR_CS_USER_RESPONSE_USER_NOT_ASKED;
- return BinaryQueue::Serialize(CSR_ERROR_NONE, d).pop();
+ return CSR_ERROR_NONE;
}
Ui::CommandId cid;
auto r = askUser.cs(cid, c.popupMessage, d);
if (r == -1) {
ERROR("Failed to get user response by popup service for target: " << d.targetName);
- return BinaryQueue::Serialize(CSR_ERROR_USER_RESPONSE_FAILED, d).pop();
+ return CSR_ERROR_USER_RESPONSE_FAILED;
}
d.response = r;
- if (d.response == CSR_CS_USER_RESPONSE_REMOVE && !d.targetName.empty()) {
- try {
- FilePtr _fileptr;
- if (fileptr)
- _fileptr = std::move(fileptr);
- else
- _fileptr = File::create(d.targetName, nullptr);
+ if (d.response != CSR_CS_USER_RESPONSE_REMOVE || d.targetName.empty())
+ return CSR_ERROR_NONE;
- _fileptr->remove();
- } catch (const Exception &e) {
- if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST)
- WARN("File already removed.: " << d.targetName);
- else if (e.error() == CSR_ERROR_FILE_SYSTEM)
- WARN("File type is changed, considered as different file: " <<
- d.targetName);
- else if (e.error() == CSR_ERROR_REMOVE_FAILED)
- return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED, d).pop();
- else
- throw;
- }
-
- this->m_db->deleteDetectedByNameOnPath(d.targetName);
+ try {
+ if (fileptr != nullptr)
+ fileptr->remove();
+ else
+ File::create(d.targetName, nullptr)->remove();
+ } catch (const Exception &e) {
+ if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST)
+ WARN("File already removed.: " << d.targetName);
+ else if (e.error() == CSR_ERROR_FILE_SYSTEM)
+ WARN("File type is changed, considered as different file: " << d.targetName);
+ else if (e.error() == CSR_ERROR_REMOVE_FAILED)
+ return CSR_ERROR_REMOVE_FAILED;
+ else
+ throw;
}
- return BinaryQueue::Serialize(CSR_ERROR_NONE, d).pop();
+ this->m_db->deleteDetectedByNameOnPath(d.targetName);
+ return CSR_ERROR_NONE;
}
-CsDetected CsLogic::convert(csre_cs_detected_h &result, const std::string &targetName,
+CsDetectedPtr CsLogic::convert(csre_cs_detected_h &result, const std::string &targetName,
time_t timestamp)
{
DEBUG("convert engine result handle to CsDetected start");
- CsDetected d;
+ CsDetectedPtr malware(new CsDetected());
- d.targetName = targetName;
+ malware->targetName = targetName;
csre_cs_severity_level_e eseverity = CSRE_CS_SEVERITY_LOW;
this->m_loader->getSeverity(result, &eseverity);
- this->m_loader->getMalwareName(result, d.malwareName);
- this->m_loader->getDetailedUrl(result, d.detailedUrl);
+ this->m_loader->getMalwareName(result, malware->malwareName);
+ this->m_loader->getDetailedUrl(result, malware->detailedUrl);
- d.ts = timestamp;
- d.severity = Csr::convert(eseverity);
+ malware->ts = timestamp;
+ malware->severity = Csr::convert(eseverity);
- return d;
+ return malware;
}
}
RawBuffer scanData(const CsContext &context, const RawBuffer &data);
RawBuffer scanFile(const CsContext &context, const std::string &filepath);
- RawBuffer getScannableFiles(const std::string &dir, const std::function<void()> &isCancelled);
- RawBuffer canonicalizePaths(const StrSet &paths);
- RawBuffer setDirTimestamp(const std::string &dir, time_t ts);
+ RawBuffer scanFilesAsync(const ConnShPtr &conn, const CsContext &context,
+ StrSet &paths, const std::function<void()> &isCancelled);
+ RawBuffer scanDirsAsync(const ConnShPtr &conn, const CsContext &context,
+ StrSet &paths, const std::function<void()> &isCancelled);
RawBuffer judgeStatus(const std::string &filepath, csr_cs_action_e action);
RawBuffer getDetected(const std::string &filepath);
RawBuffer getDetectedList(const StrSet &dirSet);
RawBuffer getIgnoredList(const StrSet &dirSet);
private:
- RawBuffer scanApp(const CsContext &context, const FilePtr &pkgPtr);
- RawBuffer scanAppOnCloud(const CsContext &context, const std::string &pkgPath,
- const std::string &pkgId);
- CsDetectedPtr scanAppDelta(const std::string &pkgPath, const std::string &pkgId,
- std::string &riskiestPath);
+ int scanFileInternal(const CsContext &context, const FilePtr &target, CsDetectedPtr &malware);
+ int scanApp(const CsContext &context, const FilePtr &pkgPtr, CsDetectedPtr &malware);
+ int scanAppOnCloud(const CsContext &context, const FilePtr &pkgPtr, CsDetectedPtr &malware);
+ CsDetectedPtr scanAppDelta(const FilePtr &pkgPtr, std::string &riskiestPath);
- CsDetected convert(csre_cs_detected_h &result, const std::string &targetName,
+ CsDetectedPtr convert(csre_cs_detected_h &result, const std::string &targetName,
time_t timestamp);
- RawBuffer handleAskUser(const CsContext &c, CsDetected &d,
- FilePtr &&fileptr = nullptr);
+ int handleAskUser(const CsContext &c, CsDetected &d, const FilePtr &fileptr = nullptr);
std::shared_ptr<CsLoader> m_loader;
std::shared_ptr<Db::Manager> m_db;
INFO("Visiting files start from dir: " << this->m_path);
- this->run(dirptr, currentdir);
+ if (this->m_isBasedOnName && currentdir->isInApp())
+ this->m_targetHandler(currentdir);
+ else
+ this->run(dirptr, currentdir);
}
} // namespace Csr
#include "common/cs-detected.h"
#include "common/wp-result.h"
#include "common/exception.h"
+#include "common/async-protocol.h"
#include "service/exception.h"
#include "service/access-control.h"
#include "service/core-usage.h"
CID_TOSTRING(GET_DETECTED_LIST);
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(SCAN_DIRS_ASYNC);
+ CID_TOSTRING(SCAN_FILES_ASYNC);
CID_TOSTRING(CANCEL_OPERATION);
CID_TOSTRING(JUDGE_STATUS);
return id;
}
-}
+} // namespace anonymous
ServerService::ServerService() : Service(), m_workqueue(5)
{
return this->m_cslogic->scanFile(*cptr, filepath);
}
- case CommandId::GET_SCANNABLE_FILES: {
+ case CommandId::SCAN_FILES_ASYNC: {
hasPermission(conn);
- std::string dir;
- q.Deserialize(dir);
+ CsContextShPtr cptr;
+ StrSet paths;
+ q.Deserialize(cptr, paths);
auto fd = conn->getFd();
{
std::lock_guard<std::mutex> l(this->m_cancelledMutex);
this->m_isCancelled[fd] = false;
- INFO("Turn off cancelled flag before scannable files start on fd: " << fd);
+ INFO("Turn off cancelled flag before start async. fd: " << fd);
}
Closer closer([this, fd]() {
INFO("Erase cancelled flag in closer on fd: " << fd);
});
- return this->m_cslogic->getScannableFiles(dir, [this, fd]() {
+ return this->m_cslogic->scanFilesAsync(conn, *cptr, paths, [this, fd]() {
std::lock_guard<std::mutex> l(this->m_cancelledMutex);
if (this->m_isCancelled.count(fd) == 1 && this->m_isCancelled[fd])
- ThrowExcInfo(-999, "operation cancelled on fd: " << fd);
+ ThrowExcInfo(ASYNC_EVENT_CANCEL, "operation cancelled on fd: " << fd);
});
}
- case CommandId::CANCEL_OPERATION: {
- std::lock_guard<std::mutex> l(this->m_cancelledMutex);
- auto fd = conn->getFd();
- if (this->m_isCancelled.count(fd) == 1) {
- this->m_isCancelled[fd] = true;
- INFO("Trun on cancelled flag of fd: " << fd);
- } else {
- WARN("Nothing to cancel on getting scannable list! fd: " << fd);
- }
-
- return RawBuffer();
- }
-
- case CommandId::CANONICALIZE_PATHS: {
+ case CommandId::SCAN_DIRS_ASYNC: {
hasPermission(conn);
+ CsContextShPtr cptr;
StrSet paths;
- q.Deserialize(paths);
+ q.Deserialize(cptr, paths);
auto fd = conn->getFd();
{
std::lock_guard<std::mutex> l(this->m_cancelledMutex);
this->m_isCancelled[fd] = false;
- INFO("Turn off cancelled flag before canonicalize paths start on fd: " << fd);
+ INFO("Turn off cancelled flag before start async. fd: " << fd);
}
Closer closer([this, fd]() {
std::lock_guard<std::mutex> l(this->m_cancelledMutex);
this->m_isCancelled.erase(fd);
- INFO("Erase cancelled flag in closer of canonicalize paths on fd: " << fd);
+ INFO("Erase cancelled flag in closer on fd: " << fd);
});
- return this->m_cslogic->canonicalizePaths(paths);
+ return this->m_cslogic->scanDirsAsync(conn, *cptr, paths, [this, fd]() {
+ std::lock_guard<std::mutex> l(this->m_cancelledMutex);
+ if (this->m_isCancelled.count(fd) == 1 && this->m_isCancelled[fd])
+ ThrowExcInfo(ASYNC_EVENT_CANCEL, "operation cancelled on fd: " << fd);
+ });
}
- case CommandId::SET_DIR_TIMESTAMP: {
- hasPermission(conn);
-
- std::string dir;
- int64_t ts64 = 0;
- q.Deserialize(dir, ts64);
+ case CommandId::CANCEL_OPERATION: {
+ std::lock_guard<std::mutex> l(this->m_cancelledMutex);
+ auto fd = conn->getFd();
+ if (this->m_isCancelled.count(fd) == 1) {
+ this->m_isCancelled[fd] = true;
+ INFO("Turn on cancelled flag of fd: " << fd);
+ } else {
+ WARN("Nothing to cancel... fd: " << fd);
+ }
- return this->m_cslogic->setDirTimestamp(dir, static_cast<time_t>(ts64));
+ return RawBuffer();
}
case CommandId::JUDGE_STATUS: {
auto detectedList = db.getDetectedAllByNameOnDir("/opt", 0);
ASSERT_IF(detectedList.empty(), true);
- db.insertDetectedFile(malware1.targetName, malware1, initDataVersion);
+ db.insertDetectedFile(malware1, initDataVersion);
detected = db.getDetectedAllByNameOnPath(malware1.targetName, 0);
CHECK_IS_NOT_NULL(detected);
checkSameMalware(malware1, *detected);
ASSERT_IF(detected->dataVersion, initDataVersion);
ASSERT_IF(detected->isIgnored, false);
- db.insertDetectedFile(malware2.targetName, malware2, initDataVersion);
+ db.insertDetectedFile(malware2, initDataVersion);
db.updateIgnoreFlag(malware2.targetName, true);
detected = db.getDetectedAllByNameOnPath(malware2.targetName, 0);
CHECK_IS_NOT_NULL(detected);
ASSERT_IF(detected->dataVersion, initDataVersion);
ASSERT_IF(detected->isIgnored, true);
- db.insertDetectedFile(malware3.targetName, malware3, initDataVersion);
+ db.insertDetectedFile(malware3, initDataVersion);
db.updateIgnoreFlag(malware3.targetName, true);
detected = db.getDetectedAllByNameOnPath(malware3.targetName, 0);
CHECK_IS_NOT_NULL(detected);
ASSERT_IF(detected->isIgnored, true);
// deleteDeprecatedDetectedMalwares test
- db.insertDetectedFile(malware4.targetName, malware4, changedDataVersion);
+ db.insertDetectedFile(malware4, changedDataVersion);
db.deleteDetectedDeprecated(3);
detected = db.getDetectedAllByNameOnPath(malware4.targetName, 0);
CHECK_IS_NOT_NULL(detected);
set_default_callback(context);
const char *dirs[4] = {
- "/opt/usr/media/",
- "/opt/usr/apps/",
+ TEST_DIR_MEDIA(),
+ TEST_DIR_APPS(),
"/tmp/",
"/sdcard/"
};