mirror of https://github.com/tp4a/teleport
rdp播放功能部分可用(支持播放FreeRDP的录像,但是不能播放MSCST的录像)。
parent
a3e0fea4d4
commit
d6bcdeb42d
|
@ -1174,92 +1174,124 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断参数是否正确
|
// 判断参数是否正确
|
||||||
if (!jsRoot["host"].isString())
|
// if (!jsRoot["host"].isString())
|
||||||
{
|
// {
|
||||||
_create_json_ret(buf, TPE_PARAM);
|
// _create_json_ret(buf, TPE_PARAM);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (!jsRoot["port"].isInt())
|
// if (!jsRoot["port"].isInt())
|
||||||
{
|
// {
|
||||||
_create_json_ret(buf, TPE_PARAM);
|
// _create_json_ret(buf, TPE_PARAM);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if (!jsRoot["tail"].isString())
|
|
||||||
|
if (!jsRoot["rid"].isInt()
|
||||||
|
|| !jsRoot["web"].isString()
|
||||||
|
|| !jsRoot["sid"].isString()
|
||||||
|
|| !jsRoot["user"].isString()
|
||||||
|
|| !jsRoot["acc"].isString()
|
||||||
|
|| !jsRoot["host"].isString()
|
||||||
|
|| !jsRoot["start"].isString()
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_create_json_ret(buf, TPE_PARAM);
|
_create_json_ret(buf, TPE_PARAM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (!jsRoot["tail"].isString())
|
||||||
|
// {
|
||||||
|
// _create_json_ret(buf, TPE_PARAM);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
int rid = jsRoot["rid"].asInt();
|
||||||
|
ex_astr a_url_base = jsRoot["web"].asCString();
|
||||||
|
ex_astr a_sid = jsRoot["sid"].asCString();
|
||||||
|
ex_astr a_user = jsRoot["user"].asCString();
|
||||||
|
ex_astr a_acc = jsRoot["acc"].asCString();
|
||||||
ex_astr a_host = jsRoot["host"].asCString();
|
ex_astr a_host = jsRoot["host"].asCString();
|
||||||
int port = jsRoot["port"].asInt();
|
ex_astr a_start = jsRoot["start"].asCString();
|
||||||
ex_astr a_tail = jsRoot["tail"].asCString();
|
//ex_astr a_tail = jsRoot["tail"].asCString();
|
||||||
ex_astr server_ip;
|
|
||||||
if (isIPAddress(a_host.c_str()))
|
|
||||||
{
|
|
||||||
server_ip = a_host;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *ptr, **pptr;
|
|
||||||
struct hostent *hptr;
|
|
||||||
char IP[128] = { 0 };
|
|
||||||
/* 取得命令后第一个参数,即要解析的域名或主机名 */
|
|
||||||
ptr = (char*)a_host.c_str();
|
|
||||||
/* 调用gethostbyname()。调用结果都存在hptr中 */
|
|
||||||
if ((hptr = gethostbyname(ptr)) == NULL)
|
|
||||||
{
|
|
||||||
//printf("gethostbyname error for host:%s/n", ptr);
|
|
||||||
_create_json_ret(buf, TPE_PARAM);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* 将主机的规范名打出来 */
|
|
||||||
//printf("official hostname:%s/n", hptr->h_name);
|
|
||||||
/* 主机可能有多个别名,将所有别名分别打出来 */
|
|
||||||
//for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
|
|
||||||
// printf(" alias:%s/n", *pptr);
|
|
||||||
/* 根据地址类型,将地址打出来 */
|
|
||||||
char szbuf[1204] = { 0 };
|
|
||||||
switch (hptr->h_addrtype)
|
|
||||||
{
|
|
||||||
case AF_INET:
|
|
||||||
case AF_INET6:
|
|
||||||
pptr = hptr->h_addr_list;
|
|
||||||
/* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */
|
|
||||||
|
|
||||||
for (; *pptr != NULL; pptr++)
|
char cmd_args[1024] = { 0 };
|
||||||
inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP));
|
ex_strformat(cmd_args, 1023, "%d \"%s\" \"%09d-%s-%s-%s-%s\"", rid, a_sid.c_str(), rid, a_user.c_str(), a_acc.c_str(), a_host.c_str(), a_start.c_str());
|
||||||
server_ip = IP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("unknown address type/n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char szURL[256] = { 0 };
|
|
||||||
sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
|
|
||||||
ex_astr a_url = szURL;
|
|
||||||
ex_wstr w_url;
|
|
||||||
ex_astr2wstr(a_url, w_url);
|
|
||||||
|
|
||||||
char szHost[256] = { 0 };
|
|
||||||
sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
|
|
||||||
|
|
||||||
a_host = szHost;
|
// ex_astr a_host = jsRoot["host"].asCString();
|
||||||
ex_wstr w_host;
|
// int port = jsRoot["port"].asInt();
|
||||||
ex_astr2wstr(a_host, w_host);
|
// ex_astr a_tail = jsRoot["tail"].asCString();
|
||||||
|
// ex_astr server_ip;
|
||||||
|
// if (isIPAddress(a_host.c_str()))
|
||||||
|
// {
|
||||||
|
// server_ip = a_host;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// char *ptr, **pptr;
|
||||||
|
// struct hostent *hptr;
|
||||||
|
// char IP[128] = { 0 };
|
||||||
|
// // 取得命令后第一个参数,即要解析的域名或主机名
|
||||||
|
// ptr = (char*)a_host.c_str();
|
||||||
|
// // 调用gethostbyname()。调用结果都存在hptr中
|
||||||
|
// if ((hptr = gethostbyname(ptr)) == NULL)
|
||||||
|
// {
|
||||||
|
// //printf("gethostbyname error for host:%s/n", ptr);
|
||||||
|
// _create_json_ret(buf, TPE_PARAM);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// // 将主机的规范名打出来
|
||||||
|
// //printf("official hostname:%s/n", hptr->h_name);
|
||||||
|
// // 主机可能有多个别名,将所有别名分别打出来
|
||||||
|
// //for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
|
||||||
|
// // printf(" alias:%s/n", *pptr);
|
||||||
|
// // 根据地址类型,将地址打出来
|
||||||
|
// char szbuf[1204] = { 0 };
|
||||||
|
// switch (hptr->h_addrtype)
|
||||||
|
// {
|
||||||
|
// case AF_INET:
|
||||||
|
// case AF_INET6:
|
||||||
|
// pptr = hptr->h_addr_list;
|
||||||
|
// // 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数
|
||||||
|
//
|
||||||
|
// for (; *pptr != NULL; pptr++)
|
||||||
|
// inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP));
|
||||||
|
// server_ip = IP;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// printf("unknown address type/n");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// char szURL[256] = { 0 };
|
||||||
|
// sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
|
||||||
|
// ex_astr a_url = szURL;
|
||||||
|
ex_wstr w_url_base;
|
||||||
|
ex_astr2wstr(a_url_base, w_url_base);
|
||||||
|
ex_wstr w_cmd_args;
|
||||||
|
ex_astr2wstr(cmd_args, w_cmd_args);
|
||||||
|
|
||||||
|
// char szHost[256] = { 0 };
|
||||||
|
// sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
|
||||||
|
//
|
||||||
|
// a_host = szHost;
|
||||||
|
// ex_wstr w_host;
|
||||||
|
// ex_astr2wstr(a_host, w_host);
|
||||||
|
|
||||||
ex_wstr w_exe_path;
|
ex_wstr w_exe_path;
|
||||||
w_exe_path = _T("\"");
|
w_exe_path = _T("\"");
|
||||||
w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\"");
|
w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\"");
|
||||||
w_exe_path += _T(" ");
|
w_exe_path += _T(" \"");
|
||||||
w_exe_path += w_url;
|
w_exe_path += w_url_base;
|
||||||
|
w_exe_path += _T("\" ");
|
||||||
w_exe_path += _T(" ");
|
w_exe_path += w_cmd_args;
|
||||||
w_exe_path += w_host;
|
|
||||||
|
|
||||||
Json::Value root_ret;
|
Json::Value root_ret;
|
||||||
ex_astr utf8_path;
|
ex_astr utf8_path;
|
||||||
ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8);
|
ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8);
|
||||||
root_ret["path"] = utf8_path;
|
root_ret["cmdline"] = utf8_path;
|
||||||
|
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __TS_HTTP_RPC_H__
|
#ifndef __TS_HTTP_RPC_H__
|
||||||
#define __TS_HTTP_RPC_H__
|
#define __TS_HTTP_RPC_H__
|
||||||
|
|
||||||
|
#include "../../external/mongoose/mongoose.h"
|
||||||
|
|
||||||
#include "ts_const.h"
|
#include "ts_const.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -10,7 +12,6 @@
|
||||||
#include <ex.h>
|
#include <ex.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include "../../external/mongoose/mongoose.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//=================================================================
|
//=================================================================
|
||||||
|
|
|
@ -54,6 +54,9 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
|
||||||
// EXLOGV("\n");
|
// EXLOGV("\n");
|
||||||
return TPE_NETWORK;
|
return TPE_NETWORK;
|
||||||
}
|
}
|
||||||
|
if (body.length() == 0) {
|
||||||
|
return TPE_NETWORK;
|
||||||
|
}
|
||||||
|
|
||||||
Json::Reader jreader;
|
Json::Reader jreader;
|
||||||
Json::Value jret;
|
Json::Value jret;
|
||||||
|
|
|
@ -27,21 +27,11 @@ $app.create_controls = function (cb_stack) {
|
||||||
dom_id: 'table-record',
|
dom_id: 'table-record',
|
||||||
data_source: {
|
data_source: {
|
||||||
type: 'ajax-post'
|
type: 'ajax-post'
|
||||||
,url: '/audit/get-records'
|
, url: '/audit/get-records'
|
||||||
//exclude: {'state': [TP_SESS_STAT_RUNNING, TP_SESS_STAT_STARTED]}
|
//exclude: {'state': [TP_SESS_STAT_RUNNING, TP_SESS_STAT_STARTED]}
|
||||||
},
|
},
|
||||||
column_default: {sort: false, align: 'left'},
|
column_default: {sort: false, align: 'left'},
|
||||||
columns: [
|
columns: [
|
||||||
// {
|
|
||||||
// // title: '<input type="checkbox" id="user-list-select-all" value="">',
|
|
||||||
// title: '<a href="javascript:;" data-reset-filter><i class="fa fa-rotate-left fa-fw"></i></a>',
|
|
||||||
// key: 'chkbox',
|
|
||||||
// sort: false,
|
|
||||||
// width: 36,
|
|
||||||
// align: 'center',
|
|
||||||
// render: 'make_check_box',
|
|
||||||
// fields: {id: 'id'}
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
key: 'id',
|
key: 'id',
|
||||||
|
@ -59,24 +49,17 @@ $app.create_controls = function (cb_stack) {
|
||||||
{
|
{
|
||||||
title: '用户',
|
title: '用户',
|
||||||
key: 'user',
|
key: 'user',
|
||||||
//sort: true,
|
|
||||||
//header_render: 'filter_search_host',
|
|
||||||
render: 'user',
|
render: 'user',
|
||||||
fields: {user_username: 'user_username', user_surname: 'user_surname'}
|
fields: {user_username: 'user_username', user_surname: 'user_surname'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '来源',
|
title: '来源',
|
||||||
key: 'client_ip',
|
key: 'client_ip',
|
||||||
//sort: true,
|
|
||||||
//header_render: 'filter_search_host',
|
|
||||||
//render: 'host_info',
|
|
||||||
fields: {client_ip: 'client_ip'}
|
fields: {client_ip: 'client_ip'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '远程连接',
|
title: '远程连接',
|
||||||
key: 'remote',
|
key: 'remote',
|
||||||
//sort: true,
|
|
||||||
//header_render: 'filter_search_host',
|
|
||||||
render: 'remote',
|
render: 'remote',
|
||||||
fields: {acc_username: 'acc_username', host_ip: 'host_ip', conn_ip: 'conn_ip', conn_port: 'conn_port'}
|
fields: {acc_username: 'acc_username', host_ip: 'host_ip', conn_ip: 'conn_ip', conn_port: 'conn_port'}
|
||||||
},
|
},
|
||||||
|
@ -85,10 +68,6 @@ $app.create_controls = function (cb_stack) {
|
||||||
key: 'protocol_type',
|
key: 'protocol_type',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 80,
|
width: 80,
|
||||||
// align: 'center',
|
|
||||||
// width: 36,
|
|
||||||
//sort: true
|
|
||||||
// header_render: 'filter_os',
|
|
||||||
render: 'protocol',
|
render: 'protocol',
|
||||||
fields: {protocol_type: 'protocol_type', protocol_sub_type: 'protocol_sub_type'}
|
fields: {protocol_type: 'protocol_type', protocol_sub_type: 'protocol_sub_type'}
|
||||||
},
|
},
|
||||||
|
@ -125,12 +104,12 @@ $app.create_controls = function (cb_stack) {
|
||||||
render: 'record_action',
|
render: 'record_action',
|
||||||
fields: {id: 'id', state: 'state', time_end: 'time_end', protocol_sub_type: 'protocol_sub_type'}
|
fields: {id: 'id', state: 'state', time_end: 'time_end', protocol_sub_type: 'protocol_sub_type'}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
|
|
||||||
// 重载回调函数
|
// 重载回调函数
|
||||||
on_header_created: $app.on_table_host_header_created,
|
//,on_header_created: $app.on_table_host_header_created
|
||||||
on_render_created: $app.on_table_host_render_created,
|
, on_render_created: $app.on_table_host_render_created
|
||||||
on_cell_created: $app.on_table_host_cell_created
|
, on_cell_created: $app.on_table_host_cell_created
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.table_record = $tp.create_table(table_record_options);
|
$app.table_record = $tp.create_table(table_record_options);
|
||||||
|
@ -141,10 +120,10 @@ $app.create_controls = function (cb_stack) {
|
||||||
//-------------------------------
|
//-------------------------------
|
||||||
// 用户列表相关过滤器
|
// 用户列表相关过滤器
|
||||||
//-------------------------------
|
//-------------------------------
|
||||||
$tp.create_table_header_filter_search($app.table_record, {
|
// $tp.create_table_header_filter_search($app.table_record, {
|
||||||
name: 'search',
|
// name: 'search',
|
||||||
place_holder: '搜索:主机IP/名称/描述/资产编号/等等...'
|
// place_holder: '搜索:主机IP/名称/描述/资产编号/等等...'
|
||||||
});
|
// });
|
||||||
// $app.table_record_role_filter = $tp.create_table_filter_role($app.table_record, $app.role_list);
|
// $app.table_record_role_filter = $tp.create_table_filter_role($app.table_record, $app.role_list);
|
||||||
// $tp.create_table_header_filter_state($app.table_record, 'state', $app.obj_states, [TP_STATE_LOCKED]);
|
// $tp.create_table_header_filter_state($app.table_record, 'state', $app.obj_states, [TP_STATE_LOCKED]);
|
||||||
// 从cookie中读取用户分页限制的选择
|
// 从cookie中读取用户分页限制的选择
|
||||||
|
@ -168,11 +147,12 @@ $app.create_controls = function (cb_stack) {
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
$app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||||
if (col_key === 'chkbox') {
|
// if (col_key === 'chkbox') {
|
||||||
cell_obj.find('[data-check-box]').click(function () {
|
// cell_obj.find('[data-check-box]').click(function () {
|
||||||
$app.check_host_all_selected();
|
// $app.check_host_all_selected();
|
||||||
});
|
// });
|
||||||
} else if (col_key === 'action') {
|
// } else
|
||||||
|
if (col_key === 'action') {
|
||||||
// 绑定系统选择框事件
|
// 绑定系统选择框事件
|
||||||
cell_obj.find('[data-action]').click(function () {
|
cell_obj.find('[data-action]').click(function () {
|
||||||
|
|
||||||
|
@ -183,7 +163,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||||
if (action === 'replay') {
|
if (action === 'replay') {
|
||||||
//$app.dlg_edit_host.show_edit(row_id);
|
//$app.dlg_edit_host.show_edit(row_id);
|
||||||
if (row_data.protocol_type === TP_PROTOCOL_TYPE_RDP) {
|
if (row_data.protocol_type === TP_PROTOCOL_TYPE_RDP) {
|
||||||
$tp.notify_error('sorry, not impl.');
|
// $tp.notify_error('sorry, not impl.');
|
||||||
|
$app.do_replay_rdp(row_data.id, row_data.user_username, row_data.acc_username, row_data.host_ip, row_data.time_begin);
|
||||||
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) {
|
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) {
|
||||||
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
|
||||||
}
|
}
|
||||||
|
@ -206,36 +187,36 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.on_table_host_render_created = function (render) {
|
$app.on_table_host_render_created = function (render) {
|
||||||
render.filter_host_state = function (header, title, col) {
|
// render.filter_host_state = function (header, title, col) {
|
||||||
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
// var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||||
_ret.push('<div class="tp-table-filter-inner">');
|
// _ret.push('<div class="tp-table-filter-inner">');
|
||||||
_ret.push('<div class="search-title">' + title + '</div>');
|
// _ret.push('<div class="search-title">' + title + '</div>');
|
||||||
|
//
|
||||||
|
// // 表格内嵌过滤器的DOM实体在这时生成
|
||||||
|
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
|
||||||
|
// _ret.push(filter_ctrl.render());
|
||||||
|
//
|
||||||
|
// _ret.push('</div></div>');
|
||||||
|
//
|
||||||
|
// return _ret.join('');
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// render.filter_search_host = function (header, title, col) {
|
||||||
|
// var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
|
||||||
|
// _ret.push('<div class="tp-table-filter-inner">');
|
||||||
|
// _ret.push('<div class="search-title">' + title + '</div>');
|
||||||
|
//
|
||||||
|
// // 表格内嵌过滤器的DOM实体在这时生成
|
||||||
|
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
|
||||||
|
// _ret.push(filter_ctrl.render());
|
||||||
|
//
|
||||||
|
// _ret.push('</div></div>');
|
||||||
|
//
|
||||||
|
// return _ret.join('');
|
||||||
|
// };
|
||||||
|
|
||||||
// 表格内嵌过滤器的DOM实体在这时生成
|
render.sid = function (row_id, fields) {
|
||||||
var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
|
return '<span class="mono">' + fields.sid + '</span>';
|
||||||
_ret.push(filter_ctrl.render());
|
|
||||||
|
|
||||||
_ret.push('</div></div>');
|
|
||||||
|
|
||||||
return _ret.join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
render.filter_search_host = function (header, title, col) {
|
|
||||||
var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
|
|
||||||
_ret.push('<div class="tp-table-filter-inner">');
|
|
||||||
_ret.push('<div class="search-title">' + title + '</div>');
|
|
||||||
|
|
||||||
// 表格内嵌过滤器的DOM实体在这时生成
|
|
||||||
var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
|
|
||||||
_ret.push(filter_ctrl.render());
|
|
||||||
|
|
||||||
_ret.push('</div></div>');
|
|
||||||
|
|
||||||
return _ret.join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
render.sid = function(row_id, fields) {
|
|
||||||
return '<span class="mono">'+fields.sid+'</span>';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render.user = function (row_id, fields) {
|
render.user = function (row_id, fields) {
|
||||||
|
@ -270,7 +251,6 @@ $app.on_table_host_render_created = function (render) {
|
||||||
};
|
};
|
||||||
|
|
||||||
render.time_begin = function (row_id, fields) {
|
render.time_begin = function (row_id, fields) {
|
||||||
// return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
|
|
||||||
return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
|
return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,60 +353,84 @@ $app.on_table_host_render_created = function (render) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.on_table_host_header_created = function (header) {
|
$app.do_replay_rdp = function (record_id, user_username, acc_username, host_ip, time_begin) {
|
||||||
$('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
|
$assist.do_rdp_replay(
|
||||||
CALLBACK_STACK.create()
|
{
|
||||||
.add(header._table_ctrl.load_data)
|
rid: record_id
|
||||||
.add(header._table_ctrl.reset_filters)
|
// , web: $tp.web_server // + '/audit/get_rdp_record/' + record_id // 'http://' + ip + ':' + port + '/log/replay/rdp/' + record_id;
|
||||||
.exec();
|
// , sid: Cookies.get('_sid')
|
||||||
});
|
, user: user_username
|
||||||
|
, acc: acc_username
|
||||||
// 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
|
, host: host_ip
|
||||||
header._table_ctrl.get_filter_ctrl('search').on_created();
|
, start: time_begin//tp_format_datetime(tp_utc2local(time_begin), 'yyyyMMdd-HHmmss')
|
||||||
};
|
|
||||||
|
|
||||||
$app.get_selected_record = function (tbl) {
|
|
||||||
var records = [];
|
|
||||||
var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
|
|
||||||
$.each(_objs, function (i, _obj) {
|
|
||||||
if ($(_obj).is(':checked')) {
|
|
||||||
var _row_data = tbl.get_row(_obj);
|
|
||||||
records.push(_row_data.id);
|
|
||||||
}
|
}
|
||||||
});
|
, function () {
|
||||||
return records;
|
// func_success
|
||||||
|
}
|
||||||
|
, function (code, message) {
|
||||||
|
if (code === TPE_NO_ASSIST)
|
||||||
|
$assist.alert_assist_not_found();
|
||||||
|
else
|
||||||
|
$tp.notify_error('播放RDP操作录像失败:' + tp_error_msg(code, message));
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.on_btn_remove_record_click = function () {
|
|
||||||
// var records = $app.get_selected_record($app.table_record);
|
// $app.on_table_host_header_created = function (header) {
|
||||||
// if (records.length === 0) {
|
// $('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
|
||||||
// $tp.notify_error('请选择要删除的会话记录!');
|
// CALLBACK_STACK.create()
|
||||||
// return;
|
// .add(header._table_ctrl.load_data)
|
||||||
// }
|
// .add(header._table_ctrl.reset_filters)
|
||||||
//
|
// .exec();
|
||||||
// var _fn_sure = function (cb_stack, cb_args) {
|
// });
|
||||||
// $tp.ajax_post_json('/user/remove-user', {users: users},
|
//
|
||||||
// function (ret) {
|
// // 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
|
||||||
// if (ret.code === TPE_OK) {
|
// header._table_ctrl.get_filter_ctrl('search').on_created();
|
||||||
// cb_stack.add($app.check_host_all_selected);
|
// };
|
||||||
// cb_stack.add($app.table_record.load_data);
|
|
||||||
// $tp.notify_success('删除用户账号操作成功!');
|
// $app.get_selected_record = function (tbl) {
|
||||||
// } else {
|
// var records = [];
|
||||||
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message));
|
// var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
|
||||||
// }
|
// $.each(_objs, function (i, _obj) {
|
||||||
//
|
// if ($(_obj).is(':checked')) {
|
||||||
// cb_stack.exec();
|
// var _row_data = tbl.get_row(_obj);
|
||||||
// },
|
// records.push(_row_data.id);
|
||||||
// function () {
|
// }
|
||||||
// $tp.notify_error('网络故障,删除用户账号操作失败!');
|
// });
|
||||||
// cb_stack.exec();
|
// return records;
|
||||||
// }
|
// };
|
||||||
// );
|
|
||||||
// };
|
// $app.on_btn_remove_record_click = function () {
|
||||||
//
|
// var records = $app.get_selected_record($app.table_record);
|
||||||
// var cb_stack = CALLBACK_STACK.create();
|
// if (records.length === 0) {
|
||||||
// $tp.dlg_confirm(cb_stack, {
|
// $tp.notify_error('请选择要删除的会话记录!');
|
||||||
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>',
|
// return;
|
||||||
// fn_yes: _fn_sure
|
// }
|
||||||
// });
|
//
|
||||||
};
|
// var _fn_sure = function (cb_stack, cb_args) {
|
||||||
|
// $tp.ajax_post_json('/user/remove-user', {users: users},
|
||||||
|
// function (ret) {
|
||||||
|
// if (ret.code === TPE_OK) {
|
||||||
|
// cb_stack.add($app.check_host_all_selected);
|
||||||
|
// cb_stack.add($app.table_record.load_data);
|
||||||
|
// $tp.notify_success('删除用户账号操作成功!');
|
||||||
|
// } else {
|
||||||
|
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// cb_stack.exec();
|
||||||
|
// },
|
||||||
|
// function () {
|
||||||
|
// $tp.notify_error('网络故障,删除用户账号操作失败!');
|
||||||
|
// cb_stack.exec();
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// var cb_stack = CALLBACK_STACK.create();
|
||||||
|
// $tp.dlg_confirm(cb_stack, {
|
||||||
|
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>',
|
||||||
|
// fn_yes: _fn_sure
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
|
@ -53,13 +53,11 @@ var CALLBACK_STACK = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// console.log(window.location, window.location.protocol+'://'+window.location.host);
|
// console.log(window.location, window.location.protocol+'://'+window.location.host);
|
||||||
|
|
||||||
|
|
||||||
// Teleport核心JS
|
// Teleport核心JS
|
||||||
var $tp = {
|
var $tp = {
|
||||||
web_server: window.location.protocol+'://'+window.location.host
|
web_server: window.location.protocol+'//'+window.location.host
|
||||||
|
|
||||||
// Teleport页面应用对象,放置页面自身特有的属性和函数
|
// Teleport页面应用对象,放置页面自身特有的属性和函数
|
||||||
, app: {
|
, app: {
|
||||||
|
@ -79,28 +77,6 @@ $tp.init = function () {
|
||||||
{id: TP_STATE_LOCKED, name: '临时锁定', style: 'warning'}
|
{id: TP_STATE_LOCKED, name: '临时锁定', style: 'warning'}
|
||||||
];
|
];
|
||||||
|
|
||||||
// $app.user_states = [
|
|
||||||
// {id: 1, name: '正常', style: 'success'},
|
|
||||||
// {id: 2, name: '临时锁定', style: 'warning'},
|
|
||||||
// {id: 3, name: '禁用', style: 'danger'}
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// $app.acc_states = [
|
|
||||||
// {id: 1, name: '正常', style: 'success'},
|
|
||||||
// {id: 2, name: '临时锁定', style: 'warning'},
|
|
||||||
// {id: 3, name: '禁用', style: 'danger'}
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// $app.host_states = [
|
|
||||||
// {id: 1, name: '正常', style: 'success'},
|
|
||||||
// {id: 2, name: '禁用', style: 'danger'}
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// $app.policy_states = [
|
|
||||||
// {id: 1, name: '正常', style: 'success'},
|
|
||||||
// {id: 2, name: '禁用', style: 'danger'}
|
|
||||||
// ];
|
|
||||||
|
|
||||||
$app.host_types = [
|
$app.host_types = [
|
||||||
{id: 1, name: '物理主机', style: 'success'},
|
{id: 1, name: '物理主机', style: 'success'},
|
||||||
{id: 2, name: '虚拟主机', style: 'info'},
|
{id: 2, name: '虚拟主机', style: 'info'},
|
||||||
|
|
|
@ -839,7 +839,8 @@ $tp.create_table_header = function (tbl, on_created) {
|
||||||
|
|
||||||
if (_.isFunction(on_created))
|
if (_.isFunction(on_created))
|
||||||
on_created(_tbl_header);
|
on_created(_tbl_header);
|
||||||
else if (!_.isUndefined(on_created))
|
//else if (!_.isUndefined(on_created))
|
||||||
|
else if (!_.isNull(on_created))
|
||||||
console.error('create table header, on_created() is not callable.');
|
console.error('create table header, on_created() is not callable.');
|
||||||
|
|
||||||
cb_stack.exec();
|
cb_stack.exec();
|
||||||
|
|
|
@ -27,7 +27,7 @@ $assist.init = function (cb_stack) {
|
||||||
$assist.running = true;
|
$assist.running = true;
|
||||||
$assist.version = ret.version;
|
$assist.version = ret.version;
|
||||||
|
|
||||||
if(_.isFunction($tp.assist_checked)) {
|
if (_.isFunction($tp.assist_checked)) {
|
||||||
$tp.assist_checked();
|
$tp.assist_checked();
|
||||||
}
|
}
|
||||||
// if (version_compare()) {
|
// if (version_compare()) {
|
||||||
|
@ -38,7 +38,7 @@ $assist.init = function (cb_stack) {
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
$assist.running = false;
|
$assist.running = false;
|
||||||
if(_.isFunction($tp.assist_checked)) {
|
if (_.isFunction($tp.assist_checked)) {
|
||||||
$tp.assist_checked();
|
$tp.assist_checked();
|
||||||
}
|
}
|
||||||
// func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
// func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||||
|
@ -120,7 +120,7 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
||||||
jsonp: 'callback',
|
jsonp: 'callback',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (ret) {
|
success: function (ret) {
|
||||||
if(ret.code === TPE_OK) {
|
if (ret.code === TPE_OK) {
|
||||||
func_success();
|
func_success();
|
||||||
} else {
|
} else {
|
||||||
func_error(ret.code, ret.message);
|
func_error(ret.code, ret.message);
|
||||||
|
@ -144,6 +144,45 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$assist.do_rdp_replay = function (args, func_success, func_error) {
|
||||||
|
// ==================================================
|
||||||
|
// args is dict with fields shown below:
|
||||||
|
// rid: (int) - record-id in database.
|
||||||
|
// user: (string) - who did the RDP connection.
|
||||||
|
// acc: (string) - account to login to remote RDP server.
|
||||||
|
// host: (string) - IP of the remote RDP server.
|
||||||
|
// start: (string) - when start the RDP connection, should be a UTC timestamp.
|
||||||
|
// ==================================================
|
||||||
|
|
||||||
|
// now fix the args.
|
||||||
|
args.web = $tp.web_server; // (string) - teleport server base address, like "http://127.0.0.1:7190", without end-slash.
|
||||||
|
args.sid = Cookies.get('_sid'); // (string) - current login user's session-id.
|
||||||
|
args.start = tp_format_datetime(tp_utc2local(args.start), 'yyyyMMdd-HHmmss'); // (string) - convert UTC timestamp to local human-readable string.
|
||||||
|
|
||||||
|
console.log('do-rdp-replay:', args);
|
||||||
|
|
||||||
|
var args_ = encodeURIComponent(JSON.stringify(args));
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
timeout: 6000,
|
||||||
|
url: $assist.api_url + '/rdp_play/' + args_,
|
||||||
|
jsonp: 'callback',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (ret) {
|
||||||
|
console.log('ret', ret);
|
||||||
|
if (ret.code === TPE_OK) {
|
||||||
|
func_success();
|
||||||
|
} else {
|
||||||
|
// func_error(ret.code, '查看远程桌面操作录像失败!');
|
||||||
|
func_error(ret.code, ret.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
func_error(TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
var version_compare = function () {
|
var version_compare = function () {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<%inherit file="../page_base.mako"/>
|
<%inherit file="../page_base.mako"/>
|
||||||
|
|
||||||
<%block name="extend_js_file">
|
<%block name="extend_js_file">
|
||||||
|
<script type="text/javascript" src="${ static_url('js/tp-assist.js') }"></script>
|
||||||
<script type="text/javascript" src="${ static_url('js/audit/record-list.js') }"></script>
|
<script type="text/javascript" src="${ static_url('js/audit/record-list.js') }"></script>
|
||||||
</%block>
|
</%block>
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,9 @@ controllers = [
|
||||||
# - [json] 读取录像数据
|
# - [json] 读取录像数据
|
||||||
(r'/audit/get-record-data', audit.DoGetRecordDataHandler),
|
(r'/audit/get-record-data', audit.DoGetRecordDataHandler),
|
||||||
|
|
||||||
|
# - 读取录像文件(用于RDP录像回放)
|
||||||
|
(r'/audit/get-file', audit.DoGetFileHandler),
|
||||||
|
|
||||||
# (r'/host/export-host', host.ExportHostHandler),
|
# (r'/host/export-host', host.ExportHostHandler),
|
||||||
# (r'/config/export-database', config.ExportDatabaseHandler),
|
# (r'/config/export-database', config.ExportDatabaseHandler),
|
||||||
# (r'/config/import-database', config.ImportDatabaseHandler),
|
# (r'/config/import-database', config.ImportDatabaseHandler),
|
||||||
|
|
|
@ -274,3 +274,82 @@ class DoGetRecordDataHandler(TPBaseJsonHandler):
|
||||||
|
|
||||||
data_list, data_size, err = record.read_record_data(record_id, offset)
|
data_list, data_size, err = record.read_record_data(record_id, offset)
|
||||||
self.write_json(err, data={'data_list': data_list, 'data_size': data_size})
|
self.write_json(err, data={'data_list': data_list, 'data_size': data_size})
|
||||||
|
|
||||||
|
|
||||||
|
class DoGetFileHandler(TPBaseHandler):
|
||||||
|
@tornado.gen.coroutine
|
||||||
|
def get(self):
|
||||||
|
|
||||||
|
log.v('--{}\n'.format(self.request.uri))
|
||||||
|
|
||||||
|
require_privilege = TP_PRIVILEGE_OPS | TP_PRIVILEGE_OPS_AUZ | TP_PRIVILEGE_AUDIT_AUZ | TP_PRIVILEGE_AUDIT_OPS_HISTORY
|
||||||
|
|
||||||
|
# sid = self.get_argument('sid', None)
|
||||||
|
# if sid is None:
|
||||||
|
# self.set_status(403)
|
||||||
|
# return self.write('need login first.')
|
||||||
|
#
|
||||||
|
# self._s_id = sid
|
||||||
|
# _user = self.get_session('user')
|
||||||
|
# if _user is None:
|
||||||
|
# self.set_status(403)
|
||||||
|
# return self.write('need login first.')
|
||||||
|
# self._user = _user
|
||||||
|
|
||||||
|
if not self._user['_is_login']:
|
||||||
|
self.set_status(401) # 401=未授权, 要求身份验证
|
||||||
|
return self.write('need login first.')
|
||||||
|
if (self._user['privilege'] & require_privilege) == 0:
|
||||||
|
self.set_status(403) # 403=禁止
|
||||||
|
return self.write('you have no such privilege.')
|
||||||
|
|
||||||
|
act = self.get_argument('act', None)
|
||||||
|
_type = self.get_argument('type', None)
|
||||||
|
rid = self.get_argument('rid', None)
|
||||||
|
filename = self.get_argument('f', None)
|
||||||
|
offset = int(self.get_argument('offset', '0'))
|
||||||
|
length = int(self.get_argument('length', '-1')) # -1 means read all content.
|
||||||
|
if act is None or _type is None or rid is None or filename is None:
|
||||||
|
self.set_status(400) # 400=错误请求
|
||||||
|
return self.write('invalid param, `rid` and `f` must present.')
|
||||||
|
|
||||||
|
if act not in ['size', 'read']:
|
||||||
|
self.set_status(400)
|
||||||
|
return self.write('invalid param, `act` should be `size` or `read`.')
|
||||||
|
if _type not in ['rdp', 'ssh', 'telnet']:
|
||||||
|
self.set_status(400)
|
||||||
|
return self.write('invalid param, `type` should be `rdp`, `ssh` or `telnet`.')
|
||||||
|
|
||||||
|
file = os.path.join(get_cfg().core.replay_path, 'rdp', '{:09d}'.format(int(rid)), filename)
|
||||||
|
if not os.path.exists(file):
|
||||||
|
self.set_status(404)
|
||||||
|
return self.write('file does not exists.')
|
||||||
|
|
||||||
|
file_size = os.path.getsize(file)
|
||||||
|
|
||||||
|
if act == 'size':
|
||||||
|
log.d('--return size:{}\n'.format(file_size))
|
||||||
|
return self.write('{}'.format(file_size))
|
||||||
|
|
||||||
|
if offset >= file_size:
|
||||||
|
self.set_status(416) # 416=请求范围不符合要求
|
||||||
|
return self.write('no more data.')
|
||||||
|
|
||||||
|
# we read most 4096 bytes one time.
|
||||||
|
BULK_SIZE = 4096
|
||||||
|
total_need = file_size - offset
|
||||||
|
if length != -1 and length < total_need:
|
||||||
|
total_need = length
|
||||||
|
total_read = 0
|
||||||
|
with open(file, 'rb') as f:
|
||||||
|
f.seek(offset)
|
||||||
|
read_this_time = BULK_SIZE if total_need > BULK_SIZE else total_need
|
||||||
|
while read_this_time > 0:
|
||||||
|
self.write(f.read(read_this_time))
|
||||||
|
total_read += read_this_time
|
||||||
|
if total_read >= total_need:
|
||||||
|
break
|
||||||
|
read_left = total_need - total_read
|
||||||
|
read_this_time = BULK_SIZE if read_left > BULK_SIZE else read_left
|
||||||
|
|
||||||
|
# all need data read.
|
||||||
|
|
Loading…
Reference in New Issue