pull/105/head
ApexLiu 2017-10-26 09:54:28 +08:00
parent 5155d4ff5d
commit 3a62227af6
10 changed files with 179 additions and 84 deletions

View File

@ -8,8 +8,11 @@
<file url="file://$PROJECT_DIR$/../common/libex/src/ex_ini.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/../common/libex/src/ex_log.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/../common/libex/src/ex_util.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/../common/teleport/teleport_const.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/base_env.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/base_record.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/base_record.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/protocol_interface.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/ts_const.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/ts_membuf.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/common/ts_membuf.h" charset="GBK" />
@ -19,6 +22,8 @@
<file url="file://$PROJECT_DIR$/tp_core/core/ts_http_rpc.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/core/ts_http_rpc.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/core/ts_main.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/core/ts_session.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/core/ts_web_rpc.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_recorder.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/protocol/rdp/rdp_session.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/tp_core/protocol/ssh/ssh_proxy.cpp" charset="GBK" />

View File

@ -1,7 +1,7 @@
#include <memory>
#include <sys/types.h>
#include <sys/stat.h>
//#include <sys/types.h>
//#include <sys/stat.h>
#include "base_record.h"
@ -10,13 +10,15 @@ TppRecBase::TppRecBase()
m_cache.reserve(MAX_SIZE_PER_FILE);
m_start_time = 0;
m_last_time = 0;
//m_protocol =
}
TppRecBase::~TppRecBase()
{
end();
}
void TppRecBase::begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info)
bool TppRecBase::begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info)
{
m_start_time = ex_get_tick_count();
@ -24,21 +26,22 @@ void TppRecBase::begin(const wchar_t* base_path, const wchar_t* base_fname, int
m_base_path = base_path;
wchar_t _str_rec_id[24] = { 0 };
ex_wcsformat(_str_rec_id, 24, L"%06d", record_id);
ex_wcsformat(_str_rec_id, 24, L"%09d", record_id);
ex_path_join(m_base_path, false, _str_rec_id, NULL);
ex_mkdirs(m_base_path);
_on_begin(info);
return _on_begin(info);
}
void TppRecBase::end()
bool TppRecBase::end()
{
_on_end();
#ifdef EX_DEBUG
if (m_cache.size() > 0)
{
EXLOGE("not all record data saved.\n");
return false;
}
#endif
return true;
}

View File

@ -11,22 +11,31 @@
#pragma pack(push,1)
/*
*
*
*
* 4M5
*
*/
// 录像文件头(随着录像数据写入,会改变的部分)
typedef struct TS_RECORD_HEADER_INFO
{
ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record
ex_u16 ver; // 录像文件版本目前为3
ex_u32 packages; // 总包数
ex_u32 time_ms; // 总耗时(毫秒)
ex_u32 file_size; // 数据总大小(不包括文件头)
ex_u32 file_size; // 数据文件大小
}TS_RECORD_HEADER_INFO;
#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO)
// 录像文件头(固定不变部分)
typedef struct TS_RECORD_HEADER_BASIC
{
ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record
ex_u16 ver; // 录像文件版本目前为3
ex_u16 protocol_type; // 协议1=RDP, 2=SSH, 3=Telnet
ex_u16 protocol_sub_type; // 子协议100=RDP, 200=SSH, 201=SFTP, 300=Telnet
ex_u16 protocol_sub_type; // 子协议100=RDP-DESKTOP, 200=SSH-SHELL, 201=SSH-SFTP, 300=Telnet
ex_u64 timestamp; // 本次录像的起始时间UTC时间戳
ex_u16 width; // 初始屏幕尺寸:宽
ex_u16 height; // 初始屏幕尺寸:高
@ -42,7 +51,7 @@ typedef struct TS_RECORD_HEADER_BASIC
// RDP专有
ex_u8 rdp_security; // 0 = RDP, 1 = TLS
ex_u8 reserve[512 - 4 - 2 - 2 - 2 - 8 - 2 - 2 - 64 - 64 - 40 - 2 - 40 - 40 - 1 - 12]; // 保留其中12B是为header-info留出的空间
ex_u8 _reserve[512 - 4 - 2 - 2 - 2 - 8 - 2 - 2 - 64 - 64 - 40 - 2 - 40 - 40 - 1 - ts_record_header_info_size];
}TS_RECORD_HEADER_BASIC;
#define ts_record_header_basic_size sizeof(TS_RECORD_HEADER_BASIC)
@ -62,7 +71,7 @@ typedef struct TS_RECORD_PKG
ex_u8 type; // 包的数据类型
ex_u32 size; // 这个包的总大小(不含包头)
ex_u32 time_ms; // 这个包距起始时间的时间差毫秒意味着一个连接不能持续超过49天
ex_u8 reserve[3]; // 保留
ex_u8 _reserve[3]; // 保留
}TS_RECORD_PKG;
#pragma pack(pop)
@ -73,17 +82,17 @@ public:
TppRecBase();
virtual ~TppRecBase();
void begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info);
void end(void);
bool begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info);
bool end();
virtual void record(ex_u8 type, const ex_u8* data, size_t size) = 0;
//virtual void record(ex_u8 type, const ex_u8* data, size_t size) = 0;
protected:
virtual void _on_begin(const TPP_CONNECT_INFO* info) = 0;
virtual void _on_end(void) = 0;
virtual bool _on_begin(const TPP_CONNECT_INFO* info) = 0;
virtual bool _on_end() = 0;
protected:
int m_protocol;
//int m_protocol;
ex_wstr m_base_path; // 录像文件基础路径,例如 /usr/local/eom/teleport/data/replay/ssh/123数字编号是内部附加的作为本次会话录像文件的目录名称
ex_wstr m_base_fname; // 录像文件的文件名,不含扩展名部分,内部会以此为基础合成文件全名,并将录像文件存放在 m_base_path 指向的目录中

