diff --git a/server/share/etc/core.ini.in b/server/share/etc/core.ini.in index 9b7fcef..3d4cfbd 100644 --- a/server/share/etc/core.ini.in +++ b/server/share/etc/core.ini.in @@ -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 diff --git a/server/tp_core/protocol/telnet/telnet_conn.cpp b/server/tp_core/protocol/telnet/telnet_conn.cpp index 0704129..9f37962 100644 --- a/server/tp_core/protocol/telnet/telnet_conn.cpp +++ b/server/tp_core/protocol/telnet/telnet_conn.cpp @@ -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) { - } diff --git a/server/tp_core/protocol/telnet/telnet_conn.h b/server/tp_core/protocol/telnet/telnet_conn.h index ed3679b..653deee 100644 --- a/server/tp_core/protocol/telnet/telnet_conn.h +++ b/server/tp_core/protocol/telnet/telnet_conn.h @@ -3,19 +3,8 @@ #include -// typedef time_t mbedtls_time_t; - -// #include -// #include -// #include -// #include - -// #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__ diff --git a/server/tp_core/protocol/telnet/telnet_recorder.cpp b/server/tp_core/protocol/telnet/telnet_recorder.cpp index d5941a1..6077a65 100644 --- a/server/tp_core/protocol/telnet/telnet_recorder.cpp +++ b/server/tp_core/protocol/telnet/telnet_recorder.cpp @@ -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() { diff --git a/server/tp_core/protocol/telnet/telnet_recorder.h b/server/tp_core/protocol/telnet/telnet_recorder.h index c7fab7c..2f23f50 100644 --- a/server/tp_core/protocol/telnet/telnet_recorder.h +++ b/server/tp_core/protocol/telnet/telnet_recorder.h @@ -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); diff --git a/server/tp_core/protocol/telnet/telnet_session.cpp b/server/tp_core/protocol/telnet/telnet_session.cpp index 935a718..0a8e025 100644 --- a/server/tp_core/protocol/telnet/telnet_session.cpp +++ b/server/tp_core/protocol/telnet/telnet_session.cpp @@ -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(); } diff --git a/server/tp_core/protocol/telnet/telnet_session.h b/server/tp_core/protocol/telnet/telnet_session.h index 8874725..a5ce14e 100644 --- a/server/tp_core/protocol/telnet/telnet_session.h +++ b/server/tp_core/protocol/telnet/telnet_session.h @@ -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; diff --git a/server/tp_core/protocol/telnet/tpp_env.cpp b/server/tp_core/protocol/telnet/tpp_env.cpp index fbd6f33..87b7c1d 100644 --- a/server/tp_core/protocol/telnet/tpp_env.cpp +++ b/server/tp_core/protocol/telnet/tpp_env.cpp @@ -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; diff --git a/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj b/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj index c7c30cf..9cb69c7 100644 --- a/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj +++ b/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj @@ -167,47 +167,6 @@ - - - - - - - - - - - - - - - - - $(IntDir)mbedtls_error.obj - $(IntDir)mbedtls_error.obj - - - - - - - - - - - - - - - - - - - - - - - diff --git a/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj.filters b/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj.filters index 4429103..8daa78f 100644 --- a/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj.filters +++ b/server/tp_core/protocol/telnet/tptelnet.vs2015.vcxproj.filters @@ -36,9 +36,6 @@ {89181d75-3db3-45a5-a35d-9083fb349de3} - - {bedac06f-83d5-4cd3-832d-0bce55c3dc52} - @@ -304,119 +301,5 @@ libuv\src\win - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - - - mbedtls - \ No newline at end of file diff --git a/server/www/teleport/static/js/audit/record-list.js b/server/www/teleport/static/js/audit/record-list.js index 432edb6..4fe4b57 100644 --- a/server/www/teleport/static/js/audit/record-list.js +++ b/server/www/teleport/static/js/audit/record-list.js @@ -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(' 鍥炴斁 '); } - 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(' 鏃ュ織 '); } } diff --git a/server/www/teleport/static/js/audit/replay-telnet.js b/server/www/teleport/static/js/audit/replay-telnet.js new file mode 100644 index 0000000..b38225c --- /dev/null +++ b/server/www/teleport/static/js/audit/replay-telnet.js @@ -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: '姝e父閫熷害'}, + {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("姝e湪鎾斁"); + $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("姝e湪缂撳瓨鏁版嵁..."); + $app.player_timer = setTimeout($app.do_play, $app.record_tick); + return; + } + + $app.dom.status.text("姝e湪鎾斁"); + $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(); +}; + diff --git a/server/www/teleport/view/audit/replay-telnet.mako b/server/www/teleport/view/audit/replay-telnet.mako new file mode 100644 index 0000000..5a6d90c --- /dev/null +++ b/server/www/teleport/view/audit/replay-telnet.mako @@ -0,0 +1,105 @@ +<%! + page_title_ = '褰曞儚鍥炴斁' +%> + +<%inherit file="../page_single_base.mako"/> + +<%block name="extend_js_file"> + + + + +<%block name="extend_css_file"> + + + +<%block name="embed_css"> + + + +<%block name="page_header"> +
+ +
+ + + +
+
+ + + + + + + + +
+ 璺宠繃鏃犳搷浣滄椂闂 +
+ + 姝e湪鑾峰彇鏁版嵁 + 鎬绘椂闀:鏈煡 +
+ +
+ +
+ + + + +<%block name="extend_content"> + + + + + +<%block name="embed_js"> + + \ No newline at end of file diff --git a/server/www/teleport/webroot/app/controller/audit.py b/server/www/teleport/webroot/app/controller/audit.py index 9591292..3766b97 100644 --- a/server/www/teleport/webroot/app/controller/audit.py +++ b/server/www/teleport/webroot/app/controller/audit.py @@ -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}) diff --git a/server/www/teleport/webroot/app/model/record.py b/server/www/teleport/webroot/app/model/record.py index faa1ab1..97857ac 100644 --- a/server/www/teleport/webroot/app/model/record.py +++ b/server/www/teleport/webroot/app/model/record.py @@ -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()