mirror of https://github.com/tp4a/teleport
telnet可以录像和播放了(还不能记录命令,不能感知客户端窗口大小变化)
parent
db9838e480
commit
21e07f7b32
|
@ -46,7 +46,7 @@ bind-ip=0.0.0.0
|
|||
bind-port=52089
|
||||
|
||||
[protocol-telnet]
|
||||
enabled=false
|
||||
enabled=true
|
||||
lib=tptelnet
|
||||
bind-ip=0.0.0.0
|
||||
bind-port=52389
|
||||
|
|
|
@ -14,8 +14,6 @@ TelnetConn::TelnetConn(TelnetSession *sess, bool is_server_side) : m_session(ses
|
|||
m_state = TELNET_CONN_STATE_FREE;
|
||||
}
|
||||
|
||||
m_is_recving = false;
|
||||
|
||||
m_timer_running = false;
|
||||
|
||||
uv_tcp_init(sess->get_loop(), &m_handle);
|
||||
|
@ -26,7 +24,6 @@ TelnetConn::~TelnetConn() {
|
|||
}
|
||||
|
||||
bool TelnetConn::start_recv() {
|
||||
m_is_recving = true;
|
||||
int err = uv_read_start((uv_stream_t *)&m_handle, _on_alloc, _on_recv);
|
||||
if (err != 0) {
|
||||
EXLOGE("[telnet] [%s] can not start to read.\n", m_name);
|
||||
|
@ -34,7 +31,6 @@ bool TelnetConn::start_recv() {
|
|||
return false;
|
||||
}
|
||||
|
||||
m_is_recving = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -53,41 +49,12 @@ void TelnetConn::close() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_is_recving) {
|
||||
m_is_recving = false;
|
||||
uv_read_stop((uv_stream_t*)&m_handle);
|
||||
}
|
||||
|
||||
// int uverr = 0;
|
||||
// uv_shutdown_t *sreq = (uv_shutdown_t *)calloc(1, sizeof(uv_shutdown_t));
|
||||
// sreq->data = this;
|
||||
// if ((uverr = uv_shutdown(sreq, stream_handle(), _uv_on_shutdown)) != 0) {
|
||||
// EXLOGW("[telnet] [%s] error when shutdown connection. %s\n", m_name, uv_strerror(uverr));
|
||||
// free(sreq);
|
||||
//
|
||||
// m_state = TELNET_CONN_STATE_FREE;
|
||||
//
|
||||
// m_session->on_conn_close();
|
||||
// }
|
||||
// else {
|
||||
// m_state = RDP_CONN_STATE_CLOSING;
|
||||
// }
|
||||
|
||||
uv_read_stop((uv_stream_t*)&m_handle);
|
||||
uv_close(handle() , _uv_on_closed);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// void TelnetConn::_uv_on_shutdown(uv_shutdown_t *req, int status) {
|
||||
// TelnetConn *_this = (TelnetConn *)req->data;
|
||||
// //EXLOGD("[telnet] [%s] .. _uv_on_shutdown, status=%d\n", _this->m_name, status);
|
||||
// uv_close((uv_handle_t *)req->handle, _uv_on_closed);
|
||||
// free(req);
|
||||
// }
|
||||
|
||||
void TelnetConn::_uv_on_closed(uv_handle_t *handle) {
|
||||
TelnetConn *_this = (TelnetConn *)handle->data;
|
||||
//EXLOGD("[telnet] [%s] .. _uv_on_closed\n", _this->m_name);
|
||||
_this->m_state = TELNET_CONN_STATE_FREE;
|
||||
_this->m_session->on_conn_close();
|
||||
}
|
||||
|
@ -101,11 +68,8 @@ void TelnetConn::_on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t
|
|||
void TelnetConn::_on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) {
|
||||
TelnetConn *_this = (TelnetConn *) handle->data;
|
||||
|
||||
//ExThreadSmartLock locker(_this->m_locker_recv);
|
||||
|
||||
if (nread == 0) {
|
||||
free(buf->base);
|
||||
//_this->m_session->do_next(_this);
|
||||
return;
|
||||
}
|
||||
else if (nread < 0) {
|
||||
|
@ -128,8 +92,6 @@ void TelnetConn::_on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *bu
|
|||
// #endif
|
||||
}
|
||||
|
||||
EXLOG_BIN((ex_u8*)buf->base, nread, "--READ-- %s", _this->m_name);
|
||||
|
||||
_this->m_buf_data.append((ex_u8 *) buf->base, nread);
|
||||
free(buf->base);
|
||||
|
||||
|
@ -140,17 +102,6 @@ bool TelnetConn::send(MemBuffer &mbuf) {
|
|||
return _raw_send(mbuf.data(), mbuf.size());
|
||||
}
|
||||
|
||||
// bool TelnetConn::send(TelnetPkgBase &pkg) {
|
||||
// MemBuffer mbuf;
|
||||
// MemStream s(mbuf);
|
||||
// if (TPE_OK != pkg.build(s)) {
|
||||
// EXLOGE("[telnet] when send, can not build package to binary.\n");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return _raw_send(mbuf.data(), mbuf.size());
|
||||
// }
|
||||
|
||||
bool TelnetConn::send(const ex_u8 *data, size_t size) {
|
||||
return _raw_send(data, size);
|
||||
}
|
||||
|
@ -158,13 +109,9 @@ bool TelnetConn::send(const ex_u8 *data, size_t size) {
|
|||
bool TelnetConn::_raw_send(const ex_u8 *data, size_t size) {
|
||||
// #ifdef LOG_DATA
|
||||
// if (!m_session->is_relay())
|
||||
EXLOG_BIN(data, size, "[telnet] [%s] SEND %dB.", m_name, size);
|
||||
// EXLOG_BIN(data, size, "[telnet] [%s] SEND %dB.", m_name, size);
|
||||
// #endif
|
||||
|
||||
return raw_send(data, size);
|
||||
}
|
||||
|
||||
bool TelnetConn::raw_send(const ex_u8 *data, size_t size) {
|
||||
uv_write_t *w = (uv_write_t *) calloc(1, sizeof(uv_write_t));
|
||||
|
||||
ex_u8 *_data = (ex_u8 *) calloc(1, size);
|
||||
|
@ -252,7 +199,6 @@ void TelnetConn::connect(const char *server_ip, ex_u16 server_port) {
|
|||
void TelnetConn::_uv_on_connect_timeout(uv_timer_t *timer)
|
||||
{
|
||||
TelnetConn *_this = (TelnetConn *)timer->data;
|
||||
//EXLOGD("[telnet] [%s] .. _uv_on_connect_timeout.\n", _this->m_name);
|
||||
|
||||
if (_this->m_timer_running) {
|
||||
_this->m_timer_running = false;
|
||||
|
@ -268,7 +214,6 @@ void TelnetConn::_uv_on_connect_timeout(uv_timer_t *timer)
|
|||
|
||||
void TelnetConn::_uv_on_reconnect(uv_handle_t *handle) {
|
||||
TelnetConn *_this = (TelnetConn *)handle->data;
|
||||
//EXLOGD("[telnet] [%s] .. _uv_on_reconnect.\n", _this->m_name);
|
||||
_this->m_state = TELNET_CONN_STATE_FREE;
|
||||
|
||||
uv_tcp_init(_this->m_session->get_loop(), &_this->m_handle);
|
||||
|
@ -280,7 +225,6 @@ void TelnetConn::_uv_on_reconnect(uv_handle_t *handle) {
|
|||
void TelnetConn::_uv_on_connected(uv_connect_t *req, int status) {
|
||||
TelnetConn *_this = (TelnetConn *)req->data;
|
||||
free(req);
|
||||
//EXLOGD("[telnet] [%s] .. _uv_on_connected: status=%d.\n", _this->m_name, status);
|
||||
|
||||
if (_this->m_timer_running) {
|
||||
_this->m_timer_running = false;
|
||||
|
@ -308,5 +252,4 @@ void TelnetConn::_uv_on_connected(uv_connect_t *req, int status) {
|
|||
|
||||
//static
|
||||
void TelnetConn::_uv_on_timer_connect_timeout_closed(uv_handle_t *handle) {
|
||||
|
||||
}
|
||||
|
|
|
@ -3,19 +3,8 @@
|
|||
|
||||
#include <uv.h>
|
||||
|
||||
// typedef time_t mbedtls_time_t;
|
||||
|
||||
// #include <mbedtls/arc4.h>
|
||||
// #include <mbedtls/ssl.h>
|
||||
// #include <mbedtls/entropy.h>
|
||||
// #include <mbedtls/ctr_drbg.h>
|
||||
|
||||
// #include "telnet_package.h"
|
||||
#include "../../common/ts_membuf.h"
|
||||
#include "../../common/ts_memstream.h"
|
||||
// #include "telnet_bulk.h"
|
||||
|
||||
|
||||
|
||||
//#define LOG_DATA
|
||||
|
||||
|
@ -47,45 +36,14 @@ public:
|
|||
MemBuffer &data() { return m_buf_data; }
|
||||
|
||||
bool send(MemBuffer &mbuf);
|
||||
// bool send(TelnetPkgBase &pkg);
|
||||
bool send(const ex_u8 *data, size_t size);
|
||||
bool raw_send(const ex_u8 *data, size_t size);
|
||||
|
||||
// connect to real server, for proxy-client-side only.
|
||||
void connect(const char *server_ip, ex_u16 server_port = 3389);
|
||||
// try to close this connection. return current RDP_CONN_STATE_XXXX.
|
||||
// try to close this connection. return current TELNET_CONN_STATE_XXXX.
|
||||
void close();
|
||||
bool start_recv();
|
||||
|
||||
|
||||
// 密钥相关
|
||||
// void gen_session_keys(ex_u8 *client_random, ex_u8 *server_random);
|
||||
// void decrypt(ex_u8 *buf_data, size_t buf_size, bool update_counter);
|
||||
// void encrypt(ex_u8 *buf_data, size_t buf_size, bool update_counter);
|
||||
// ex_u32 get_dec_counter() { return m_decrypt_total; }
|
||||
// ex_u32 get_enc_counter() { return m_encrypt_total; }
|
||||
// void calc_mac(ex_u8 *buf_data, size_t buf_size, ex_u8 *signature, bool with_counter = false, ex_u32 counter = 0);
|
||||
|
||||
// RDP-SSL 相关
|
||||
// bool ssl_prepare();
|
||||
|
||||
// mbedtls_ssl_context *ssl_context() { return &m_ssl_ctx; }
|
||||
|
||||
// bool ssl_is_in_handshake() { return m_ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER; }
|
||||
// int ssl_do_handshake();
|
||||
// int ssl_do_read();
|
||||
|
||||
// bool ssl_send(MemBuffer &mbuf);
|
||||
// bool ssl_send(TelnetPkgBase &pkg);
|
||||
// bool ssl_send(const ex_u8 *data, size_t size);
|
||||
|
||||
// MemBuffer &ssl_data() { return m_ssl_mbuf; }
|
||||
|
||||
// static int on_ssl_read(void *ctx, ex_u8 *buf, size_t len);
|
||||
// static int on_ssl_write(void *ctx, const ex_u8 *buf, size_t len);
|
||||
|
||||
//RDP_BULK* get_bulk() { return m_bulk; }
|
||||
|
||||
private:
|
||||
static void _on_alloc(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||
static void _on_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf);
|
||||
|
@ -93,18 +51,10 @@ private:
|
|||
static void _uv_on_connect_timeout(uv_timer_t *timer);
|
||||
static void _uv_on_connected(uv_connect_t *req, int status);
|
||||
static void _uv_on_reconnect(uv_handle_t *handle);
|
||||
static void _uv_on_shutdown(uv_shutdown_t *req, int status);
|
||||
static void _uv_on_closed(uv_handle_t *handle);
|
||||
static void _uv_on_timer_connect_timeout_closed(uv_handle_t *handle);
|
||||
|
||||
// static void _sec_hash_48(ex_u8 *buf_out, ex_u8 *buf_in, ex_u8 *salt1, ex_u8 *salt2, ex_u8 salt);
|
||||
// static void _sec_hash_16(ex_u8 *buf_out, ex_u8 *buf_in, ex_u8 *salt1, ex_u8 *salt2);
|
||||
// void _sec_update(ex_u8 *init_key, ex_u8 *curr_key);
|
||||
|
||||
bool _raw_send(const ex_u8 *data, size_t size);
|
||||
// bool _ssl_send(const ex_u8 *data, size_t size);
|
||||
// bool _ssl_prepare_as_server();
|
||||
// bool _ssl_prepare_as_client();
|
||||
|
||||
private:
|
||||
TelnetSession *m_session;
|
||||
|
@ -117,46 +67,13 @@ private:
|
|||
uv_timer_t m_timer_connect_timeout;
|
||||
bool m_timer_running; // does m_timer_connect_timeout initialized and started.
|
||||
|
||||
ex_u8 m_state; // RDP_CONN_STATE_XXXX
|
||||
ex_u8 m_state; // TELNET_CONN_STATE_XXXX
|
||||
|
||||
// 作为client需要的数据(远程主机信息)
|
||||
std::string m_server_ip;
|
||||
ex_u16 m_server_port;
|
||||
bool m_is_recving; // does this connection is receiving data?
|
||||
|
||||
ExThreadLock m_locker_send;
|
||||
ExThreadLock m_locker_recv;
|
||||
MemBuffer m_buf_data;
|
||||
|
||||
|
||||
// 会话密钥相关
|
||||
// ex_u8 m_rc4_key_len;
|
||||
// ex_u8 m_mac_key[16];
|
||||
// ex_u8 m_init_enc_key[16];
|
||||
// ex_u8 m_init_dec_key[16];
|
||||
// ex_u8 m_curr_enc_key[16];
|
||||
// ex_u8 m_curr_dec_key[16];
|
||||
// mbedtls_arc4_context m_rc4_encrypt_key;
|
||||
// mbedtls_arc4_context m_rc4_decrypt_key;
|
||||
|
||||
// ex_u32 m_encrypt_count;
|
||||
// ex_u32 m_decrypt_count;
|
||||
// ex_u32 m_encrypt_total;
|
||||
// ex_u32 m_decrypt_total;
|
||||
|
||||
|
||||
// RDP-SSL相关
|
||||
// MemBuffer m_ssl_mbuf; // 存放接收到的数据(经过ssl解密)的缓冲区,等待处理。处理函数处理之后,应该将已经处理过的数据弹掉。
|
||||
// mbedtls_ssl_context m_ssl_ctx;
|
||||
// mbedtls_x509_crt m_ssl_node_cert;
|
||||
// mbedtls_pk_context m_ssl_node_key;
|
||||
// mbedtls_ssl_config m_ssl_conf;
|
||||
// mbedtls_entropy_context m_ssl_entropy;
|
||||
// mbedtls_ctr_drbg_context m_ssl_ctr_drbg;
|
||||
// mbedtls_x509_crt m_ssl_ca_cert;
|
||||
|
||||
// 数据包解析相关
|
||||
//RDP_BULK* m_bulk;
|
||||
};
|
||||
|
||||
#endif // __TELNET_CONN_H__
|
||||
|
|
|
@ -1,168 +1,158 @@
|
|||
#include "telnet_recorder.h"
|
||||
|
||||
static ex_u8 TPP_RECORD_MAGIC[4] = { 'T', 'P', 'P', 'R' };
|
||||
|
||||
TppTelnetRec::TppTelnetRec()
|
||||
{
|
||||
#include "telnet_recorder.h"
|
||||
|
||||
static ex_u8 TPP_RECORD_MAGIC[4] = { 'T', 'P', 'P', 'R' };
|
||||
|
||||
TppTelnetRec::TppTelnetRec()
|
||||
{
|
||||
m_cmd_cache.reserve(MAX_SIZE_PER_FILE);
|
||||
|
||||
memset(&m_head, 0, sizeof(TS_RECORD_HEADER));
|
||||
memcpy((ex_u8*)(&m_head.info.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
|
||||
m_head.info.ver = 0x03;
|
||||
m_header_changed = false;
|
||||
m_save_full_header = false;
|
||||
|
||||
m_file_info = NULL;
|
||||
m_file_data = NULL;
|
||||
m_file_cmd = NULL;
|
||||
}
|
||||
|
||||
TppTelnetRec::~TppTelnetRec()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_on_begin(const TPP_CONNECT_INFO* info)
|
||||
{
|
||||
if (NULL == info)
|
||||
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.basic.acc_username, info->acc_username, strlen(info->acc_username) >= 63 ? 63 : strlen(info->acc_username));
|
||||
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));
|
||||
memcpy(m_head.basic.client_ip, info->client_ip, strlen(info->client_ip) >= 39 ? 39 : strlen(info->client_ip));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_on_end()
|
||||
{
|
||||
// 如果还有剩下未写入的数据,写入文件中。
|
||||
save_record();
|
||||
|
||||
if (m_file_info != NULL)
|
||||
fclose(m_file_info);
|
||||
if (m_file_data != NULL)
|
||||
fclose(m_file_data);
|
||||
if (m_file_cmd != NULL)
|
||||
fclose(m_file_cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TppTelnetRec::save_record() {
|
||||
_save_to_data_file();
|
||||
_save_to_cmd_file();
|
||||
}
|
||||
|
||||
// void TppTelnetRec::record_time_begin(void) // 指定从此时开始计时,之前收到的包会计时为0,这样播放时会快进到此处。
|
||||
// {
|
||||
// m_start_time = ex_get_tick_count();
|
||||
// // m_head.timestamp = time(NULL);
|
||||
// m_head.basic.timestamp = (ex_u64)time(NULL);
|
||||
// m_save_full_header = true;
|
||||
// m_header_changed = true;
|
||||
// }
|
||||
|
||||
void TppTelnetRec::record(ex_u8 type, const ex_u8* data, size_t size)
|
||||
{
|
||||
if (data == NULL || 0 == size)
|
||||
return;
|
||||
|
||||
if (sizeof(TS_RECORD_PKG) + size + m_cache.size() > MAX_SIZE_PER_FILE)
|
||||
_save_to_data_file();
|
||||
|
||||
TS_RECORD_PKG pkg = { 0 };
|
||||
pkg.type = type;
|
||||
pkg.size = (ex_u32)size;
|
||||
|
||||
if (m_start_time > 0)
|
||||
{
|
||||
pkg.time_ms = (ex_u32)(ex_get_tick_count() - m_start_time);
|
||||
m_head.info.time_ms = pkg.time_ms;
|
||||
}
|
||||
|
||||
m_cache.append((ex_u8*)&pkg, sizeof(TS_RECORD_PKG));
|
||||
m_cache.append(data, size);
|
||||
|
||||
m_head.info.packages++;
|
||||
m_header_changed = true;
|
||||
}
|
||||
|
||||
void TppTelnetRec::record_win_size(int width, int height)
|
||||
{
|
||||
m_head.basic.width = (ex_u16)width;
|
||||
m_head.basic.height = (ex_u16)height;
|
||||
m_save_full_header = true;
|
||||
m_header_changed = true;
|
||||
//_save_to_info_file();
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_save_to_info_file() {
|
||||
if (!m_header_changed)
|
||||
return true;
|
||||
|
||||
if (m_file_info == NULL) {
|
||||
ex_wstr fname = m_base_path;
|
||||
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
|
||||
fname += L".tpr";
|
||||
|
||||
m_file_info = ex_fopen(fname, L"wb");
|
||||
if (NULL == m_file_info)
|
||||
{
|
||||
EXLOGE("[ssh] can not open record info-file for write.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// first time to save header, write whole header.
|
||||
m_save_full_header = true;
|
||||
}
|
||||
|
||||
fseek(m_file_info, 0L, SEEK_SET);
|
||||
if (m_save_full_header) {
|
||||
fwrite(&m_head, ts_record_header_size, 1, m_file_info);
|
||||
fflush(m_file_info);
|
||||
m_save_full_header = false;
|
||||
}
|
||||
else {
|
||||
fwrite(&m_head.info, ts_record_header_info_size, 1, m_file_info);
|
||||
fflush(m_file_info);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_save_to_data_file()
|
||||
{
|
||||
if (m_cache.size() == 0)
|
||||
return true;
|
||||
|
||||
if (m_file_data == NULL) {
|
||||
ex_wstr fname = m_base_path;
|
||||
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
|
||||
fname += L".dat";
|
||||
|
||||
m_file_data = ex_fopen(fname, L"wb");
|
||||
if (NULL == m_file_data)
|
||||
{
|
||||
EXLOGE("[ssh] can not open record data-file for write.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_header_changed = true;
|
||||
}
|
||||
|
||||
fwrite(m_cache.data(), m_cache.size(), 1, m_file_data);
|
||||
fflush(m_file_data);
|
||||
m_cache.empty();
|
||||
|
||||
return _save_to_info_file();
|
||||
}
|
||||
|
||||
memset(&m_head, 0, sizeof(TS_RECORD_HEADER));
|
||||
memcpy((ex_u8*)(&m_head.info.magic), TPP_RECORD_MAGIC, sizeof(ex_u32));
|
||||
m_head.info.ver = 0x03;
|
||||
m_header_changed = false;
|
||||
m_save_full_header = false;
|
||||
|
||||
m_file_info = NULL;
|
||||
m_file_data = NULL;
|
||||
m_file_cmd = NULL;
|
||||
}
|
||||
|
||||
TppTelnetRec::~TppTelnetRec()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_on_begin(const TPP_CONNECT_INFO* info)
|
||||
{
|
||||
if (NULL == info)
|
||||
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.basic.acc_username, info->acc_username, strlen(info->acc_username) >= 63 ? 63 : strlen(info->acc_username));
|
||||
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));
|
||||
memcpy(m_head.basic.client_ip, info->client_ip, strlen(info->client_ip) >= 39 ? 39 : strlen(info->client_ip));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_on_end()
|
||||
{
|
||||
// 如果还有剩下未写入的数据,写入文件中。
|
||||
save_record();
|
||||
|
||||
if (m_file_info != NULL)
|
||||
fclose(m_file_info);
|
||||
if (m_file_data != NULL)
|
||||
fclose(m_file_data);
|
||||
if (m_file_cmd != NULL)
|
||||
fclose(m_file_cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TppTelnetRec::save_record() {
|
||||
_save_to_data_file();
|
||||
_save_to_cmd_file();
|
||||
}
|
||||
|
||||
void TppTelnetRec::record(ex_u8 type, const ex_u8* data, size_t size)
|
||||
{
|
||||
if (data == NULL || 0 == size)
|
||||
return;
|
||||
|
||||
if (sizeof(TS_RECORD_PKG) + size + m_cache.size() > MAX_SIZE_PER_FILE)
|
||||
_save_to_data_file();
|
||||
|
||||
TS_RECORD_PKG pkg = { 0 };
|
||||
pkg.type = type;
|
||||
pkg.size = (ex_u32)size;
|
||||
|
||||
if (m_start_time > 0)
|
||||
{
|
||||
pkg.time_ms = (ex_u32)(ex_get_tick_count() - m_start_time);
|
||||
m_head.info.time_ms = pkg.time_ms;
|
||||
}
|
||||
|
||||
m_cache.append((ex_u8*)&pkg, sizeof(TS_RECORD_PKG));
|
||||
m_cache.append(data, size);
|
||||
|
||||
m_head.info.packages++;
|
||||
m_header_changed = true;
|
||||
}
|
||||
|
||||
void TppTelnetRec::record_win_size(int width, int height)
|
||||
{
|
||||
m_head.basic.width = (ex_u16)width;
|
||||
m_head.basic.height = (ex_u16)height;
|
||||
m_save_full_header = true;
|
||||
m_header_changed = true;
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_save_to_info_file() {
|
||||
if (!m_header_changed)
|
||||
return true;
|
||||
|
||||
if (m_file_info == NULL) {
|
||||
ex_wstr fname = m_base_path;
|
||||
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
|
||||
fname += L".tpr";
|
||||
|
||||
m_file_info = ex_fopen(fname, L"wb");
|
||||
if (NULL == m_file_info)
|
||||
{
|
||||
EXLOGE("[ssh] can not open record info-file for write.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// first time to save header, write whole header.
|
||||
m_save_full_header = true;
|
||||
}
|
||||
|
||||
fseek(m_file_info, 0L, SEEK_SET);
|
||||
if (m_save_full_header) {
|
||||
fwrite(&m_head, ts_record_header_size, 1, m_file_info);
|
||||
fflush(m_file_info);
|
||||
m_save_full_header = false;
|
||||
}
|
||||
else {
|
||||
fwrite(&m_head.info, ts_record_header_info_size, 1, m_file_info);
|
||||
fflush(m_file_info);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_save_to_data_file()
|
||||
{
|
||||
if (m_cache.size() == 0)
|
||||
return true;
|
||||
|
||||
if (m_file_data == NULL) {
|
||||
ex_wstr fname = m_base_path;
|
||||
ex_path_join(fname, false, m_base_fname.c_str(), NULL);
|
||||
fname += L".dat";
|
||||
|
||||
m_file_data = ex_fopen(fname, L"wb");
|
||||
if (NULL == m_file_data)
|
||||
{
|
||||
EXLOGE("[ssh] can not open record data-file for write.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_header_changed = true;
|
||||
}
|
||||
|
||||
fwrite(m_cache.data(), m_cache.size(), 1, m_file_data);
|
||||
fflush(m_file_data);
|
||||
m_cache.empty();
|
||||
|
||||
return _save_to_info_file();
|
||||
}
|
||||
|
||||
bool TppTelnetRec::_save_to_cmd_file()
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
TppTelnetRec();
|
||||
virtual ~TppTelnetRec();
|
||||
|
||||
// void record_time_begin(void); // 指定从此时开始计时,之前收到的包会计时为0,这样播放时会快进到此处。
|
||||
void record(ex_u8 type, const ex_u8* data, size_t size);
|
||||
void record_win_size(int width, int height);
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ TelnetSession::TelnetSession(TelnetProxy *proxy) :
|
|||
m_proxy(proxy),
|
||||
m_conn_info(NULL)
|
||||
{
|
||||
m_client_type = 0;
|
||||
m_state = TP_SESS_STAT_RUNNING;
|
||||
m_record_started = false;
|
||||
m_db_id = 0;
|
||||
m_is_relay = false;
|
||||
m_is_closed = false;
|
||||
|
@ -40,9 +40,6 @@ TelnetSession::~TelnetSession() {
|
|||
delete m_conn_client;
|
||||
delete m_conn_server;
|
||||
|
||||
// mbedtls_rsa_free(&m_server_pubkey);
|
||||
// mbedtls_rsa_free(&m_proxy_keypair_dynamic);
|
||||
|
||||
if (NULL != m_conn_info) {
|
||||
g_telnet_env.free_connect_info(m_conn_info);
|
||||
}
|
||||
|
@ -126,21 +123,9 @@ void TelnetSession::do_next(TelnetConn *conn) {
|
|||
case s_negotiation_with_client:
|
||||
new_status = _do_negotiation_with_client(conn);
|
||||
break;
|
||||
// case s_ssl_handshake_with_client: // 与客户端端进行SSL握手
|
||||
// new_status = _do_ssl_handshake_with_client();
|
||||
// break;
|
||||
// case s_connect_server:
|
||||
// new_status = _do_connect_server();
|
||||
// break;
|
||||
case s_server_connected:
|
||||
new_status = _do_server_connected();
|
||||
break;
|
||||
// case s_negotiation_with_server:
|
||||
// new_status = _do_negotiation_with_server();
|
||||
// break;
|
||||
// case s_ssl_handshake_with_server:
|
||||
// new_status = _do_ssl_handshake_with_server();
|
||||
// break;
|
||||
case s_relay:
|
||||
new_status = _do_relay(conn);
|
||||
break;
|
||||
|
@ -164,7 +149,6 @@ void TelnetSession::do_next(TelnetConn *conn) {
|
|||
if (m_status == s_dead) {
|
||||
EXLOGW("[telnet] try to remove session.\n");
|
||||
_on_session_end();
|
||||
//m_proxy->session_finished(this);
|
||||
m_is_closed = true;
|
||||
m_proxy->clean_session();
|
||||
}
|
||||
|
@ -410,9 +394,6 @@ sess_state TelnetSession::_do_negotiation_with_client(TelnetConn* conn) {
|
|||
}
|
||||
}
|
||||
|
||||
// 记录日志,会话开始了
|
||||
// set_info(sess_info);
|
||||
|
||||
// try to connect to real server.
|
||||
m_conn_server->connect(m_conn_ip.c_str(), m_conn_port);
|
||||
|
||||
|
@ -439,6 +420,7 @@ sess_state TelnetSession::_do_server_connected() {
|
|||
m_conn_server->send(_d, sizeof(_d) - 1);
|
||||
}
|
||||
|
||||
m_is_relay = true;
|
||||
EXLOGW("[telnet] enter relay mode.\n");
|
||||
|
||||
return s_relay;
|
||||
|
@ -451,15 +433,6 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
|||
if (conn->is_server_side())
|
||||
{
|
||||
// 收到了客户端发来的数据
|
||||
// if (!_this->m_is_changle_title_sent)
|
||||
// {
|
||||
// _this->m_is_changle_title_sent = true;
|
||||
// ts_astr msg = "\033]0;TP#telnet://";
|
||||
// msg += m_server_ip;
|
||||
// msg += "\007\x0d\x0a";
|
||||
// m_conn_client->send((ts_u8*)msg.c_str(), msg.length());
|
||||
// }
|
||||
|
||||
if (_this->m_is_putty_mode && !_this->m_is_putty_eat_username)
|
||||
{
|
||||
if (_this->_eat_username(m_conn_client, m_conn_server))
|
||||
|
@ -482,6 +455,8 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
|||
else
|
||||
{
|
||||
// 收到了服务端返回的数据
|
||||
if(m_record_started)
|
||||
m_rec.record(TS_RECORD_TYPE_TELNET_DATA, m_conn_server->data().data(), m_conn_server->data().size());
|
||||
|
||||
if (!_this->m_username_sent && _this->m_acc_name.length() > 0)
|
||||
{
|
||||
|
@ -497,6 +472,14 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
|||
{
|
||||
_this->m_password_sent = true;
|
||||
is_processed = true;
|
||||
|
||||
if (!m_record_started) {
|
||||
m_record_started = true;
|
||||
if (!_on_session_begin()) {
|
||||
return _do_close(TP_SESS_STAT_ERR_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,54 +489,7 @@ sess_state TelnetSession::_do_relay(TelnetConn *conn) {
|
|||
return s_relay;
|
||||
}
|
||||
|
||||
|
||||
// 替换会导致客户端窗口标题改变的数据
|
||||
//ts_u8* data = m_conn_server->data().data();
|
||||
//size_t len = m_conn_server->data().size();
|
||||
// if (len > 5)
|
||||
// {
|
||||
// const ts_u8* _begin = memmem(data, len, (const ts_u8*)"\033]0;", 4);
|
||||
//
|
||||
// if (NULL != _begin)
|
||||
// {
|
||||
// size_t len_before = _begin - data;
|
||||
//
|
||||
// const ts_u8* _end = memmem(_begin + 4, len - len_before, (const ts_u8*)"\007", 1);
|
||||
// if (NULL != _end)
|
||||
// {
|
||||
// _end++;
|
||||
//
|
||||
// // 这个包中含有改变标题的数据,将标题换为我们想要的
|
||||
// size_t len_end = len - (_end - data);
|
||||
// MemBuffer mbuf;
|
||||
//
|
||||
// if (len_before > 0)
|
||||
// mbuf.append(data, len_before);
|
||||
//
|
||||
// mbuf.append((ts_u8*)"\033]0;TP#ssh://", 13);
|
||||
// mbuf.append((ts_u8*)_this->m_server_ip.c_str(), _this->m_server_ip.length());
|
||||
// mbuf.append((ts_u8*)"\007", 1);
|
||||
//
|
||||
// if (len_end > 0)
|
||||
// mbuf.append(_end, len_end);
|
||||
//
|
||||
// m_conn_client->send(mbuf.data(), mbuf.size());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// m_conn_client->send(m_conn_server->data().data(), m_conn_server->data().size());
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// m_conn_client->send(m_conn_server->data().data(), m_conn_server->data().size());
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
{
|
||||
m_conn_client->send(m_conn_server->data().data(), m_conn_server->data().size());
|
||||
}
|
||||
|
||||
m_conn_client->send(m_conn_server->data().data(), m_conn_server->data().size());
|
||||
m_conn_server->data().empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ enum sess_state {
|
|||
s_client_connect, // 客户端连接
|
||||
s_negotiation_with_client, // 与客户端进行握手,直到得到客户端发来的登录用户名(其实是SessionID)
|
||||
|
||||
// s_connect_server, // 与服务端连接
|
||||
s_server_connected, // 成功连接上服务器了
|
||||
|
||||
s_relay, // 正常转发数据
|
||||
|
@ -38,8 +37,6 @@ public:
|
|||
TelnetConn* server() { return m_conn_server; }
|
||||
uv_loop_t* get_loop();
|
||||
|
||||
//bool is_client_auth_replaced() const { return m_is_client_auth_replaced; }
|
||||
|
||||
void set_state(int state) { m_state = state; }
|
||||
void close(int err_code);
|
||||
void on_conn_close();
|
||||
|
@ -53,13 +50,9 @@ public:
|
|||
m_rec.record(type, data, size);
|
||||
}
|
||||
|
||||
//static bool init_builtin_keypair();
|
||||
|
||||
void client_addr(const char* addr) { m_client_addr = addr; }
|
||||
const char* client_addr() const { return m_client_addr.c_str(); }
|
||||
|
||||
//static void release_builtin_keys();
|
||||
|
||||
bool is_relay() { return m_is_relay; }
|
||||
bool is_closed() { return m_is_closed; }
|
||||
|
||||
|
@ -72,26 +65,19 @@ protected:
|
|||
private:
|
||||
sess_state _do_client_connect(TelnetConn* conn);
|
||||
sess_state _do_negotiation_with_client(TelnetConn* conn);
|
||||
//sess_state _do_ssl_handshake_with_client();
|
||||
// sess_state _do_connect_server();
|
||||
sess_state _do_server_connected();
|
||||
//sess_state _do_negotiation_with_server();
|
||||
//sess_state _do_ssl_handshake_with_server();
|
||||
sess_state _do_relay(TelnetConn* conn);
|
||||
//sess_state _relay_dispatch_rdp(TelnetConn* conn_from, TelnetConn* conn_to);
|
||||
//sess_state _relay_dispatch_ssl(TelnetConn* conn_from, TelnetConn* conn_to);
|
||||
sess_state _do_close(int err_code);
|
||||
sess_state _do_check_closing();
|
||||
|
||||
//bool _replace_server_cert(SC_ConferenceCreateResponse& gcc);
|
||||
bool _parse_find_and_send(TelnetConn* conn_recv, TelnetConn* conn_remote, const char* find, const char* send);
|
||||
bool _eat_username(TelnetConn* conn_recv, TelnetConn* conn_remote);
|
||||
|
||||
private:
|
||||
int m_state;
|
||||
int m_client_type; // 1 = mstsc, 2=freerdp
|
||||
|
||||
TPP_CONNECT_INFO* m_conn_info;
|
||||
bool m_record_started;
|
||||
int m_db_id;
|
||||
|
||||
bool m_is_relay; // 是否进入relay模式了(只有进入relay模式才会有录像存在)
|
||||
|
@ -118,7 +104,6 @@ private:
|
|||
|
||||
bool m_is_putty_mode;
|
||||
bool m_is_putty_eat_username;
|
||||
// bool m_is_changle_title_sent; // 连接成功后,可以给客户端发送一个特殊的字符序列,客户端会改变窗口标题(已经在PuTTY/SecureCRT测试过)
|
||||
|
||||
bool m_username_sent;
|
||||
bool m_password_sent;
|
||||
|
|
|
@ -19,14 +19,14 @@ bool TppTelnetEnv::_on_init(TPP_INIT_ARGS* args) {
|
|||
|
||||
ex_wstr tmp;
|
||||
if (!ps->GetStr(L"bind-ip", tmp)) {
|
||||
bind_ip = TS_RDP_PROXY_HOST;
|
||||
bind_ip = TS_TELNET_PROXY_HOST;
|
||||
}
|
||||
else {
|
||||
ex_wstr2astr(tmp, bind_ip);
|
||||
}
|
||||
|
||||
if (!ps->GetInt(L"bind-port", bind_port)) {
|
||||
bind_port = TS_RDP_PROXY_PORT;
|
||||
bind_port = TS_TELNET_PROXY_PORT;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -167,47 +167,6 @@
|
|||
<ClCompile Include="..\..\..\..\external\libuv\src\win\util.c" />
|
||||
<ClCompile Include="..\..\..\..\external\libuv\src\win\winapi.c" />
|
||||
<ClCompile Include="..\..\..\..\external\libuv\src\win\winsock.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\aes.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\arc4.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\asn1parse.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\base64.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\bignum.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\blowfish.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\certs.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\cipher.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\cipher_wrap.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ctr_drbg.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\debug.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\des.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\dhm.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\entropy.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\entropy_poll.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\error.c">
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)mbedtls_error.obj</ObjectFileName>
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)mbedtls_error.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\hmac_drbg.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md5.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md_wrap.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\oid.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pem.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pk.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkcs12.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkcs5.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkparse.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pk_wrap.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\rsa.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha1.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha256.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha512.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_ciphersuites.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_cli.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_srv.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_tls.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\timing.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\x509.c" />
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\x509_crt.c" />
|
||||
<ClCompile Include="..\..\common\base_env.cpp" />
|
||||
<ClCompile Include="..\..\common\base_record.cpp" />
|
||||
<ClCompile Include="..\..\common\ts_membuf.cpp" />
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
<Filter Include="libuv\src\win">
|
||||
<UniqueIdentifier>{89181d75-3db3-45a5-a35d-9083fb349de3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="mbedtls">
|
||||
<UniqueIdentifier>{bedac06f-83d5-4cd3-832d-0bce55c3dc52}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\common\libex\include\ex\ex_const.h">
|
||||
|
@ -304,119 +301,5 @@
|
|||
<ClCompile Include="..\..\..\..\external\libuv\src\win\process-stdio.c">
|
||||
<Filter>libuv\src\win</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\rsa.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha1.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md5.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\bignum.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\md_wrap.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha256.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\sha512.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\asn1parse.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\oid.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\debug.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\x509.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pk.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pk_wrap.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\x509_crt.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\certs.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\entropy.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ctr_drbg.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\arc4.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pem.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\dhm.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\cipher.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\aes.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\des.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\base64.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\hmac_drbg.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\entropy_poll.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\cipher_wrap.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\blowfish.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkparse.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkcs5.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\pkcs12.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\error.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\timing.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_tls.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_ciphersuites.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_cli.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\external\mbedtls\library\ssl_srv.c">
|
||||
<Filter>mbedtls</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -166,6 +166,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
|||
// window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
||||
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) {
|
||||
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
||||
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_TELNET) {
|
||||
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
||||
}
|
||||
} else if (action === 'cmd') {
|
||||
//$app.dlg_accounts.show(row_id);
|
||||
|
@ -334,7 +336,7 @@ $app.on_table_host_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.record_action = function (row_id, fields) {
|
||||
if(fields.state === TP_SESS_STAT_RUNNING || fields.state === TP_SESS_STAT_STARTED)
|
||||
if (fields.state === TP_SESS_STAT_RUNNING || fields.state === TP_SESS_STAT_STARTED)
|
||||
return '';
|
||||
|
||||
var ret = [];
|
||||
|
@ -346,7 +348,9 @@ $app.on_table_host_render_created = function (render) {
|
|||
if (fields.protocol_sub_type !== TP_PROTOCOL_TYPE_SSH_SFTP)
|
||||
ret.push('<a href="javascript:;" class="btn btn-sm btn-primary" data-action="replay" data-record-id="' + fields.id + '"><i class="fa fa-caret-square-o-right fa-fw"></i> 回放</a> ');
|
||||
}
|
||||
if (fields.protocol_sub_type !== TP_PROTOCOL_TYPE_RDP_DESKTOP) {
|
||||
if (fields.protocol_sub_type === TP_PROTOCOL_TYPE_SSH_SHELL
|
||||
|| fields.protocol_sub_type === TP_PROTOCOL_TYPE_SSH_SFTP
|
||||
) {
|
||||
ret.push('<a href="javascript:;" class="btn btn-sm btn-info" data-action="cmd" data-record-id="' + fields.id + '"><i class="fa fa-list-alt fa-fw"></i> 日志</a> ');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
"use strict";
|
||||
|
||||
$app.on_init = function (cb_stack) {
|
||||
var record_id = $app.options.record_id;
|
||||
|
||||
$app.record_hdr = null;
|
||||
$app.record_data = [];
|
||||
$app.record_data_offset = 0;
|
||||
$app.played_pkg_count = 0;
|
||||
$app.player_timer = null;
|
||||
$app.is_playing = false;
|
||||
$app.is_need_stop = false;
|
||||
$app.need_skip = true;
|
||||
$app.player_console_term = null;
|
||||
$app.player_current_time = null;
|
||||
$app.is_finished = false;
|
||||
$app.record_tick = 50;
|
||||
|
||||
|
||||
$app.speed_table = [
|
||||
{speed: 1, name: '正常速度'},
|
||||
{speed: 2, name: '快进 x2'},
|
||||
{speed: 4, name: '快进 x4'},
|
||||
{speed: 8, name: '快进 x8'},
|
||||
{speed: 16, name: '快进 x16'}
|
||||
];
|
||||
$app.speed_offset = 0;
|
||||
|
||||
|
||||
$app.dom = {
|
||||
time: $('#play-time'),
|
||||
btn_play: $('#btn-play'),
|
||||
btn_speed: $('#btn-speed'),
|
||||
btn_skip: $('#btn-skip'),
|
||||
btn_restart: $('#btn-restart'),
|
||||
btn_big_font: $('#btn-big-font'),
|
||||
btn_small_font: $('#btn-small-font'),
|
||||
progress: $('#progress'),
|
||||
status: $('#play-status'),
|
||||
xterm_box: $('#xterm-box'),
|
||||
xterm_terminal: null,
|
||||
xterm_viewport: null
|
||||
};
|
||||
|
||||
$app.dom.progress.width($('#toolbar').width()).val(0);
|
||||
|
||||
Terminal.cursorBlink = false;
|
||||
|
||||
$tp.ajax_post_json('/audit/get-record-header', {protocol: TP_PROTOCOL_TYPE_TELNET, id: record_id},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
$app.record_hdr = ret.data;
|
||||
if ($app.record_hdr.width === 0)
|
||||
$app.record_hdr.width = 80;
|
||||
if ($app.record_hdr.height === 0)
|
||||
$app.record_hdr.height = 24;
|
||||
console.log('header', $app.record_hdr);
|
||||
|
||||
$('#recorder-info').html(tp_format_datetime($app.record_hdr.start) + ': ' + $app.record_hdr.user_name + '@' + $app.record_hdr.client_ip + ' 访问 ' + $app.record_hdr.account + '@' + $app.record_hdr.conn_ip + ':' + $app.record_hdr.conn_port);
|
||||
|
||||
$app.req_record_data(record_id, 0);
|
||||
|
||||
$app.player_current_time = 0;
|
||||
//setTimeout(init, 500);
|
||||
$app.init_and_play();
|
||||
} else {
|
||||
$tp.notify_error('读取录像信息失败:' + tp_error_msg(ret.code, ret.message));
|
||||
console.error('load init info error ', ret.code);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
$tp.notify_error('网络通讯失败');
|
||||
}
|
||||
);
|
||||
|
||||
$app.dom.btn_big_font.click(function () {
|
||||
if (_.isNull($app.dom.xterm_terminal))
|
||||
return;
|
||||
var _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
if (_size >= 24)
|
||||
return;
|
||||
|
||||
$app.dom.xterm_terminal.css('font-size', _size + 1);
|
||||
|
||||
$app.player_console_term.charMeasure.measure();
|
||||
$app.adjust_viewport();
|
||||
});
|
||||
|
||||
$app.dom.btn_small_font.click(function () {
|
||||
if (_.isNull($app.dom.xterm_terminal))
|
||||
return;
|
||||
|
||||
var _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
if (_size <= 12)
|
||||
return;
|
||||
|
||||
$app.dom.xterm_terminal.css('font-size', _size - 1);
|
||||
|
||||
$app.player_console_term.charMeasure.measure();
|
||||
$app.adjust_viewport();
|
||||
});
|
||||
|
||||
$app.dom.btn_play.click(function () {
|
||||
if ($app.is_playing)
|
||||
$app.pause();
|
||||
else
|
||||
$app.play();
|
||||
});
|
||||
|
||||
$app.dom.btn_skip.click(function () {
|
||||
var obj = $('#btn-skip i');
|
||||
if ($app.need_skip) {
|
||||
$app.need_skip = false;
|
||||
obj.removeClass('fa-check-square-o').addClass('fa-square-o');
|
||||
} else {
|
||||
$app.need_skip = true;
|
||||
obj.removeClass('fa-square-o').addClass('fa-check-square-o');
|
||||
}
|
||||
|
||||
// console.log('skip:', $app.need_skip);
|
||||
});
|
||||
|
||||
$app.dom.btn_restart.click(function () {
|
||||
$app.restart();
|
||||
});
|
||||
|
||||
$app.speed_offset = 0;
|
||||
$app.dom.btn_speed.text($app.speed_table[$app.speed_offset].name);
|
||||
|
||||
$app.dom.btn_speed.click(function () {
|
||||
var length = $app.speed_table.length;
|
||||
$app.speed_offset += 1;
|
||||
if ($app.speed_offset === length) {
|
||||
$app.speed_offset = 0;
|
||||
}
|
||||
$app.dom.btn_speed.text($app.speed_table[$app.speed_offset].name);
|
||||
});
|
||||
|
||||
$app.dom.progress.mousedown(function () {
|
||||
$app.pause();
|
||||
});
|
||||
$app.dom.progress.mouseup(function () {
|
||||
$app.player_current_time = parseInt($app.record_hdr.time_used * $app.dom.progress.val() / 100);
|
||||
setTimeout(function () {
|
||||
$app.init_and_play();
|
||||
}, 100);
|
||||
});
|
||||
$app.dom.progress.mousemove(function () {
|
||||
$app.player_current_time = parseInt($app.record_hdr.time_used * $app.dom.progress.val() / 100);
|
||||
$app.dom.time.text(parseInt(($app.player_current_time) / 1000) + '/' + parseInt($app.record_hdr.time_used / 1000) + '秒');
|
||||
});
|
||||
|
||||
$app.adjust_viewport = function () {
|
||||
if (!_.isNull($app.dom.xterm_viewport)) {
|
||||
$app.dom.xterm_viewport.width(parseInt(window.getComputedStyle($app.dom.xterm_rows[0]).width));
|
||||
$app.dom.xterm_viewport.height(parseInt(window.getComputedStyle($app.dom.xterm_rows[0]).height) - 1);
|
||||
}
|
||||
};
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
$app.req_record_data = function (record_id, offset) {
|
||||
$tp.ajax_post_json('/audit/get-record-data', {protocol: TP_PROTOCOL_TYPE_TELNET, id: record_id, offset: offset},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
// console.log('data', ret.data);
|
||||
$app.record_data = $app.record_data.concat(ret.data.data_list);
|
||||
$app.record_data_offset += ret.data.data_size;
|
||||
|
||||
if ($app.record_data.length < $app.record_hdr.pkg_count) {
|
||||
$app.req_record_data(record_id, $app.record_data_offset);
|
||||
}
|
||||
} else {
|
||||
$app.dom.status.text("读取录像数据失败:" + tp_error_msg(ret.code));
|
||||
$tp.notify_error('读取录像数据失败:' + tp_error_msg(ret.code, ret.message));
|
||||
console.log('req_record_info error ', ret.code);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
console.log('req_record_info error');
|
||||
},
|
||||
30 * 1000
|
||||
);
|
||||
};
|
||||
|
||||
$app.init_and_play = function() {
|
||||
if (_.isNull($app.player_console_term)) {
|
||||
$app.player_console_term = new Terminal({
|
||||
cols: $app.record_hdr.width,
|
||||
rows: $app.record_hdr.height
|
||||
});
|
||||
|
||||
$app.player_console_term.on('refresh', function () {
|
||||
$app.adjust_viewport();
|
||||
});
|
||||
|
||||
$app.player_console_term.open(document.getElementById('xterm-box'), true);
|
||||
|
||||
$app.dom.xterm_terminal = $('#xterm-box .terminal');
|
||||
$app.dom.xterm_rows = $('#xterm-box .terminal .xterm-rows');
|
||||
$app.dom.xterm_viewport = $('#xterm-box .terminal .xterm-viewport');
|
||||
} else {
|
||||
$app.player_console_term.reset($app.record_hdr.width, $app.record_hdr.height);
|
||||
}
|
||||
|
||||
if ($app.record_hdr.pkg_count === 0)
|
||||
return;
|
||||
|
||||
$app.dom.progress.val(0);
|
||||
// $app.dom.status.text("正在播放");
|
||||
$app.dom.btn_play.children().removeClass().addClass('fa fa-pause').text(' 暂停');
|
||||
|
||||
$app.is_need_stop = false;
|
||||
$app.is_playing = true;
|
||||
$app.is_finished = false;
|
||||
$app.played_pkg_count = 0;
|
||||
//setTimeout(do_play, $app.record_tick);
|
||||
$app.do_play();
|
||||
};
|
||||
|
||||
$app.do_play = function() {
|
||||
if ($app.is_need_stop) {
|
||||
$app.is_playing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($app.record_data.length <= $app.played_pkg_count) {
|
||||
$app.dom.status.text("正在缓存数据...");
|
||||
$app.player_timer = setTimeout($app.do_play, $app.record_tick);
|
||||
return;
|
||||
}
|
||||
|
||||
$app.dom.status.text("正在播放");
|
||||
$app.player_current_time += $app.record_tick * $app.speed_table[$app.speed_offset].speed;
|
||||
|
||||
var _record_tick = $app.record_tick;
|
||||
|
||||
for (var i = $app.played_pkg_count; i < $app.record_data.length; i++) {
|
||||
if ($app.is_need_stop)
|
||||
break;
|
||||
|
||||
var play_data = $app.record_data[i];
|
||||
|
||||
if (play_data.t < $app.player_current_time) {
|
||||
if (play_data.a === 1) {
|
||||
$app.player_console_term.resize(play_data.w, play_data.h);
|
||||
} else if (play_data.a === 2) {
|
||||
$app.player_console_term.write(play_data.d);
|
||||
}
|
||||
else {
|
||||
$app.player_console_term.write(tp_base64_decode(play_data.d));
|
||||
}
|
||||
|
||||
if (($app.played_pkg_count + 1) === $app.record_hdr.pkg_count) {
|
||||
$app.dom.progress.val(100);
|
||||
$app.dom.status.text('播放完成');
|
||||
$app.dom.time.text(parseInt($app.record_hdr.time_used / 1000) + '秒');
|
||||
$app.is_finished = true;
|
||||
$app.is_playing = false;
|
||||
$app.dom.btn_play.children().removeClass().addClass('fa fa-play').text(' 播放');
|
||||
|
||||
return;
|
||||
} else {
|
||||
$app.played_pkg_count++;
|
||||
}
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($app.is_need_stop)
|
||||
return;
|
||||
|
||||
if ($app.need_skip) {
|
||||
if (play_data.t - $app.player_current_time > 800) {
|
||||
$app.player_current_time = play_data.t; // - $app.record_tick * $app.speed_table[$app.speed_offset].speed;
|
||||
_record_tick = 800;
|
||||
}
|
||||
}
|
||||
|
||||
// sync progress bar.
|
||||
var _progress = parseInt($app.player_current_time * 100 / $app.record_hdr.time_used);
|
||||
$app.dom.progress.val(_progress);
|
||||
var temp = parseInt($app.player_current_time / 1000);
|
||||
$app.dom.time.text(temp + '/' + parseInt($app.record_hdr.time_used / 1000) + '秒');
|
||||
|
||||
// if all packages played
|
||||
if ($app.played_pkg_count >= $app.record_hdr.pkg_count) {
|
||||
$app.dom.progress.val(100);
|
||||
$app.dom.status.text('播放完成');
|
||||
$app.dom.time.text(parseInt($app.record_hdr.time_used / 1000) + '秒');
|
||||
$app.is_finished = true;
|
||||
$app.is_playing = false;
|
||||
$app.dom.btn_play.children().removeClass().addClass('fa fa-play').text(' 播放');
|
||||
} else {
|
||||
if (!$app.is_need_stop)
|
||||
$app.player_timer = setTimeout($app.do_play, _record_tick);
|
||||
}
|
||||
};
|
||||
|
||||
$app.play = function() {
|
||||
if ($app.is_playing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($app.is_finished) {
|
||||
$app.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
$app.dom.btn_play.children().removeClass().addClass('fa fa-pause').text(' 暂停');
|
||||
|
||||
$app.is_need_stop = false;
|
||||
$app.is_playing = true;
|
||||
$app.player_timer = setTimeout($app.do_play, $app.record_tick);
|
||||
};
|
||||
|
||||
$app.pause = function() {
|
||||
if (!_.isNull($app.player_timer))
|
||||
clearTimeout($app.player_timer);
|
||||
$app.dom.btn_play.children().removeClass().addClass('fa fa-play').text(' 播放');
|
||||
$app.is_need_stop = true;
|
||||
$app.is_playing = false;
|
||||
$app.dom.status.text("已暂停");
|
||||
};
|
||||
|
||||
$app.restart = function() {
|
||||
if (!_.isNull($app.player_timer))
|
||||
clearTimeout($app.player_timer);
|
||||
$app.player_current_time = 0;
|
||||
$app.init_and_play();
|
||||
};
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<%!
|
||||
page_title_ = '录像回放'
|
||||
%>
|
||||
|
||||
<%inherit file="../page_single_base.mako"/>
|
||||
|
||||
<%block name="extend_js_file">
|
||||
<script type="text/javascript" src="${ static_url('plugins/xterm/xterm.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('js/audit/replay-telnet.js') }"></script>
|
||||
</%block>
|
||||
|
||||
<%block name="extend_css_file">
|
||||
<link href="${ static_url('plugins/xterm/xterm.css') }" rel="stylesheet" type="text/css"/>
|
||||
</%block>
|
||||
|
||||
<%block name="embed_css">
|
||||
<style type="text/css">
|
||||
.container {
|
||||
width:100%;
|
||||
padding-right: 20px;
|
||||
}
|
||||
#xterm-box {
|
||||
margin: 10px 0;
|
||||
## background-color: #1e1e1e;
|
||||
## margin-top: 10px;
|
||||
## margin-bottom: 48px;
|
||||
## width: 300px;
|
||||
## border: 1px solid #9c9c9c;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
font-family: Consolas, Monaco, courier-new, courier, monospace;
|
||||
color: #b7b7b7;
|
||||
font-size: 13px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
## background-color: transparent;
|
||||
}
|
||||
|
||||
.terminal .xterm-viewport {
|
||||
## background-color: transparent;
|
||||
## display:none;
|
||||
## overflow: auto;
|
||||
padding-right:17px;
|
||||
}
|
||||
|
||||
.terminal .xterm-rows {
|
||||
## margin:5px;
|
||||
padding:5px;
|
||||
border-right: 1px dashed #363636;
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
</style>
|
||||
</%block>
|
||||
|
||||
<%block name="page_header">
|
||||
<div class="container-fluid top-navbar">
|
||||
<div class="breadcrumb-container">
|
||||
<ol class="breadcrumb">
|
||||
<li><i class="fa fa-server"></i> ${self.attr.page_title_}</li>
|
||||
<li class="sub-title"><span id="recorder-info"></span></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</%block>
|
||||
|
||||
|
||||
<div class="page-content">
|
||||
<div id="toolbar" style="display: inline-block;">
|
||||
<button id="btn-play" type="button" class="btn btn-primary btn-sm" style="width:80px;"><i class="fa fa-pause fa-fw"> 暂停</i></button>
|
||||
<button id="btn-restart" type="button" class="btn btn-success btn-sm"><i class="fa fa-refresh fa-fw"></i> 重新播放</button>
|
||||
|
||||
<button id="btn-speed" type="button" class="btn btn-info btn-sm" style="width:80px;">正常速度</button>
|
||||
|
||||
<button id="btn-big-font" type="button" class="btn btn-default btn-sm"><i class="fa fa-font fa-fw"></i>+</button>
|
||||
<button id="btn-small-font" type="button" class="btn btn-default btn-sm"><i class="fa fa-font fa-fw"></i>-</button>
|
||||
|
||||
<div style="display:inline-block;position:relative;top:4px;margin-left:10px;margin-right:15px;">
|
||||
<span id="btn-skip" style="cursor:pointer;"><i class="fa fa-check-square-o fa-fw"></i> 跳过无操作时间</span>
|
||||
</div>
|
||||
|
||||
<span id="play-status" class="badge badge-normal" style="margin-left:5px;">正在获取数据</span>
|
||||
<span id="play-time" class="badge badge-success" style="margin-left:5px;">总时长:未知</span>
|
||||
</div>
|
||||
<input id="progress" type="range" value="0" min=0 max=100 style="margin-top: 10px;"/>
|
||||
<div id="xterm-box"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<%block name="extend_content">
|
||||
|
||||
</%block>
|
||||
|
||||
|
||||
|
||||
<%block name="embed_js">
|
||||
<script type="text/javascript">
|
||||
$app.add_options(${page_param});
|
||||
</script>
|
||||
</%block>
|
|
@ -499,6 +499,9 @@ class ReplayHandler(TPBaseHandler):
|
|||
elif protocol == TP_PROTOCOL_TYPE_SSH:
|
||||
param = {'record_id': record_id}
|
||||
self.render('audit/replay-ssh.mako', page_param=json.dumps(param))
|
||||
elif protocol == TP_PROTOCOL_TYPE_TELNET:
|
||||
param = {'record_id': record_id}
|
||||
self.render('audit/replay-telnet.mako', page_param=json.dumps(param))
|
||||
|
||||
|
||||
# # class PlayRdpHandler(TPBaseAdminAuthHandler):
|
||||
|
@ -641,6 +644,8 @@ class DoGetRecordDataHandler(TPBaseJsonHandler):
|
|||
data_list, data_size, err = record.read_rdp_record_data(record_id, offset)
|
||||
elif protocol_type == TP_PROTOCOL_TYPE_SSH:
|
||||
data_list, data_size, err = record.read_ssh_record_data(record_id, offset)
|
||||
elif protocol_type == TP_PROTOCOL_TYPE_TELNET:
|
||||
data_list, data_size, err = record.read_telnet_record_data(record_id, offset)
|
||||
else:
|
||||
self.write_json(TPE_NOT_EXISTS)
|
||||
self.write_json(err, data={'data_list': data_list, 'data_size': data_size})
|
||||
|
|
|
@ -134,6 +134,8 @@ def read_record_head(protocol_type, record_id):
|
|||
path_name = 'rdp'
|
||||
elif protocol_type == TP_PROTOCOL_TYPE_SSH:
|
||||
path_name = 'ssh'
|
||||
elif protocol_type == TP_PROTOCOL_TYPE_TELNET:
|
||||
path_name = 'telnet'
|
||||
|
||||
record_path = os.path.join(tp_cfg().core.replay_path, path_name, '{:09d}'.format(int(record_id)))
|
||||
header_file_path = os.path.join(record_path, 'tp-{}.tpr'.format(path_name))
|
||||
|
@ -366,6 +368,82 @@ def read_ssh_record_data(record_id, offset):
|
|||
return data_list, data_size, TPE_OK
|
||||
|
||||
|
||||
def read_telnet_record_data(record_id, offset):
|
||||
if not tp_cfg().core.detected:
|
||||
return None, TPE_NO_CORE_SERVER
|
||||
|
||||
record_path = os.path.join(tp_cfg().core.replay_path, 'telnet', '{:09d}'.format(int(record_id)))
|
||||
file_data = os.path.join(record_path, 'tp-telnet.dat')
|
||||
|
||||
if not os.path.exists(file_data):
|
||||
return None, 0, TPE_NOT_EXISTS
|
||||
|
||||
data_list = list()
|
||||
data_size = 0
|
||||
file = None
|
||||
try:
|
||||
file_size = os.path.getsize(file_data)
|
||||
if offset >= file_size:
|
||||
return None, 0, TPE_FAILED
|
||||
|
||||
file = open(file_data, 'rb')
|
||||
if offset > 0:
|
||||
file.seek(offset, io.SEEK_SET)
|
||||
|
||||
# read 1000 packages one time from offset.
|
||||
for i in range(1000):
|
||||
"""
|
||||
// 一个数据包的头
|
||||
typedef struct TS_RECORD_PKG
|
||||
{
|
||||
ex_u8 type; // 包的数据类型
|
||||
ex_u32 size; // 这个包的总大小(不含包头)
|
||||
ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天)
|
||||
ex_u8 _reserve[3]; // 保留
|
||||
}TS_RECORD_PKG;
|
||||
"""
|
||||
_data = file.read(12)
|
||||
data_size += 12
|
||||
_action, _size, _time, = struct.unpack_from('=BII', _data)
|
||||
if offset + data_size + _size > file_size:
|
||||
return None, 0, TPE_FAILED
|
||||
|
||||
_data = file.read(_size)
|
||||
data_size += _size
|
||||
|
||||
temp = dict()
|
||||
temp['a'] = _action
|
||||
temp['t'] = _time
|
||||
if _action == 1:
|
||||
# this is window size changed.
|
||||
w, h = struct.unpack_from('HH', _data)
|
||||
temp['w'] = w
|
||||
temp['h'] = h
|
||||
elif _action == 2:
|
||||
try:
|
||||
_d = _data.decode()
|
||||
temp['d'] = _d
|
||||
except:
|
||||
_data = base64.b64encode(_data)
|
||||
temp['a'] = 3
|
||||
temp['d'] = _data.decode()
|
||||
else:
|
||||
return None, 0, TPE_FAILED
|
||||
|
||||
data_list.append(temp)
|
||||
if offset + data_size == file_size:
|
||||
break
|
||||
|
||||
except Exception:
|
||||
log.e('failed to read record file: {}\n'.format(file_data))
|
||||
return None, 0, TPE_FAILED
|
||||
finally:
|
||||
if file is not None:
|
||||
file.close()
|
||||
|
||||
return data_list, data_size, TPE_OK
|
||||
|
||||
|
||||
def delete_log(log_list):
|
||||
try:
|
||||
where = list()
|
||||
|
|
Loading…
Reference in New Issue