mirror of https://github.com/tp4a/teleport
增强:强制中断在线会话功能实现了,SSH协议已测试,RDP和TELNET协议尚未实现。
parent
685f31f566
commit
3eb59eb071
|
@ -14,6 +14,9 @@
|
||||||
# define TPP_API
|
# define TPP_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TPP_CMD_INIT 0x00000000
|
||||||
|
#define TPP_CMD_KILL_SESSIONS 0x00000006
|
||||||
|
|
||||||
typedef struct TPP_CONNECT_INFO
|
typedef struct TPP_CONNECT_INFO
|
||||||
{
|
{
|
||||||
char* sid;
|
char* sid;
|
||||||
|
@ -79,6 +82,8 @@ extern "C"
|
||||||
TPP_API void tpp_timer(void);
|
TPP_API void tpp_timer(void);
|
||||||
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args);
|
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args);
|
||||||
|
|
||||||
|
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -89,4 +94,6 @@ typedef ex_rv(*TPP_STOP_FUNC)(void);
|
||||||
typedef void(*TPP_TIMER_FUNC)(void);
|
typedef void(*TPP_TIMER_FUNC)(void);
|
||||||
typedef void(*TPP_SET_CFG_FUNC)(TPP_SET_CFG_ARGS* cfg_args);
|
typedef void(*TPP_SET_CFG_FUNC)(TPP_SET_CFG_ARGS* cfg_args);
|
||||||
|
|
||||||
|
typedef ex_rv(*TPP_COMMAND_FUNC)(ex_u32 cmd, const char* param); // param is a JSON formatted string.
|
||||||
|
|
||||||
#endif // __TP_PROTOCOL_INTERFACE_H__
|
#endif // __TP_PROTOCOL_INTERFACE_H__
|
||||||
|
|
|
@ -47,15 +47,17 @@ bool TppManager::load_tpp(const ex_wstr& libname)
|
||||||
lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
|
lib->stop = (TPP_STOP_FUNC)GetProcAddress(lib->dylib, "tpp_stop");
|
||||||
lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
|
lib->timer = (TPP_TIMER_FUNC)GetProcAddress(lib->dylib, "tpp_timer");
|
||||||
lib->set_cfg = (TPP_SET_CFG_FUNC)GetProcAddress(lib->dylib, "tpp_set_cfg");
|
lib->set_cfg = (TPP_SET_CFG_FUNC)GetProcAddress(lib->dylib, "tpp_set_cfg");
|
||||||
|
lib->command = (TPP_COMMAND_FUNC)GetProcAddress(lib->dylib, "tpp_command");
|
||||||
#else
|
#else
|
||||||
lib->init = (TPP_INIT_FUNC)dlsym(lib->dylib, "tpp_init");
|
lib->init = (TPP_INIT_FUNC)dlsym(lib->dylib, "tpp_init");
|
||||||
lib->start = (TPP_START_FUNC)dlsym(lib->dylib, "tpp_start");
|
lib->start = (TPP_START_FUNC)dlsym(lib->dylib, "tpp_start");
|
||||||
lib->stop = (TPP_STOP_FUNC)dlsym(lib->dylib, "tpp_stop");
|
lib->stop = (TPP_STOP_FUNC)dlsym(lib->dylib, "tpp_stop");
|
||||||
lib->timer = (TPP_TIMER_FUNC)dlsym(lib->dylib, "tpp_timer");
|
lib->timer = (TPP_TIMER_FUNC)dlsym(lib->dylib, "tpp_timer");
|
||||||
lib->set_cfg = (TPP_SET_CFG_FUNC)dlsym(lib->dylib, "tpp_set_cfg");
|
lib->set_cfg = (TPP_SET_CFG_FUNC)dlsym(lib->dylib, "tpp_set_cfg");
|
||||||
|
lib->command = (TPP_COMMAND_FUNC)dlsym(lib->dylib, "tpp_command");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (lib->init == NULL || lib->start == NULL || lib->stop == NULL || lib->timer == NULL || lib->set_cfg == NULL)
|
if (lib->init == NULL || lib->start == NULL || lib->stop == NULL || lib->timer == NULL || lib->set_cfg == NULL || lib->command == NULL)
|
||||||
{
|
{
|
||||||
EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", libfile.c_str());
|
EXLOGE(L"[core] load dylib `%ls` failed, can not locate all functions.\n", libfile.c_str());
|
||||||
delete lib;
|
delete lib;
|
||||||
|
@ -118,3 +120,12 @@ void TppManager::set_config(int noop_timeout) {
|
||||||
(*it)->set_cfg(&args);
|
(*it)->set_cfg(&args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TppManager::kill_sessions(const ex_astr& sessions) {
|
||||||
|
tpp_libs::iterator it = m_libs.begin();
|
||||||
|
for (; it != m_libs.end(); ++it)
|
||||||
|
{
|
||||||
|
(*it)->command(TPP_CMD_KILL_SESSIONS, sessions.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ typedef struct TPP_LIB
|
||||||
TPP_STOP_FUNC stop;
|
TPP_STOP_FUNC stop;
|
||||||
TPP_TIMER_FUNC timer;
|
TPP_TIMER_FUNC timer;
|
||||||
TPP_SET_CFG_FUNC set_cfg;
|
TPP_SET_CFG_FUNC set_cfg;
|
||||||
|
|
||||||
|
TPP_COMMAND_FUNC command;
|
||||||
}TPP_LIB;
|
}TPP_LIB;
|
||||||
|
|
||||||
typedef std::list<TPP_LIB*> tpp_libs;
|
typedef std::list<TPP_LIB*> tpp_libs;
|
||||||
|
@ -51,6 +53,7 @@ public:
|
||||||
int count(void) { return m_libs.size(); }
|
int count(void) { return m_libs.size(); }
|
||||||
|
|
||||||
void set_config(int noop_timeout);
|
void set_config(int noop_timeout);
|
||||||
|
void kill_sessions(const ex_astr& sessions);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tpp_libs m_libs;
|
tpp_libs m_libs;
|
||||||
|
|
|
@ -255,6 +255,9 @@ void TsHttpRpc::_process_request(const ex_astr& func_cmd, const Json::Value& jso
|
||||||
if (func_cmd == "request_session") {
|
if (func_cmd == "request_session") {
|
||||||
_rpc_func_request_session(json_param, buf);
|
_rpc_func_request_session(json_param, buf);
|
||||||
}
|
}
|
||||||
|
else if (func_cmd == "kill_sessions") {
|
||||||
|
_rpc_func_kill_sessions(json_param, buf);
|
||||||
|
}
|
||||||
else if (func_cmd == "get_config") {
|
else if (func_cmd == "get_config") {
|
||||||
_rpc_func_get_config(json_param, buf);
|
_rpc_func_get_config(json_param, buf);
|
||||||
}
|
}
|
||||||
|
@ -378,6 +381,45 @@ void TsHttpRpc::_rpc_func_request_session(const Json::Value& json_param, ex_astr
|
||||||
_create_json_ret(buf, TPE_OK, jr_data);
|
_create_json_ret(buf, TPE_OK, jr_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TsHttpRpc::_rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf) {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"sessions": ["0123456", "ABCDEF", ...]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (json_param.isArray())
|
||||||
|
{
|
||||||
|
_create_json_ret(buf, TPE_PARAM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_param["sessions"].isNull() || !json_param["sessions"].isArray())
|
||||||
|
{
|
||||||
|
_create_json_ret(buf, TPE_PARAM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value s = json_param["sessions"];
|
||||||
|
int cnt = s.size();
|
||||||
|
for (int i = 0; i < cnt; ++i)
|
||||||
|
{
|
||||||
|
if (!s[i].isString()) {
|
||||||
|
_create_json_ret(buf, TPE_PARAM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXLOGV("[core] kill %d sessions.\n", cnt);
|
||||||
|
|
||||||
|
ex_astr ss = s.toStyledString();
|
||||||
|
|
||||||
|
g_tpp_mgr.kill_sessions(ss);
|
||||||
|
|
||||||
|
_create_json_ret(buf, TPE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf)
|
void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf)
|
||||||
{
|
{
|
||||||
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#enc
|
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#enc
|
||||||
|
@ -428,7 +470,7 @@ void TsHttpRpc::_rpc_func_set_config(const Json::Value& json_param, ex_astr& buf
|
||||||
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#set_config
|
// https://github.com/eomsoft/teleport/wiki/TELEPORT-CORE-JSON-RPC#set_config
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
"noop-timeout": 900 # 900s = 15m
|
"noop-timeout": 15 # 按分钟计
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -453,7 +495,7 @@ void TsHttpRpc::_rpc_func_set_config(const Json::Value& json_param, ex_astr& buf
|
||||||
|
|
||||||
//static TppManager g_tpp_mgr;
|
//static TppManager g_tpp_mgr;
|
||||||
EXLOGV("[core] no-op timeout set to %d minutes.\n", noop_timeout);
|
EXLOGV("[core] no-op timeout set to %d minutes.\n", noop_timeout);
|
||||||
g_tpp_mgr.set_config(noop_timeout * 60);
|
g_tpp_mgr.set_config(noop_timeout * 60); // 内部按秒计,因此要 *60
|
||||||
|
|
||||||
|
|
||||||
// Json::Value jr_data;
|
// Json::Value jr_data;
|
||||||
|
|
|
@ -37,6 +37,8 @@ private:
|
||||||
void _rpc_func_set_config(const Json::Value& json_param, ex_astr& buf);
|
void _rpc_func_set_config(const Json::Value& json_param, ex_astr& buf);
|
||||||
// 请求一个会话ID
|
// 请求一个会话ID
|
||||||
void _rpc_func_request_session(const Json::Value& json_param, ex_astr& buf);
|
void _rpc_func_request_session(const Json::Value& json_param, ex_astr& buf);
|
||||||
|
// 强行终止会话
|
||||||
|
void _rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf);
|
||||||
// 加密一个字符串(返回的是密文的BASE64编码)
|
// 加密一个字符串(返回的是密文的BASE64编码)
|
||||||
void _rpc_func_enc(const Json::Value& json_param, ex_astr& buf);
|
void _rpc_func_enc(const Json::Value& json_param, ex_astr& buf);
|
||||||
// 要求整个核心服务退出
|
// 要求整个核心服务退出
|
||||||
|
|
|
@ -87,6 +87,20 @@ void SshProxy::set_cfg(TPP_SET_CFG_ARGS* args) {
|
||||||
m_noop_timeout_sec = args->noop_timeout;
|
m_noop_timeout_sec = args->noop_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SshProxy::kill_sessions(const ex_astrs& sessions) {
|
||||||
|
ExThreadSmartLock locker(m_lock);
|
||||||
|
ts_ssh_sessions::iterator it;
|
||||||
|
for (it = m_sessions.begin(); it != m_sessions.end(); ++it) {
|
||||||
|
for (size_t i = 0; i < sessions.size(); ++i) {
|
||||||
|
if (it->first->sid() == sessions[i]) {
|
||||||
|
EXLOGW("[ssh] try to kill %s\n", sessions[i].c_str());
|
||||||
|
it->first->check_noop_timeout(0, 0); // Á¢¼´½áÊø
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SshProxy::_thread_loop()
|
void SshProxy::_thread_loop()
|
||||||
{
|
{
|
||||||
EXLOGI("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
EXLOGI("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
bool init();
|
bool init();
|
||||||
void timer();
|
void timer();
|
||||||
void set_cfg(TPP_SET_CFG_ARGS* args);
|
void set_cfg(TPP_SET_CFG_ARGS* args);
|
||||||
|
void kill_sessions(const ex_astrs& sessions);
|
||||||
|
|
||||||
void session_finished(SshSession* sess);
|
void session_finished(SshSession* sess);
|
||||||
|
|
||||||
|
|
|
@ -191,11 +191,14 @@ void SshSession::_check_channels() {
|
||||||
|| (cli == NULL && srv != NULL && ssh_channel_is_closed(srv))
|
|| (cli == NULL && srv != NULL && ssh_channel_is_closed(srv))
|
||||||
|| (srv == NULL && cli != NULL && ssh_channel_is_closed(cli))
|
|| (srv == NULL && cli != NULL && ssh_channel_is_closed(cli))
|
||||||
) {
|
) {
|
||||||
if (cli)
|
if (cli) {
|
||||||
ssh_channel_free(cli);
|
ssh_channel_free(cli);
|
||||||
if (srv)
|
cli = NULL;
|
||||||
|
}
|
||||||
|
if (srv) {
|
||||||
ssh_channel_free(srv);
|
ssh_channel_free(srv);
|
||||||
|
srv = NULL;
|
||||||
|
}
|
||||||
_record_end((*it));
|
_record_end((*it));
|
||||||
|
|
||||||
delete(*it);
|
delete(*it);
|
||||||
|
@ -407,8 +410,11 @@ void SshSession::check_noop_timeout(ex_u32 t_now, ex_u32 timeout) {
|
||||||
for (; it != m_channels.end(); ++it) {
|
for (; it != m_channels.end(); ++it) {
|
||||||
if ((*it)->need_close)
|
if ((*it)->need_close)
|
||||||
continue;
|
continue;
|
||||||
if (t_now - (*it)->last_access_timestamp > timeout) {
|
if (t_now == 0)
|
||||||
EXLOGW("[ssh] need close channel by timeout.\n");
|
EXLOGW("[ssh] try close channel by kill.\n");
|
||||||
|
else if (t_now - (*it)->last_access_timestamp > timeout)
|
||||||
|
EXLOGW("[ssh] try close channel by timeout.\n");
|
||||||
|
if (t_now == 0 || t_now - (*it)->last_access_timestamp > timeout) {
|
||||||
(*it)->need_close = true;
|
(*it)->need_close = true;
|
||||||
m_have_error = true;
|
m_have_error = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
//
|
//
|
||||||
void check_noop_timeout(ex_u32 t_now, ex_u32 timeout);
|
void check_noop_timeout(ex_u32 t_now, ex_u32 timeout);
|
||||||
|
|
||||||
|
const ex_astr& sid() { return m_sid; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _thread_loop(void);
|
void _thread_loop(void);
|
||||||
void _set_stop_flag(void);
|
void _set_stop_flag(void);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "tpp_env.h"
|
#include "tpp_env.h"
|
||||||
|
|
||||||
#include <teleport_const.h>
|
#include <teleport_const.h>
|
||||||
|
#include <json/json.h>
|
||||||
|
|
||||||
|
|
||||||
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args)
|
TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args)
|
||||||
{
|
{
|
||||||
|
@ -42,3 +44,45 @@ TPP_API void tpp_timer(void) {
|
||||||
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args) {
|
TPP_API void tpp_set_cfg(TPP_SET_CFG_ARGS* cfg_args) {
|
||||||
g_ssh_proxy.set_cfg(cfg_args);
|
g_ssh_proxy.set_cfg(cfg_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ex_rv _kill_sessions(const char* param) {
|
||||||
|
Json::Value jp;
|
||||||
|
Json::Reader jreader;
|
||||||
|
|
||||||
|
if (!jreader.parse(param, jp))
|
||||||
|
return TPE_JSON_FORMAT;
|
||||||
|
|
||||||
|
if (!jp.isArray())
|
||||||
|
return TPE_PARAM;
|
||||||
|
|
||||||
|
ex_astrs ss;
|
||||||
|
int cnt = jp.size();
|
||||||
|
for (int i = 0; i < cnt; ++i)
|
||||||
|
{
|
||||||
|
if (!jp[i].isString()) {
|
||||||
|
return TPE_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss.push_back(jp[i].asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ssh_proxy.kill_sessions(ss);
|
||||||
|
|
||||||
|
return TPE_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
TPP_API ex_rv tpp_command(ex_u32 cmd, const char* param) {
|
||||||
|
switch (cmd) {
|
||||||
|
case TPP_CMD_KILL_SESSIONS:
|
||||||
|
if (param == NULL || strlen(param) == 0)
|
||||||
|
return TPE_PARAM;
|
||||||
|
return _kill_sessions(param);
|
||||||
|
default:
|
||||||
|
return TPE_UNKNOWN_CMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TPE_NOT_IMPLEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../../../common\teleport;../../../../common\libex\include;../../../../external/jsoncpp/include;../../../../external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../../../common\teleport;../../../../common\libex\include;../../../../external/jsoncpp/include;../../../../external\libssh-win-static\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
@ -109,6 +109,7 @@
|
||||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
|
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_types.h" />
|
||||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
|
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_util.h" />
|
||||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
|
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_winsrv.h" />
|
||||||
|
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h" />
|
||||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
|
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\callbacks.h" />
|
||||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />
|
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\libssh.h" />
|
||||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h" />
|
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h" />
|
||||||
|
@ -133,6 +134,9 @@
|
||||||
<ClCompile Include="..\..\..\..\common\libex\src\ex_thread.cpp" />
|
<ClCompile Include="..\..\..\..\common\libex\src\ex_thread.cpp" />
|
||||||
<ClCompile Include="..\..\..\..\common\libex\src\ex_util.cpp" />
|
<ClCompile Include="..\..\..\..\common\libex\src\ex_util.cpp" />
|
||||||
<ClCompile Include="..\..\..\..\common\libex\src\ex_winsrv.cpp" />
|
<ClCompile Include="..\..\..\..\common\libex\src\ex_winsrv.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_reader.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_value.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_writer.cpp" />
|
||||||
<ClCompile Include="..\..\common\base_env.cpp" />
|
<ClCompile Include="..\..\common\base_env.cpp" />
|
||||||
<ClCompile Include="..\..\common\base_record.cpp" />
|
<ClCompile Include="..\..\common\base_record.cpp" />
|
||||||
<ClCompile Include="..\..\common\ts_membuf.cpp" />
|
<ClCompile Include="..\..\common\ts_membuf.cpp" />
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
<Filter Include="libssh">
|
<Filter Include="libssh">
|
||||||
<UniqueIdentifier>{f1fea9ae-123c-4aa8-a152-e88d1d0a29fd}</UniqueIdentifier>
|
<UniqueIdentifier>{f1fea9ae-123c-4aa8-a152-e88d1d0a29fd}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="jsoncpp">
|
||||||
|
<UniqueIdentifier>{022b0a3d-47c2-40d8-96d9-dceea02e7eef}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h">
|
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h">
|
||||||
|
@ -107,6 +110,9 @@
|
||||||
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h">
|
<ClInclude Include="..\..\..\..\external\libssh-win-static\include\libssh\server.h">
|
||||||
<Filter>libssh</Filter>
|
<Filter>libssh</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\..\external\jsoncpp\include\json\json.h">
|
||||||
|
<Filter>jsoncpp</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="tpssh.cpp">
|
<ClCompile Include="tpssh.cpp">
|
||||||
|
@ -160,5 +166,14 @@
|
||||||
<ClCompile Include="ssh_recorder.cpp">
|
<ClCompile Include="ssh_recorder.cpp">
|
||||||
<Filter>main app</Filter>
|
<Filter>main app</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_reader.cpp">
|
||||||
|
<Filter>jsoncpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_value.cpp">
|
||||||
|
<Filter>jsoncpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\..\external\jsoncpp\src\lib_json\json_writer.cpp">
|
||||||
|
<Filter>jsoncpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -80,7 +80,7 @@ $app.create_controls = function (cb_stack) {
|
||||||
fields: {time_begin: 'time_begin'}
|
fields: {time_begin: 'time_begin'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '耗时',
|
title: '时长',
|
||||||
key: 'time_cost',
|
key: 'time_cost',
|
||||||
render: 'time_cost',
|
render: 'time_cost',
|
||||||
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
||||||
|
|
|
@ -45,6 +45,13 @@ $app.create_controls = function (cb_stack) {
|
||||||
sort_asc: false,
|
sort_asc: false,
|
||||||
fields: {id: 'id'}
|
fields: {id: 'id'}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '会话ID',
|
||||||
|
key: 'sid',
|
||||||
|
sort: true,
|
||||||
|
sort_asc: false,
|
||||||
|
fields: {sid: 'sid'}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '用户',
|
title: '用户',
|
||||||
key: 'user',
|
key: 'user',
|
||||||
|
@ -90,7 +97,7 @@ $app.create_controls = function (cb_stack) {
|
||||||
fields: {time_begin: 'time_begin'}
|
fields: {time_begin: 'time_begin'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '耗时',
|
title: '时长',
|
||||||
key: 'time_cost',
|
key: 'time_cost',
|
||||||
render: 'time_cost',
|
render: 'time_cost',
|
||||||
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
fields: {time_begin: 'time_begin', time_end: 'time_end', state: 'state'}
|
||||||
|
@ -170,30 +177,22 @@ $app.create_controls = function (cb_stack) {
|
||||||
$app.on_table_session_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
$app.on_table_session_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||||
if (col_key === 'chkbox') {
|
if (col_key === 'chkbox') {
|
||||||
cell_obj.find('[data-check-box]').click(function () {
|
cell_obj.find('[data-check-box]').click(function () {
|
||||||
|
// 同步相同会话ID的选中状态
|
||||||
|
var _obj = $(this);
|
||||||
|
var checked = _obj.is(':checked');
|
||||||
|
var _row_data = tbl.get_row(_obj);
|
||||||
|
var _objs = $('#' + $app.table_session.dom_id + ' tbody').find('[data-check-box]');
|
||||||
|
$.each(_objs, function (i, _o) {
|
||||||
|
var _rd = tbl.get_row(_o);
|
||||||
|
if (_row_data.sid === _rd.sid) {
|
||||||
|
$(_o).prop('checked', checked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
$app.check_host_all_selected();
|
$app.check_host_all_selected();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// else if (col_key === 'action') {
|
|
||||||
// // 绑定系统选择框事件
|
|
||||||
// cell_obj.find('[data-action]').click(function () {
|
|
||||||
// var action = $(this).attr('data-action');
|
|
||||||
// if (action === 'edit') {
|
|
||||||
// $app.dlg_edit_host.show_edit(row_id);
|
|
||||||
// } else if (action === 'account') {
|
|
||||||
// $app.dlg_accounts.show(row_id);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } else if (col_key === 'ip') {
|
|
||||||
// cell_obj.find('[data-toggle="popover"]').popover({trigger: 'hover'});
|
|
||||||
// // } else if (col_key === 'account') {
|
|
||||||
// // cell_obj.find('[data-action="add-account"]').click(function () {
|
|
||||||
// // $app.dlg_accounts.show(row_id);
|
|
||||||
// // });
|
|
||||||
// } else if (col_key === 'account_count') {
|
|
||||||
// cell_obj.find('[data-action="edit-account"]').click(function () {
|
|
||||||
// $app.dlg_accounts.show(row_id);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.check_host_all_selected = function (cb_stack) {
|
$app.check_host_all_selected = function (cb_stack) {
|
||||||
|
@ -389,18 +388,48 @@ $app.on_table_session_header_created = function (header) {
|
||||||
//header._table_ctrl.get_filter_ctrl('host_state').on_created();
|
//header._table_ctrl.get_filter_ctrl('host_state').on_created();
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.get_selected_session = function (tbl) {
|
$app.get_selected_sessions = function (tbl) {
|
||||||
var records = [];
|
var records = [];
|
||||||
var _objs = $('#' + $app.table_session.dom_id + ' tbody tr td input[data-check-box]');
|
var _objs = $('#' + $app.table_session.dom_id + ' tbody tr td input[data-check-box]');
|
||||||
$.each(_objs, function (i, _obj) {
|
$.each(_objs, function (i, _obj) {
|
||||||
if ($(_obj).is(':checked')) {
|
if ($(_obj).is(':checked')) {
|
||||||
var _row_data = tbl.get_row(_obj);
|
var _row_data = tbl.get_row(_obj);
|
||||||
records.push(_row_data.id);
|
records.push(_row_data.sid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return records;
|
return records;
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.on_btn_kill_sessions_click = function () {
|
$app.on_btn_kill_sessions_click = function () {
|
||||||
$tp.notify_error('抱歉,此功能尚未实现!');
|
var sessions = $app.get_selected_sessions($app.table_session);
|
||||||
|
console.log(sessions);
|
||||||
|
if (sessions.length === 0) {
|
||||||
|
$tp.notify_error('请选择要强行终止的会话!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _fn_sure = function (cb_stack, cb_args) {
|
||||||
|
$tp.ajax_post_json('/ops/kill', {sessions: sessions},
|
||||||
|
function (ret) {
|
||||||
|
if (ret.code === TPE_OK) {
|
||||||
|
$app.table_session.load_data();
|
||||||
|
$tp.notify_success('强行终止会话操作成功!');
|
||||||
|
} else {
|
||||||
|
$tp.notify_error('强行终止会话失败:' + tp_error_msg(ret.code, ret.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_stack.exec();
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
$tp.notify_error('网络故障,强行终止会话操作失败!');
|
||||||
|
cb_stack.exec();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var cb_stack = CALLBACK_STACK.create();
|
||||||
|
$tp.dlg_confirm(cb_stack, {
|
||||||
|
msg: '您确定要强行终止这些会话吗?',
|
||||||
|
fn_yes: _fn_sure
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,12 +34,12 @@
|
||||||
|
|
||||||
<!-- begin page-nav -->
|
<!-- begin page-nav -->
|
||||||
<div class="table-extend-area">
|
<div class="table-extend-area">
|
||||||
## <div class="table-extend-cell checkbox-select-all"><input id="table-session-select-all" type="checkbox"/></div>
|
<div class="table-extend-cell checkbox-select-all"><input id="table-session-select-all" type="checkbox"/></div>
|
||||||
## <div class="table-extend-cell group-actions">
|
<div class="table-extend-cell group-actions">
|
||||||
## <div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
## <button id="btn-kill-sessions" type="button" class="btn btn-danger"><i class="fa fa-times-circle fa-fw"></i> 强行中断</button>
|
<button id="btn-kill-sessions" type="button" class="btn btn-danger"><i class="fa fa-times-circle fa-fw"></i> 强行中断</button>
|
||||||
## </div>
|
</div>
|
||||||
## </div>
|
</div>
|
||||||
<div class="table-extend-cell table-item-counter">
|
<div class="table-extend-cell table-item-counter">
|
||||||
<ol id="table-session-paging"></ol>
|
<ol id="table-session-paging"></ol>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,4 +59,10 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- end of box -->
|
<!-- end of box -->
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<p>说明:</p>
|
||||||
|
<ul class="help-list">
|
||||||
|
<li>注意:强制中断会话时,相同会话ID的会话(例如使用SecureCRT或者xShell客户端的“克隆会话”功能打开的会话)均会被中断。</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -162,6 +162,8 @@ controllers = [
|
||||||
(r'/ops/get-remotes', ops.DoGetRemotesHandler),
|
(r'/ops/get-remotes', ops.DoGetRemotesHandler),
|
||||||
# - [json] 构建授权映射表
|
# - [json] 构建授权映射表
|
||||||
(r'/ops/build-auz-map', ops.DoBuildAuzMapHandler),
|
(r'/ops/build-auz-map', ops.DoBuildAuzMapHandler),
|
||||||
|
# - [json] 强行终止指定会话
|
||||||
|
(r'/ops/kill', ops.DoKillSessionsHandler),
|
||||||
|
|
||||||
# ====================================================
|
# ====================================================
|
||||||
# 审计相关
|
# 审计相关
|
||||||
|
|
|
@ -736,6 +736,32 @@ class DoGetRemotesHandler(TPBaseJsonHandler):
|
||||||
self.write_json(err, data=ret)
|
self.write_json(err, data=ret)
|
||||||
|
|
||||||
|
|
||||||
|
class DoKillSessionsHandler(TPBaseJsonHandler):
|
||||||
|
@tornado.gen.coroutine
|
||||||
|
def post(self):
|
||||||
|
ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
|
||||||
|
if ret != TPE_OK:
|
||||||
|
return
|
||||||
|
|
||||||
|
args = self.get_argument('args', None)
|
||||||
|
if args is None:
|
||||||
|
return self.write_json(TPE_PARAM)
|
||||||
|
try:
|
||||||
|
args = json.loads(args)
|
||||||
|
except:
|
||||||
|
return self.write_json(TPE_JSON_FORMAT)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sessions = args['sessions']
|
||||||
|
except:
|
||||||
|
return self.write_json(TPE_PARAM)
|
||||||
|
|
||||||
|
req = {'method': 'kill_sessions', 'param': {'sessions': sessions}}
|
||||||
|
_yr = core_service_async_post_http(req)
|
||||||
|
_err, _ = yield _yr
|
||||||
|
self.write_json(_err)
|
||||||
|
|
||||||
|
|
||||||
class DoBuildAuzMapHandler(TPBaseJsonHandler):
|
class DoBuildAuzMapHandler(TPBaseJsonHandler):
|
||||||
def post(self):
|
def post(self):
|
||||||
ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
|
ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
|
||||||
|
|
|
@ -100,8 +100,8 @@ def get_records(handler, sql_filter, sql_order, sql_limit, sql_restrict, sql_exc
|
||||||
s.order_by('r.id', _sort)
|
s.order_by('r.id', _sort)
|
||||||
elif 'time_begin' == sql_order['name']:
|
elif 'time_begin' == sql_order['name']:
|
||||||
s.order_by('r.time_begin', _sort)
|
s.order_by('r.time_begin', _sort)
|
||||||
# elif 'os_type' == sql_order['name']:
|
elif 'sid' == sql_order['name']:
|
||||||
# s.order_by('h.os_type', _sort)
|
s.order_by('r.sid', _sort)
|
||||||
# elif 'cid' == sql_order['name']:
|
# elif 'cid' == sql_order['name']:
|
||||||
# s.order_by('h.cid', _sort)
|
# s.order_by('h.cid', _sort)
|
||||||
# elif 'state' == sql_order['name']:
|
# elif 'state' == sql_order['name']:
|
||||||
|
|
Loading…
Reference in New Issue