View File

@ -7,6 +7,7 @@ SshProxy::SshProxy() :
ExThreadBase("ssh-proxy-thread"),
m_bind(NULL)
{
m_timer_counter = 0;
}
SshProxy::~SshProxy()
@ -16,8 +17,8 @@ SshProxy::~SshProxy()
ssh_finalize();
ts_sftp_sessions::iterator it = m_sftp_sessions.begin();
for (; it != m_sftp_sessions.end(); ++it)
ts_sftp_sessions::iterator it;
for (it = m_sftp_sessions.begin(); it != m_sftp_sessions.end(); ++it)
{
delete it->second;
}
@ -69,7 +70,20 @@ bool SshProxy::init(void)
}
void SshProxy::timer(void) {
// be called per one second.
// EXLOGV("[ssh] on-timer.\n");
m_timer_counter++;
if(m_timer_counter < 5)
return;
m_timer_counter = 0;
ExThreadSmartLock locker(m_lock);
ts_ssh_sessions::iterator it;
for(it = m_sessions.begin(); it != m_sessions.end(); ++it) {
it->first->flush_record();
}
}
void SshProxy::_thread_loop(void)

View File

@ -52,7 +52,8 @@ private:
private:
ssh_bind m_bind;
bool m_stop_flag;
//bool m_stop_flag;
int m_timer_counter;
ExThreadLock m_lock;

View File

