2019-04-22 12:25:25 +00:00
|
|
|
#include <hook/shell.hpp>
|
2019-05-01 15:36:20 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
/** put win32 stuff here */
|
|
|
|
#else
|
2019-04-22 14:00:59 +00:00
|
|
|
#include <util/threadpool.h>
|
2019-04-22 12:25:25 +00:00
|
|
|
#include <util/logger.hpp>
|
2019-04-22 12:48:48 +00:00
|
|
|
#include <sys/wait.h>
|
2019-04-27 10:48:01 +00:00
|
|
|
#include <unistd.h>
|
2019-05-06 02:41:06 +00:00
|
|
|
#if !defined(__linux__) || !defined(_GNU_SOURCE)
|
|
|
|
// Not all systems declare this variable
|
|
|
|
extern char **environ;
|
|
|
|
#endif
|
2019-05-01 15:36:20 +00:00
|
|
|
#endif
|
2019-04-27 10:48:01 +00:00
|
|
|
#if defined(Darwin)
|
|
|
|
#include <crt_externs.h>
|
|
|
|
#endif
|
2019-04-22 12:25:25 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace hooks
|
|
|
|
{
|
2019-05-01 15:36:20 +00:00
|
|
|
#if defined(_WIN32)
|
2019-05-02 16:23:31 +00:00
|
|
|
Backend_ptr ExecShellBackend(std::string)
|
2019-05-01 15:36:20 +00:00
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
#else
|
2019-05-05 13:51:48 +00:00
|
|
|
struct ExecShellHookBackend
|
|
|
|
: public IBackend,
|
|
|
|
public std::enable_shared_from_this< ExecShellHookBackend >
|
2019-04-22 12:25:25 +00:00
|
|
|
{
|
2019-04-22 14:00:59 +00:00
|
|
|
llarp_threadpool *m_ThreadPool;
|
2019-05-05 13:51:48 +00:00
|
|
|
|
|
|
|
std::vector< std::string > _args;
|
|
|
|
std::vector< char * > args;
|
2019-04-22 14:00:59 +00:00
|
|
|
|
2019-04-22 12:25:25 +00:00
|
|
|
ExecShellHookBackend(std::string script)
|
2019-04-22 14:00:59 +00:00
|
|
|
: m_ThreadPool(llarp_init_threadpool(1, script.c_str()))
|
2019-04-22 12:25:25 +00:00
|
|
|
{
|
2019-05-05 13:51:48 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
const auto idx = script.find_first_of(' ');
|
|
|
|
std::string sub;
|
|
|
|
if(idx == std::string::npos)
|
|
|
|
sub = script;
|
|
|
|
else
|
|
|
|
sub = script.substr(0, idx);
|
|
|
|
_args.emplace_back(std::move(sub));
|
|
|
|
args.push_back((char *)_args.back().c_str());
|
|
|
|
script = script.substr(idx + 1);
|
|
|
|
} while(script.find_first_of(' ') != std::string::npos);
|
|
|
|
args.push_back(nullptr);
|
|
|
|
LogInfo("make hook ", args.size());
|
2019-04-22 12:25:25 +00:00
|
|
|
}
|
|
|
|
|
2019-04-22 14:00:59 +00:00
|
|
|
~ExecShellHookBackend()
|
|
|
|
{
|
2019-04-22 14:03:22 +00:00
|
|
|
llarp_threadpool_stop(m_ThreadPool);
|
2019-04-22 14:00:59 +00:00
|
|
|
llarp_free_threadpool(&m_ThreadPool);
|
|
|
|
}
|
2019-04-22 12:25:25 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
Start() override
|
|
|
|
{
|
2019-04-22 14:00:59 +00:00
|
|
|
llarp_threadpool_start(m_ThreadPool);
|
|
|
|
return true;
|
2019-04-22 12:25:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Stop() override
|
|
|
|
{
|
2019-04-22 14:00:59 +00:00
|
|
|
llarp_threadpool_stop(m_ThreadPool);
|
2019-04-22 12:25:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-05-05 13:51:48 +00:00
|
|
|
char *
|
|
|
|
Exe() const
|
|
|
|
{
|
|
|
|
return args[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
char *const *
|
|
|
|
Args() const
|
|
|
|
{
|
|
|
|
return args.data();
|
|
|
|
}
|
|
|
|
|
2019-04-22 12:25:25 +00:00
|
|
|
void
|
|
|
|
NotifyAsync(
|
2019-05-05 13:51:48 +00:00
|
|
|
std::unordered_map< std::string, std::string > params) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ExecShellHookJob
|
|
|
|
{
|
|
|
|
std::vector< std::string > m_env;
|
|
|
|
std::vector< char * > _m_env;
|
|
|
|
std::shared_ptr< ExecShellHookBackend > m_Parent;
|
|
|
|
|
|
|
|
ExecShellHookJob(std::shared_ptr< ExecShellHookBackend > b,
|
|
|
|
const std::unordered_map< std::string, std::string > env)
|
|
|
|
: m_Parent(b)
|
2019-04-22 12:25:25 +00:00
|
|
|
{
|
2019-05-05 13:51:48 +00:00
|
|
|
#if defined(Darwin)
|
|
|
|
char **ptr = *_NSGetEnviron();
|
|
|
|
#else
|
|
|
|
char **ptr = environ;
|
|
|
|
#endif
|
|
|
|
do
|
|
|
|
{
|
|
|
|
m_env.emplace_back(*ptr);
|
|
|
|
++ptr;
|
|
|
|
} while(ptr && *ptr);
|
|
|
|
for(const auto &item : env)
|
|
|
|
m_env.emplace_back(item.first + "=" + item.second);
|
|
|
|
for(const auto &item : m_env)
|
|
|
|
_m_env.push_back((char *)item.c_str());
|
|
|
|
_m_env.push_back(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *const *
|
|
|
|
Env()
|
|
|
|
{
|
|
|
|
return _m_env.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
Exec(std::shared_ptr< ExecShellHookJob > self)
|
|
|
|
{
|
|
|
|
std::thread t([&]() {
|
|
|
|
int result = 0;
|
|
|
|
const pid_t child = ::fork();
|
|
|
|
if(child == -1)
|
|
|
|
return;
|
|
|
|
if(child)
|
|
|
|
::waitpid(child, &result, 0);
|
|
|
|
else
|
|
|
|
::execve(self->m_Parent->Exe(), self->m_Parent->Args(),
|
|
|
|
self->Env());
|
|
|
|
});
|
|
|
|
t.join();
|
2019-04-22 12:25:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-05 13:51:48 +00:00
|
|
|
void
|
|
|
|
ExecShellHookBackend::NotifyAsync(
|
|
|
|
std::unordered_map< std::string, std::string > params)
|
|
|
|
{
|
|
|
|
auto job = std::make_shared< ExecShellHookJob >(shared_from_this(),
|
|
|
|
std::move(params));
|
|
|
|
m_ThreadPool->QueueFunc([=]() { ExecShellHookJob::Exec(job); });
|
|
|
|
}
|
|
|
|
|
2019-04-22 12:25:25 +00:00
|
|
|
Backend_ptr
|
|
|
|
ExecShellBackend(std::string execFilePath)
|
|
|
|
{
|
2019-05-05 13:51:48 +00:00
|
|
|
Backend_ptr ptr = std::make_shared< ExecShellHookBackend >(execFilePath);
|
2019-04-22 12:25:25 +00:00
|
|
|
if(!ptr->Start())
|
|
|
|
return nullptr;
|
|
|
|
return ptr;
|
|
|
|
}
|
2019-05-01 15:36:20 +00:00
|
|
|
#endif
|
2019-04-22 12:25:25 +00:00
|
|
|
} // namespace hooks
|
2019-04-27 10:48:01 +00:00
|
|
|
} // namespace llarp
|