@ -1,5 +1,5 @@
#include "ssh_recorder.h"
#include <teleport_const.h>
//#include <teleport_const.h>
static ex_u8 TPP_RECORD_MAGIC[4] = { 'T', 'P', 'P', 'R' };
@ -8,23 +8,26 @@ TppSshRec::TppSshRec()
m_cmd_cache.reserve(MAX_SIZE_PER_FILE);
memset(&m_head, 0, sizeof(TS_RECORD_HEADER));
memcpy((ex_u8*)(&m_head.basic.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
m_head.basic.ver = 0x02;
memcpy((ex_u8*)(&m_head.info.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
m_head.info.ver = 0x03;
m_file_info = NULL;
m_file_data = NULL;
m_file_cmd = NULL;
}
TppSshRec::~TppSshRec()
{
end();
}
void TppSshRec::_on_begin(const TPP_CONNECT_INFO* info)
bool TppSshRec::_on_begin(const TPP_CONNECT_INFO* info)
{
if (NULL == info)
return;
m_head.basic.timestamp = time(NULL);
m_head.basic.protocol_type = info->protocol_type;
m_head.basic.protocol_sub_type = info->protocol_sub_type;
m_head.basic.conn_port = info->conn_port;
return false;
m_head.basic.timestamp = (ex_u64)time(NULL);
m_head.basic.protocol_type = (ex_u16)info->protocol_type;
m_head.basic.protocol_sub_type = (ex_u16)info->protocol_sub_type;
m_head.basic.conn_port = (ex_u16)info->conn_port;
// memcpy(m_head.account, info.acc_username.c_str(), info.acc_username.length() > 15 ? 15 : info.acc_username.length());
// memcpy(m_head.username, info.user_username.c_str(), info.user_username.length() > 15 ? 15 : info.user_username.length());
// memcpy(m_head.ip, info.host_ip.c_str(), info.host_ip.length() > 17 ? 17 : info.host_ip.length());
@ -33,9 +36,42 @@ void TppSshRec::_on_begin(const TPP_CONNECT_INFO* info)
memcpy(m_head.basic.user_username, info->user_username, strlen(info->user_username) >= 63 ? 63 : strlen(info->user_username));
memcpy(m_head.basic.host_ip, info->host_ip, strlen(info->host_ip) >= 39 ? 39 : strlen(info->host_ip));
memcpy(m_head.basic.conn_ip, info->conn_ip, strlen(info->conn_ip) >= 39 ? 39 : strlen(info->conn_ip));
ex_wstr fname_info = m_base_path;
ex_path_join(fname_info, false, m_base_fname.c_str(), NULL);
fname_info += L".tpr";
ex_wstr fname_data = m_base_path;
ex_path_join(fname_data, false, m_base_fname.c_str(), NULL);
fname_data += L".dat";
ex_wstr fname_cmd = m_base_path;
ex_path_join(fname_cmd, false, m_base_fname.c_str(), NULL);
fname_cmd += L"-cmd.txt";
m_file_info = ex_fopen(fname_info, L"wb");
if (NULL == m_file_info)
{
EXLOGE("[ssh] can not open record info-file for write.\n");
return false;
}
m_file_data = ex_fopen(fname_data, L"wb");
if (NULL == m_file_data)
{
EXLOGE("[ssh] can not open record data-file for write.\n");
return false;
}
m_file_cmd = ex_fopen(fname_cmd, L"wb");
if (NULL == m_file_cmd)
{
EXLOGE("[ssh] can not open record cmd-file for write.\n");
return false;
}
return true;
}
void TppSshRec::_on_end(void)
bool TppSshRec::_on_end()
{
// 如果还有剩下未写入的数据,写入文件中。
if (m_cache.size() > 0)
@ -43,24 +79,37 @@ void TppSshRec::_on_end(void)
if (m_cmd_cache.size() > 0)
_save_to_cmd_file();
// ¸üÐÂÍ·ÐÅÏ¢
//m_head.timestamp = m_start_time;
m_head.info.time_ms = (ex_u32)(m_last_time - m_start_time);
// // ¸üÐÂÍ·ÐÅÏ¢
// //m_head.timestamp = m_start_time;
// m_head.info.time_ms = (ex_u32)(m_last_time - m_start_time);
//
// ex_wstr fname = m_base_path;
// ex_path_join(fname, false, m_base_fname.c_str(), NULL);
// fname += L".tpr";
//
// FILE* f = ex_fopen(fname, L"wb");
// if (NULL == f)
// {
// EXLOGE("[ssh] can not open record file for write.\n");
// return false;
// }
//
// fwrite(&m_head, sizeof(TS_RECORD_HEADER), 1, f);
// fflush(f);
// fclose(f);
ex_wstr fname = m_base_path;
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
fname += L".tpr";
fclose(m_file_info);
fclose(m_file_data);
fclose(m_file_cmd);
FILE* f = ex_fopen(fname, L"wb");
if (NULL == f)
{
EXLOGE("[ssh] can not open record file for write.\n");
return;
}
return true;
}
fwrite(&m_head, sizeof(TS_RECORD_HEADER), 1, f);
fflush(f);
fclose(f);
void TppSshRec::flush_record() {
if (m_cache.size() > 0)
_save_to_data_file();
if (m_cmd_cache.size() > 0)
_save_to_cmd_file();
}
void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size)
@ -68,14 +117,15 @@ void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size)
if (data == NULL || 0 == size)
return;
m_head.info.packages++;
m_head.info.time_ms = (ex_u32)(m_last_time - m_start_time);
if (sizeof(TS_RECORD_PKG) + size + m_cache.size() > m_cache.buffer_size())
_save_to_data_file();
TS_RECORD_PKG pkg;
memset(&pkg, 0, sizeof(TS_RECORD_PKG));
TS_RECORD_PKG pkg = {0};
//memset(&pkg, 0, sizeof(TS_RECORD_PKG));
pkg.type = type;
pkg.size = size;
pkg.size = (ex_u32)size;
if (m_start_time > 0)
{
@ -89,19 +139,19 @@ void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size)
void TppSshRec::record_win_size_startup(int width, int height)
{
m_head.basic.width = width;
m_head.basic.height = height;
m_head.basic.width = (ex_u16)width;
m_head.basic.height = (ex_u16)height;
}
void TppSshRec::record_win_size_change(int width, int height)
{
TS_RECORD_WIN_SIZE pkg;
TS_RECORD_WIN_SIZE pkg = {0};
pkg.width = (ex_u16)width;
pkg.height = (ex_u16)height;
record(TS_RECORD_TYPE_SSH_TERM_SIZE, (ex_u8*)&pkg, sizeof(TS_RECORD_WIN_SIZE));
}
void TppSshRec::record_command(const ex_astr cmd)
void TppSshRec::record_command(const ex_astr& cmd)
{
char szTime[100] = { 0 };
#ifdef EX_OS_WIN32
@ -117,7 +167,7 @@ void TppSshRec::record_command(const ex_astr cmd)
return;
sprintf(szTime, "[%04d-%02d-%02d %02d:%02d:%02d] ", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
#endif
int lenTime = strlen(szTime);
size_t lenTime = strlen(szTime);
if (m_cmd_cache.size() + cmd.length() + lenTime > m_cache.buffer_size())
@ -127,29 +177,29 @@ void TppSshRec::record_command(const ex_astr cmd)
m_cmd_cache.append((ex_u8*)cmd.c_str(), cmd.length());
}
bool TppSshRec::_save_to_data_file(void)
bool TppSshRec::_save_to_data_file()
{
wchar_t _str_file_id[24] = { 0 };
ex_wcsformat(_str_file_id, 24, L".%03d", 0);// m_head.file_count);
ex_wstr fname = m_base_path;
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
fname += _str_file_id;
FILE* f = ex_fopen(fname, L"wb");
if (NULL == f)
{
EXLOGE("[ssh] can not open record data-file for write.\n");
m_cache.empty();
return false;
}
// wchar_t _str_file_id[24] = { 0 };
// ex_wcsformat(_str_file_id, 24, L".%03d", 0);// m_head.file_count);
//
// ex_wstr fname = m_base_path;
// ex_path_join(fname, false, m_base_fname.c_str(), NULL);
// fname += _str_file_id;
//
// FILE* f = ex_fopen(fname, L"wb");
//
// if (NULL == f)
// {
// EXLOGE("[ssh] can not open record data-file for write.\n");
// m_cache.empty();
// return false;
// }
ex_u32 size = m_cache.size();
fwrite(&size, sizeof(ex_u32), 1, f);
fwrite(m_cache.data(), m_cache.size(), 1, f);
fflush(f);
fclose(f);
fwrite(&size, sizeof(ex_u32), 1, m_file_data);
fwrite(m_cache.data(), m_cache.size(), 1, m_file_data);
// fflush(f);
// fclose(f);
//m_head.file_count++;
//m_head.file_size += m_cache.size();
@ -158,7 +208,7 @@ bool TppSshRec::_save_to_data_file(void)
return true;
}
bool TppSshRec::_save_to_cmd_file(void)
bool TppSshRec::_save_to_cmd_file()
{
ex_wstr fname = m_base_path;
ex_path_join(fname, false, m_base_fname.c_str(), NULL);

View File

@ -54,19 +54,25 @@ public:
void record(ex_u8 type, const ex_u8* data, size_t size);
void record_win_size_startup(int width, int height);
void record_win_size_change(int width, int height);
void record_command(const ex_astr cmd);
void record_command(const ex_astr& cmd);
void flush_record();
protected:
void _on_begin(const TPP_CONNECT_INFO* info);
void _on_end(void);
bool _on_begin(const TPP_CONNECT_INFO* info);
bool _on_end();
bool _save_to_data_file(void);
bool _save_to_cmd_file(void);
bool _save_to_data_file();
bool _save_to_cmd_file();
protected:
TS_RECORD_HEADER m_head;
MemBuffer m_cmd_cache;
FILE* m_file_info;
FILE* m_file_data;
FILE* m_file_cmd;
};
#endif // __TPP_SSH_RECORDER_H__

View File

@ -220,6 +220,10 @@ void SshSession::_run(void) {
ssh_event_free(event_loop);
}
void SshSession::flush_record() {
m_rec.flush_record();
}
int SshSession::_on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata) {
// 这里拿到的user就是我们要的session-idpassword可以用ticket来填充作为额外判断用户是否被允许访问的依据。

View File

@ -53,6 +53,8 @@ public:
void client_port(ex_u16 port) { m_client_port = port; }
ex_u16 client_port(void) const { return m_client_port; }
void flush_record();
protected:
// ¼Ì³Ð×Ô TppSessionBase
bool _on_session_begin(const TPP_CONNECT_INFO* info);

View File

@ -35,5 +35,6 @@ TPP_API ex_rv tpp_stop(void)
}
TPP_API void tpp_timer(void) {
// be called per one second.
g_ssh_proxy.timer();
}