diff --git a/client/tp_assist/ts_const.h b/client/tp_assist/ts_const.h index 00da1ca..3aa16c9 100644 --- a/client/tp_assist/ts_const.h +++ b/client/tp_assist/ts_const.h @@ -1,11 +1,12 @@ -#ifndef __TS_CONST_H__ -#define __TS_CONST_H__ - -#define TS_WEB_URL L"http://teleport.eomsoft.net/" -#define TS_BBS_URL L"http://bbs.eomsoft.net/" -#define TS_TRAY_MSG L"Teleport助手正常工作中" - -#define TS_HTTP_RPC_PORT 50022 -#define TS_HTTP_RPC_HOST "127.0.0.1" - -#endif // __TS_CONST_H__ +#ifndef __TS_CONST_H__ +#define __TS_CONST_H__ + +#define TS_WEB_URL L"http://teleport.eomsoft.net/" +#define TS_BBS_URL L"http://bbs.eomsoft.net/" +#define TS_TRAY_MSG L"Teleport助手正常工作中" + +#define TS_HTTP_RPC_PORT 50022 +//#define TS_HTTP_RPC_HOST "127.0.0.1" +#define TS_HTTP_RPC_HOST "localhost" + +#endif // __TS_CONST_H__ diff --git a/client/tp_assist/ts_http_rpc.cpp b/client/tp_assist/ts_http_rpc.cpp index 012ed45..1f6e88a 100644 --- a/client/tp_assist/ts_http_rpc.cpp +++ b/client/tp_assist/ts_http_rpc.cpp @@ -1,1590 +1,1591 @@ -#include "stdafx.h" - -#pragma warning(disable:4091) - -#include -#include - -#include - -#include "ts_http_rpc.h" -#include "dlg_main.h" -#include "ts_ver.h" - -/* -1. -SecureCRT支持设置标签页的标题,命令行参数 /N "tab name"就可以 -Example: -To launch a new Telnet session, displaying the name "Houston, TX" on the tab, use the following: -/T /N "Houston, TX" /TELNET 192.168.0.6 - -2. -多次启动的SecureCRT放到一个窗口的不同标签页中,使用参数: /T - SecureCRT.exe /T /N "TP#ssh://192.168.1.3" /SSH2 /L root /PASSWORD 1234 120.26.109.25 - -3. -telnet客户端的启动: - putty.exe telnet://administrator@127.0.0.1:52389 -如果是SecureCRT,则需要 - SecureCRT.exe /T /N "TP#telnet://192.168.1.3" /SCRIPT X:\path\to\startup.vbs /TELNET 127.0.0.1 52389 -其中,startup.vbs的内容为: ----------文件开始--------- -#$language = "VBScript" -#$interface = "1.0" -Sub main - crt.Screen.Synchronous = True - crt.Screen.WaitForString "ogin: " - crt.Screen.Send "SESSION-ID" & VbCr - crt.Screen.Synchronous = False -End Sub ----------文件结束--------- - -4. 为了让putty的窗口标签显示正常的IP,可以尝试在连接成功后,主动向服务端发送下列命令: - PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@192.168.1.2: \w\a\]$PS1" -手工测试了,ubuntu服务器可以,不知道是否能够支持所有的Linux。SecureCRT对此表示忽略。 -*/ - -// #define RDP_CLIENT_SYSTEM_BUILTIN -// #define RDP_CLIENT_SYSTEM_ACTIVE_CONTROL -#define RDP_CLIENT_FREERDP - - -#ifdef RDP_CLIENT_SYSTEM_BUILTIN -#include -#pragma comment(lib, "Crypt32.lib") - -std::string rdp_content = "\ -connect to console:i:%d\n\ -screen mode id:i:%d\n\ -desktopwidth:i:%d\n\ -desktopheight:i:%d\n\ -winposstr:s:0,1,%d,%d,%d,%d\n\ -full address:s:%s:%d\n\ -username:s:%s\n\ -prompt for credentials:i:0\n\ -use multimon:i:0\n\ -authentication level:i:3\n\ -session bpp:i:16\n\ -compression:i:1\n\ -keyboardhook:i:2\n\ -audiocapturemode:i:0\n\ -negotiate security layer:i:1\n\ -videoplaybackmode:i:1\n\ -connection type:i:2\n\ -prompt for credentials on client:i:0\n\ -displayconnectionbar:i:1\n\ -disable wallpaper:i:1\n\ -allow font smoothing:i:0\n\ -allow desktop composition:i:0\n\ -disable full window drag:i:1\n\ -disable menu anims:i:1\n\ -disable themes:i:1\n\ -disable cursor setting:i:0\n\ -bitmapcachepersistenable:i:1\n\ -audiomode:i:0\n\ -redirectprinters:i:0\n\ -redirectcomports:i:0\n\ -redirectsmartcards:i:0\n\ -redirectclipboard:i:1\n\ -redirectposdevices:i:0\n\ -redirectdirectx:i:0\n\ -autoreconnection enabled:i:0\n\ -drivestoredirect:s:*\n\ -password 51:b:%s\n\ -"; - -//password 51:b:01000000D08C9DDF0115D1118C7A00C04FC297EB0100000052A9E191EA75A948B359790578C9371A0000000008000000700073007700000003660000A8000000100000000A1DCCD2E50775CA25EC3857164B34DC0000000004800000A000000010000000FCE1A645B9B61AA450946BB6F955058108020000D83591CA47562D6DDAA689F050AE145039EBE22E00D1D3AEAA98373C7B63C3E8E7149072DF989EA43EFCE20513AD3D27B11BE7F17066A688E1DCE828AF85460AAC327B38E90776DB962888E4393D19637578984B19A187AAD95F6D2726ADE7DD315FF56C15FF5B3031014EDDCC3C24D1B81779AFDB006EE575F5BEFB8D2D2138D9D9D642BBB251CC5ED7226968764856EC660A646BACE748A13D6002A9A537AA70710615650B9387EED66DE28BD57B304BBDD7B581B943DA628EB0289E30A8BA784B76F7885BECCAB4FEF7820E97EE3C6E036EEAF6EAA669288DF2FCACC9BEC045C907EBBDE87AFB8CC6B07A600BD63AC891B61D95C2265DD9FD5E635D61BFBF5EDC28311375066611C610FB533D64515B643C82F57D9B183B05C156D91BC0974D38E546022B139E82452E6F1EDF76E52F732C3904E5E433F8F3D488DB0698427DBB0791A9F207F8CB6654CB8410BAF4A59C4F9E821E589ABC1E6E6E1D432181B690408F6884FE1007895A4D26D4A5A2C7458EE747DA35D44AC9FB08AB5477EA3E7CCDB3E37EE20FAFD0D0CF9584E420598B7003B347943AC28048F45E0FD21AD08148FFADCE0E7877219259A7BE722FFAE845A429BA2CF0A71F2D19EA7495530FABDB5106E8D404A38A7E6394C38457640EA7398C5D55F0C4D342CC6A39C77E10A2A5145AEA40B14F5C7C3760334D83C9BE748383FADE231248537353817D51F7B44F61B406ABC61400000071C354139F458B02D978015F785B97F7F6B307380\n\ -//password 51:b:01000000"; - -#endif - - -TsHttpRpc g_http_interface; - -void http_rpc_main_loop(void) -{ - if (!g_http_interface.init(TS_HTTP_RPC_HOST, TS_HTTP_RPC_PORT)) - { - EXLOGE("[ERROR] can not start HTTP-RPC listener, maybe port %d is already in use.\n", TS_HTTP_RPC_PORT); - return; - } - - EXLOGW("======================================================\n"); - EXLOGW("[rpc] TeleportAssist-HTTP-RPC ready on %s:%d\n", TS_HTTP_RPC_HOST, TS_HTTP_RPC_PORT); - - g_http_interface.run(); - - EXLOGW("[rpc] main loop end.\n"); -} - -void http_rpc_stop(void) -{ - g_http_interface.stop(); -} - -#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') - -int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded) -{ - int i, j, a, b; - - for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) - { - if (src[i] == '%') - { - if (i < src_len - 2 && isxdigit(*(const unsigned char *)(src + i + 1)) && - isxdigit(*(const unsigned char *)(src + i + 2))) { - a = tolower(*(const unsigned char *)(src + i + 1)); - b = tolower(*(const unsigned char *)(src + i + 2)); - dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b)); - i += 2; - } - else - { - return -1; - } - } - else if (is_form_url_encoded && src[i] == '+') - { - dst[j] = ' '; - } - else - { - dst[j] = src[i]; - } - } - - dst[j] = '\0'; /* Null-terminate the destination */ - - return i >= src_len ? j : -1; -} - -#ifdef RDP_CLIENT_SYSTEM_BUILTIN -bool calc_psw51b(const char* password, std::string& ret) -{ - DATA_BLOB DataIn; - DATA_BLOB DataOut; - - ex_wstr w_pswd; - ex_astr2wstr(password, w_pswd, EX_CODEPAGE_ACP); - - DataIn.cbData = w_pswd.length() * sizeof(wchar_t); - DataIn.pbData = (BYTE*)w_pswd.c_str(); - - - if (!CryptProtectData(&DataIn, L"psw", NULL, NULL, NULL, 0, &DataOut)) - return false; - - char szRet[5] = {0}; - for (int i = 0; i < DataOut.cbData; ++i) - { - sprintf_s(szRet, 5, "%02X", DataOut.pbData[i]); - ret += szRet; - } - - LocalFree(DataOut.pbData); - return true; -} -#endif - -TsHttpRpc::TsHttpRpc() -{ - m_stop = false; - mg_mgr_init(&m_mg_mgr, NULL); -} - -TsHttpRpc::~TsHttpRpc() -{ - mg_mgr_free(&m_mg_mgr); -} - -bool TsHttpRpc::init(const char* ip, int port) -{ - char file_name[MAX_PATH] = { 0 }; - if (!GetModuleFileNameA(NULL, file_name, MAX_PATH)) - return false; - - int len = strlen(file_name); - - if (file_name[len] == '\\') - { - file_name[len] = '\0'; - } - char* match = strrchr(file_name, '\\'); - if (match != NULL) - { - *match = '\0'; - } - - struct mg_connection* nc = NULL; - - char addr[128] = { 0 }; - if (0 == strcmp(ip, "127.0.0.1") || 0 == strcmp(ip, "localhost")) - sprintf_s(addr, 128, ":%d", port); - else - sprintf_s(addr, 128, "%s:%d", ip, port); - - nc = mg_bind(&m_mg_mgr, addr, _mg_event_handler); - if (nc == NULL) - { - EXLOGE("[rpc] TsHttpRpc::init %s:%d\n", ip, port); - return false; - } - nc->user_data = this; - - mg_set_protocol_http_websocket(nc); - - m_content_type_map[".js"] = "application/javascript"; - m_content_type_map[".png"] = "image/png"; - m_content_type_map[".jpeg"] = "image/jpeg"; - m_content_type_map[".jpg"] = "image/jpeg"; - m_content_type_map[".gif"] = "image/gif"; - m_content_type_map[".ico"] = "image/x-icon"; - m_content_type_map[".json"] = "image/json"; - m_content_type_map[".html"] = "text/html"; - m_content_type_map[".css"] = "text/css"; - m_content_type_map[".tif"] = "image/tiff"; - m_content_type_map[".tiff"] = "image/tiff"; - m_content_type_map[".svg"] = "text/html"; - - return true; -} - -void TsHttpRpc::run(void) -{ - while(!m_stop) - { - mg_mgr_poll(&m_mg_mgr, 500); - } -} - -void TsHttpRpc::stop(void) -{ - m_stop = true; -} - -void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_data) -{ - struct http_message *hm = (struct http_message*)ev_data; - - TsHttpRpc* _this = (TsHttpRpc*)nc->user_data; - if (NULL == _this) - { - EXLOGE("[ERROR] invalid http request.\n"); - return; - } - - switch (ev) - { - case MG_EV_HTTP_REQUEST: - { - ex_astr uri; - ex_chars _uri; - _uri.resize(hm->uri.len + 1); - memset(&_uri[0], 0, hm->uri.len + 1); - memcpy(&_uri[0], hm->uri.p, hm->uri.len); - uri = &_uri[0]; - -#ifdef EX_DEBUG - char* dbg_method = NULL; - if (hm->method.len == 3 && 0 == memcmp(hm->method.p, "GET", hm->method.len)) - dbg_method = "GET"; - else if (hm->method.len == 4 && 0 == memcmp(hm->method.p, "POST", hm->method.len)) - dbg_method = "POST"; - else - dbg_method = "UNSUPPORTED-HTTP-METHOD"; - - EXLOGV("[rpc] got %s request: %s\n", dbg_method, uri.c_str()); -#endif - ex_astr ret_buf; - bool b_is_index = false; - - if (uri == "/") - { - ex_wstr page = L"Teleport助手\n\n
Teleport助手工作正常!
"; - ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); - - mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); - nc->flags |= MG_F_SEND_AND_CLOSE; - return; - } - else if (uri == "/config") - { - uri = "/index.html"; - b_is_index = true; - } - - { - while (true) - { - int offset = uri.find("/"); - if (offset < 0) - { - break; - } - uri = uri.replace(offset, 1, "\\"); - } - ex_astr file_suffix; - int offset = uri.rfind("."); - if (offset > 0) - { - file_suffix = uri.substr(offset, uri.length()); - } - - ex_astr temp; - ex_wstr2astr(g_env.m_site_path, temp); - ex_astr index_path = temp + uri; - FILE* file = NULL; - //fopen(index_path.c_str(), "rb"); - fopen_s(&file, index_path.c_str(), "rb"); - unsigned long file_size = 0; - char* buf = 0; - int ret = 0; - if (file) - { - fseek(file, 0, SEEK_END); - file_size = ftell(file); - buf = new char[file_size]; - memset(buf, 0, file_size); - fseek(file, 0, SEEK_SET); - ret = fread(buf, 1, file_size, file); - fclose(file); - - ex_astr content_type = _this->get_content_type(file_suffix); - - mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: %s\r\n\r\n", file_size, content_type.c_str()); - mg_send(nc, buf, file_size); - delete []buf; - nc->flags |= MG_F_SEND_AND_CLOSE; - return; - } - else if (b_is_index) - { - ex_wstr page = L"404 Not Found

404 Not Found


未能找到TELEPORT助手配置页面文件!

"; - ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); - - mg_printf(nc, "HTTP/1.0 404 File Not Found\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); - nc->flags |= MG_F_SEND_AND_CLOSE; - return; - } - } - - ex_astr method; - ex_astr json_param; - int rv = _this->_parse_request(hm, method, json_param); - if (0 != rv) - { - EXLOGE("[ERROR] http-rpc got invalid request.\n"); - _this->_create_json_ret(ret_buf, rv); - } - else - { - _this->_process_js_request(method, json_param, ret_buf); - } - - mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: application/json\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); - nc->flags |= MG_F_SEND_AND_CLOSE; - } - break; - default: - break; - } -} - -int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_astr& func_args) -{ - if (NULL == req) - return TPE_FAILED; - - bool is_get = true; - if (req->method.len == 3 && 0 == memcmp(req->method.p, "GET", req->method.len)) - is_get = true; - else if (req->method.len == 4 && 0 == memcmp(req->method.p, "POST", req->method.len)) - is_get = false; - else - return TPE_HTTP_METHOD; - - ex_astrs strs; - - size_t pos_start = 1; // 跳过第一个字节,一定是 '/' - - size_t i = 0; - for (i = pos_start; i < req->uri.len; ++i) - { - if (req->uri.p[i] == '/') - { - if (i - pos_start > 0) - { - ex_astr tmp_uri; - tmp_uri.assign(req->uri.p + pos_start, i - pos_start); - strs.push_back(tmp_uri); - } - pos_start = i + 1; // 跳过当前找到的分隔符 - } - } - if (pos_start < req->uri.len) - { - ex_astr tmp_uri; - tmp_uri.assign(req->uri.p + pos_start, req->uri.len - pos_start); - strs.push_back(tmp_uri); - } - - if (0 == strs.size()) - return TPE_PARAM; - - if (is_get) - { - if (1 == strs.size()) - { - func_cmd = strs[0]; - } - else if (2 == strs.size()) - { - func_cmd = strs[0]; - func_args = strs[1]; - } - else - { - return TPE_PARAM; - } - } - else - { - if (1 == strs.size()) - { - func_cmd = strs[0]; - } - else - { - return TPE_PARAM; - } - - if (req->body.len > 0) - { - func_args.assign(req->body.p, req->body.len); - } - } - - if (func_args.length() > 0) - { - // 将参数进行 url-decode 解码 - int len = func_args.length() * 2; - ex_chars sztmp; - sztmp.resize(len); - memset(&sztmp[0], 0, len); - if (-1 == ts_url_decode(func_args.c_str(), func_args.length(), &sztmp[0], len, 0)) - return TPE_HTTP_URL_ENCODE; - - func_args = &sztmp[0]; - } - - EXLOGV("[rpc] method=%s, json_param=%s\n", func_cmd.c_str(), func_args.c_str()); - - return TPE_OK; -} - -void TsHttpRpc::_process_js_request(const ex_astr& func_cmd, const ex_astr& func_args, ex_astr& buf) -{ - if (func_cmd == "ts_get_version") - { - _rpc_func_get_version(func_args, buf); - } - else if (func_cmd == "ts_op") - { - _rpc_func_create_ts_client(func_args, buf); - } - else if (func_cmd == "ts_check") - { - _rpc_func_ts_check(func_args, buf); - } - else if (func_cmd == "ts_rdp_play") - { - _rpc_func_ts_rdp_play(func_args, buf); - } - else if (func_cmd == "ts_get_config") - { - _rpc_func_get_config(func_args, buf); - } - else if (func_cmd == "ts_set_config") - { - _rpc_func_set_config(func_args, buf); - } - else if (func_cmd == "ts_file_action") - { - _rpc_func_file_action(func_args, buf); - } - else - { - EXLOGE("[rpc] got unknown command: %s\n", func_cmd.c_str()); - _create_json_ret(buf, TPE_UNKNOWN_CMD); - } -} - -void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode) -{ - // 返回: {"code":123} - - Json::FastWriter jr_writer; - Json::Value jr_root; - - jr_root["code"] = errcode; - buf = jr_writer.write(jr_root); -} - -void TsHttpRpc::_create_json_ret(ex_astr& buf, Json::Value& jr_root) -{ - Json::FastWriter jr_writer; - buf = jr_writer.write(jr_root); -} - -void TsHttpRpc::_rpc_func_create_ts_client(const ex_astr& func_args, ex_astr& buf) -{ - // 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} - // authmode: 1=password, 2=private-key - // protocol: 1=rdp, 2=ssh - // SSH返回: {"code":0, "data":{"sid":"0123abcde"}} - // RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}} - - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - if (jsRoot.isArray()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - - // 判断参数是否正确 - if (!jsRoot["server_ip"].isString() || !jsRoot["size"].isNumeric() - || !jsRoot["server_port"].isNumeric() || !jsRoot["host_ip"].isString() - || !jsRoot["session_id"].isString() || !jsRoot["pro_type"].isNumeric() - ) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - - int pro_sub = 1; - if (!jsRoot["pro_sub"].isNull()) { - if (jsRoot["pro_sub"].isNumeric()) { - pro_sub = jsRoot["pro_sub"].asInt(); - } - } - - std::string teleport_ip = jsRoot["server_ip"].asCString(); - int teleport_port = jsRoot["server_port"].asUInt(); - - int windows_size = 2; - if (jsRoot["size"].isNull()) - windows_size = 2; - else - windows_size = jsRoot["size"].asUInt(); - - int console = 0; - if (jsRoot["console"].isNull()) - console = 0; - else - console = jsRoot["console"].asUInt(); - - std::string real_host_ip = jsRoot["host_ip"].asCString(); - std::string sid = jsRoot["session_id"].asCString(); - - int pro_type = jsRoot["pro_type"].asUInt(); - - ex_wstr w_exe_path; - WCHAR w_szCommandLine[MAX_PATH] = { 0 }; - - - ex_wstr w_sid; - ex_astr2wstr(sid, w_sid); - ex_wstr w_teleport_ip; - ex_astr2wstr(teleport_ip, w_teleport_ip); - ex_wstr w_real_host_ip; - ex_astr2wstr(real_host_ip, w_real_host_ip); - WCHAR w_port[32] = { 0 }; - swprintf_s(w_port, _T("%d"), teleport_port); - - - if (pro_type == 1) - { - //============================================== - // RDP - //============================================== -//#if 1 - -#if defined(RDP_CLIENT_SYSTEM_ACTIVE_CONTROL) - int split_pos = session_id.length() - 2; - std::string real_s_id = session_id.substr(0, split_pos); - std::string str_pwd_len = session_id.substr(split_pos, session_id.length()); - int n_pwd_len = strtol(str_pwd_len.c_str(), NULL, 16); - n_pwd_len -= real_s_id.length(); - WCHAR w_szPwd[256] = { 0 }; - for (int i = 0; i < n_pwd_len; i++) - { - w_szPwd[i] = '*'; - } - - w_exe_path = g_env.m_tools_path + _T("\\tprdp\\tp_rdp.exe"); - ex_wstr w_s_id; - ex_astr2str(real_s_id, w_s_id); - ex_wstr w_server_ip; - ex_astr2str(server_ip, w_server_ip); - - ex_wstr w_host_ip; - ex_astr2str(host_ip, w_host_ip); - - swprintf_s(w_szCommandLine, _T(" -h%s -u%s -p%s -x%d -d%s -r%d"), w_server_ip.c_str(), w_s_id.c_str(), w_szPwd, host_port, w_host_ip.c_str(), windows_size); - - // sprintf_s(sz_file_name, ("%s\\%s.rdp"), temp_path, temp_host_ip.c_str()); - // FILE* f = fopen(sz_file_name, ("wt")); - // if (f == NULL) - // { - // printf("fopen failed (%d).\n", GetLastError()); - // _create_json_ret(buf, TSR_OPENFILE_ERROR); - // return; - // } - // // Write a string into the file. - // fwrite(sz_rdp_file_content, strlen(sz_rdp_file_content), 1, f); - // fclose(f); - // ex_wstr w_sz_file_name; - // ex_astr2str(sz_file_name, w_sz_file_name); - // swprintf_s(w_szCommandLine, _T("mstsc %s"), w_sz_file_name.c_str()); - - w_exe_path += w_szCommandLine; - //BOOL bRet = DeleteFile(w_sz_file_name.c_str()); -#elif defined(RDP_CLIENT_FREERDP) - wchar_t* w_screen = NULL; - - switch (windows_size) - { - case 0: //全屏 - w_screen = _T("/f"); - break; - case 2: - w_screen = _T("/size:1024x768"); - break; - case 3: - w_screen = _T("/size:1280x1024"); - break; - case 1: - default: - w_screen = _T("/size:800x600"); - break; - } - - int split_pos = sid.length() - 2; - std::string real_sid = sid.substr(0, split_pos); - std::string str_pwd_len = sid.substr(split_pos, sid.length()); - int n_pwd_len = strtol(str_pwd_len.c_str(), NULL, 16); - n_pwd_len -= real_sid.length(); - WCHAR w_szPwd[256] = { 0 }; - for (int i = 0; i < n_pwd_len; i++) - { - w_szPwd[i] = '*'; - } - - ex_astr2wstr(real_sid, w_sid); - - - w_exe_path = _T("\""); - w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-client.exe\""); - - // use /gdi:sw otherwise the display will be yellow. - if (console != 0) - { - swprintf_s(w_szCommandLine, _T(" %s /v:{host_ip}:{host_port} /admin /u:{user_name} /p:%s +clipboard /drives /gdi:sw /t:\"TP#{real_ip}\""), - w_screen, w_szPwd - ); - } - else - { - swprintf_s(w_szCommandLine, _T(" %s /v:{host_ip}:{host_port} /u:{user_name} /p:%s +clipboard /drives /gdi:sw /t:\"TP#{real_ip}\""), - w_screen, w_szPwd - ); - } - - w_exe_path += w_szCommandLine; - -//#endif - -#elif defined(RDP_CLIENT_SYSTEM_BUILTIN) - int width = 800; - int higth = 600; - int cx = 0; - int cy = 0; - - int display = 1; - int iWidth = GetSystemMetrics(SM_CXSCREEN); - int iHeight = GetSystemMetrics(SM_CYSCREEN); - switch (windows_size) - { - case 0: - //全屏 - width = iWidth; - higth = iHeight; - display = 2; - break; - case 1: - { - width = 800; - higth = 600; - display = 1; - break; - } - case 2: - { - width = 1024; - higth = 768; - display = 1; - break; - } - case 3: - { - width = 1280; - higth = 1024; - display = 1; - break; - } - default: - //int iWidth = GetSystemMetrics(SM_CXSCREEN); - //int iHeight = GetSystemMetrics(SM_CYSCREEN); - //width = iWidth; - //width = iHeight - 50; - width = 800; - higth = 600; - break; - } - - cx = (iWidth - width) / 2; - cy = (iHeight - higth) / 2; - if (cx < 0) - { - cx = 0; - } - if (cy < 0) - { - cy = 0; - } - - int split_pos = sid.length() - 2; - std::string real_sid = sid.substr(0, split_pos); - - std::string psw51b; - if (!calc_psw51b("Abcd1234", psw51b)) - { - printf("calc password failed.\n"); - _create_json_ret(buf, TPE_FAILED); - return; - } - - char sz_rdp_file_content[4096] = { 0 }; - sprintf_s(sz_rdp_file_content, rdp_content.c_str(), - console, display, width, higth - , cx, cy, cx + width + 20, cy + higth + 40 - , teleport_ip.c_str(), teleport_port - , real_sid.c_str() - , psw51b.c_str() - ); - - char sz_file_name[MAX_PATH] = { 0 }; - char temp_path[MAX_PATH] = { 0 }; - DWORD ret = GetTempPathA(MAX_PATH, temp_path); - if (ret <= 0) - { - printf("fopen failed (%d).\n", GetLastError()); - _create_json_ret(buf, TPE_FAILED); - return; - } - ex_wstr w_s_id; - ex_astr2wstr(real_sid, w_s_id); - - ex_astr temp_host_ip = real_host_ip;// replace_all_distinct(real_host_ip, ("."), "-"); - ex_replace_all(temp_host_ip, ".", "-"); - - sprintf_s(sz_file_name, ("%s%s.rdp"), temp_path, temp_host_ip.c_str()); - //FILE* f = fopen(sz_file_name, ("wt")); - //if (f == NULL) - FILE* f = NULL; - if(fopen_s(&f, sz_file_name, "wt") != 0) - { - printf("fopen failed (%d).\n", GetLastError()); - _create_json_ret(buf, TPE_OPENFILE); - return; - } - // Write a string into the file. - fwrite(sz_rdp_file_content, strlen(sz_rdp_file_content), 1, f); - fclose(f); - ex_wstr w_sz_file_name; - ex_astr2wstr(sz_file_name, w_sz_file_name); - - swprintf_s(w_szCommandLine, _T("mstsc \"%s\""), w_sz_file_name.c_str()); - w_exe_path = w_szCommandLine; - //BOOL bRet = DeleteFile(w_sz_file_name.c_str()); -#endif - } - else if (pro_type == 2) - { - //============================================== - // SSH - //============================================== - - if (pro_sub == 1) - { - clientsetmap::iterator it = g_cfgSSH.m_clientsetmap.find(g_cfgSSH.m_current_client); - if (it == g_cfgSSH.m_clientsetmap.end()) - { - w_exe_path = _T("\""); - w_exe_path += g_env.m_tools_path; - w_exe_path += _T("\\putty\\putty.exe\""); - w_exe_path += _T(" -ssh -pw **** -P {host_port} -l {user_name} {host_ip}"); - } - else - { - w_exe_path = _T("\""); - w_exe_path += it->second.path + _T("\" "); - w_exe_path += it->second.commandline; - } - } - else - { - clientsetmap::iterator it = g_cfgScp.m_clientsetmap.find(g_cfgScp.m_current_client); - if (it == g_cfgScp.m_clientsetmap.end()) - { - w_exe_path = _T("\""); - w_exe_path += g_env.m_tools_path; - w_exe_path += _T("\\winscp\\winscp.exe\""); - w_exe_path += _T(" /sessionname=\"TP#{real_ip}\" {user_name}:****@{host_ip}:{host_port}"); - } - else { - w_exe_path = it->second.path + _T(" "); - w_exe_path += it->second.commandline; - } - } - } - else if (pro_type == 3) - { - //============================================== - // TELNET - //============================================== - - clientsetmap::iterator it = g_cfgTelnet.m_clientsetmap.find(g_cfgTelnet.m_current_client); - if (it == g_cfgTelnet.m_clientsetmap.end()) - { - w_exe_path = _T("\""); - w_exe_path += g_env.m_tools_path; - w_exe_path += _T("\\putty\\putty.exe\""); - w_exe_path += _T(" telnet://{user_name}@{host_ip}:{host_port}"); - } - else - { - w_exe_path = _T("\""); - w_exe_path += it->second.path + _T("\" "); - w_exe_path += it->second.commandline; - } - } - - ex_replace_all(w_exe_path, _T("{host_port}"), w_port); - ex_replace_all(w_exe_path, _T("{host_ip}"), w_teleport_ip.c_str()); - ex_replace_all(w_exe_path, _T("{user_name}"), w_sid.c_str()); - ex_replace_all(w_exe_path, _T("{real_ip}"), w_real_host_ip.c_str()); - ex_replace_all(w_exe_path, _T("{assist_tools_path}"), g_env.m_tools_path.c_str()); - - - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - Json::Value root_ret; - ex_astr utf8_path; - ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8); - root_ret["path"] = utf8_path; - - if (!CreateProcess(NULL, (wchar_t *)w_exe_path.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) - { - EXLOGE(_T("CreateProcess() failed. Error=0x%08X.\n %s\n"), GetLastError(), w_exe_path.c_str()); - root_ret["code"] = TPE_START_CLIENT; - _create_json_ret(buf, root_ret); - return; - } - - root_ret["code"] = TPE_OK; - _create_json_ret(buf, root_ret); -} - -bool isIPAddress(const char *s) -{ - const char *pChar; - bool rv = true; - int tmp1, tmp2, tmp3, tmp4, i; - while (1) - { - i = sscanf_s(s, "%d.%d.%d.%d", &tmp1, &tmp2, &tmp3, &tmp4); - if (i != 4) - { - rv = false; - break; - } - - if ((tmp1 > 255) || (tmp2 > 255) || (tmp3 > 255) || (tmp4 > 255)) - { - rv = false; - break; - } - - for (pChar = s; *pChar != 0; pChar++) - { - if ((*pChar != '.') - && ((*pChar < '0') || (*pChar > '9'))) - { - rv = false; - break; - } - } - break; - } - - return rv; -} - -void TsHttpRpc::_rpc_func_ts_check(const ex_astr& func_args, ex_astr& buf) -{ - // 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} - // authmode: 1=password, 2=private-key - // protocol: 1=rdp, 2=ssh - // SSH返回: {"code":0, "data":{"sid":"0123abcde"}} - // RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}} - - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - if (jsRoot.isArray()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - int windows_size = 2; - - - - // 判断参数是否正确 - if (!jsRoot["server_ip"].isString() || !jsRoot["ssh_port"].isNumeric() - || !jsRoot["rdp_port"].isNumeric() - ) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - - std::string host = jsRoot["server_ip"].asCString(); - int rdp_port = jsRoot["rdp_port"].asUInt(); - int ssh_port = jsRoot["rdp_port"].asUInt(); - std::string server_ip; - if (isIPAddress(host.c_str())) - { - server_ip = host; - } - else - { - char *ptr, **pptr; - struct hostent *hptr; - char IP[128] = { 0 }; - /* 取得命令后第一个参数,即要解析的域名或主机名 */ - ptr = (char*)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; /* 如果调用gethostbyname发生错误,返回1 */ - } - /* 将主机的规范名打出来 */ - //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; - //printf(" address:%s/n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); - break; - default: - printf("unknown address type/n"); - break; - } - } - if (!isIPAddress(server_ip.c_str())) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (TestTCPPort(server_ip, rdp_port) && TestTCPPort(server_ip, ssh_port)) - { - _create_json_ret(buf, TPE_OK); - return; - } - ICMPheaderRet temp = { 0 }; - int b_ok = ICMPSendTo(&temp, (char*)server_ip.c_str(), 16, 8); - if (b_ok == 0) - { - _create_json_ret(buf, TPE_OK); - return; - } - else - { - _create_json_ret(buf, TPE_NETWORK); - } - - return; -} - -void TsHttpRpc::_rpc_func_ts_rdp_play(const ex_astr& func_args, ex_astr& buf) -{ - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - - // 判断参数是否正确 - if (!jsRoot["host"].isString()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (!jsRoot["port"].isInt()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (!jsRoot["tail"].isString()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - ex_astr a_host = jsRoot["host"].asCString(); - int port = jsRoot["port"].asInt(); - 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; - 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_wstr w_host; - ex_astr2wstr(a_host, w_host); - - ex_wstr w_exe_path; - w_exe_path = _T("\""); - w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\""); - //swprintf_s(w_szCommandLine, _T(" -ssh -pw **** -P %d -l %s %s"), teleport_port, w_s_id.c_str(), w_teleport_ip.c_str()); - w_exe_path += _T(" "); - w_exe_path += w_url; - - w_exe_path += _T(" "); - w_exe_path += w_host; - - Json::Value root_ret; - ex_astr utf8_path; - ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8); - root_ret["path"] = utf8_path; - - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - if (!CreateProcess(NULL, (wchar_t *)w_exe_path.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) - { - EXLOGE(_T("CreateProcess() failed. Error=0x%08X.\n %s\n"), GetLastError(), w_exe_path.c_str()); - root_ret["code"] = TPE_START_CLIENT; - _create_json_ret(buf, root_ret); - return; - } - - root_ret["code"] = TPE_OK; - _create_json_ret(buf, root_ret); - return; -} - -void TsHttpRpc::_rpc_func_get_config(const ex_astr& func_args, ex_astr& buf) -{ - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - // 判断参数是否正确 - if (!jsRoot["type"].isNumeric()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - int type = jsRoot["type"].asUInt(); - if (type == 1) - { - Json::Value jr_root; - Json::Value config_list; - - jr_root["code"] = 0; - - clientsetmap::iterator it; - for (it = g_cfgSSH.m_clientsetmap.begin(); it != g_cfgSSH.m_clientsetmap.end(); it++) - { - - Json::Value config; - ex_astr temp; - ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); - config["name"] = temp; - - ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); - config["path"] = temp; - - ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); - config["commandline"] = temp; - - ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); - config["alias_name"] = temp; - - ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); - config["desc"] = temp; - - config["build_in"] = it->second.is_default ? 1 : 0; - if (it->first == g_cfgSSH.m_current_client) - { - config["current"] = 1; - } - else { - config["current"] = 0; - } - - - config_list.append(config); - } - - jr_root["config_list"] = config_list; - _create_json_ret(buf, jr_root); - - return; - } - else if (type == 2) - { - Json::Value jr_root; - Json::Value config_list; - - jr_root["code"] = 0; - - clientsetmap::iterator it; - for (it = g_cfgScp.m_clientsetmap.begin(); it != g_cfgScp.m_clientsetmap.end(); it++) - { - - Json::Value config; - ex_astr temp; - ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); - config["name"] = temp; - - ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); - config["path"] = temp; - - ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); - config["commandline"] = temp; - - ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); - config["desc"] = temp; - - ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); - config["alias_name"] = temp; - - config["build_in"] = it->second.is_default ? 1 : 0; - - if (it->first == g_cfgScp.m_current_client) - config["current"] = 1; - else - config["current"] = 0; - - config_list.append(config); - } - - jr_root["config_list"] = config_list; - _create_json_ret(buf, jr_root); - return; - } - else if (type == 3) - { - Json::Value jr_root; - Json::Value config_list; - - jr_root["code"] = 0; - - clientsetmap::iterator it; - for (it = g_cfgTelnet.m_clientsetmap.begin(); it != g_cfgTelnet.m_clientsetmap.end(); it++) - { - Json::Value config; - ex_astr temp; - ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); - config["name"] = temp; - - ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); - config["path"] = temp; - - ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); - config["commandline"] = temp; - - ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); - config["desc"] = temp; - - ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); - config["alias_name"] = temp; - - config["build_in"] = it->second.is_default ? 1 : 0; - - if (it->first == g_cfgTelnet.m_current_client) - config["current"] = 1; - else - config["current"] = 0; - - config_list.append(config); - } - - jr_root["config_list"] = config_list; - _create_json_ret(buf, jr_root); - return; - } - else - { - _create_json_ret(buf, TPE_PARAM); - return; - } -} - -void TsHttpRpc::_rpc_func_set_config(const ex_astr& func_args, ex_astr& buf) -{ - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - if (jsRoot.isArray()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - - // 判断参数是否正确 - if (!jsRoot["name"].isString() || !jsRoot["path"].isString() || - !jsRoot["commandline"].isString() || - !jsRoot["type"].isNumeric()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - int type = jsRoot["type"].asUInt(); - ex_astr name = jsRoot["name"].asCString(); - ex_astr path = jsRoot["path"].asCString(); - ex_astr commandline = jsRoot["commandline"].asCString(); - - ex_wstr w_path; - ex_astr2wstr(path, w_path, EX_CODEPAGE_UTF8); - ex_wstr w_name; - ex_astr2wstr(name, w_name, EX_CODEPAGE_UTF8); - - ex_wstr w_commandline; - ex_astr2wstr(commandline, w_commandline, EX_CODEPAGE_UTF8); - - if (type == 1) - { - - clientsetmap::iterator it = g_cfgSSH.m_clientsetmap.find(w_name); - if (it == g_cfgSSH.m_clientsetmap.end()) { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (it->second.is_default) - { - g_cfgSSH.set(_T("common"), _T("current_client"), w_name); - g_cfgSSH.save(); - g_cfgSSH.init(); - _create_json_ret(buf, TPE_OK); - return; - } - g_cfgSSH.set(w_name, _T("path"), w_path); - g_cfgSSH.set(w_name, _T("command_line"), w_commandline); - g_cfgSSH.set(_T("common"), _T("current_client"), w_name); - - g_cfgSSH.save(); - g_cfgSSH.init(); - _create_json_ret(buf, TPE_OK); - return; - - } - else if (type == 2) - { - clientsetmap::iterator it = g_cfgScp.m_clientsetmap.find(w_name); - if (it == g_cfgScp.m_clientsetmap.end()) { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (it->second.is_default) - { - g_cfgScp.set(_T("common"), _T("current_client"), w_name); - g_cfgScp.save(); - g_cfgScp.init(); - _create_json_ret(buf, TPE_OK); - return; - } - g_cfgScp.set(w_name, _T("path"), w_path); - g_cfgScp.set(w_name, _T("command_line"), w_commandline); - g_cfgScp.set(_T("common"), _T("current_client"), w_name); - - g_cfgScp.save(); - g_cfgScp.init(); - _create_json_ret(buf, TPE_OK); - return; - } - else if (type == 3) - { - clientsetmap::iterator it = g_cfgTelnet.m_clientsetmap.find(w_name); - if (it == g_cfgTelnet.m_clientsetmap.end()) { - _create_json_ret(buf, TPE_PARAM); - return; - } - if (it->second.is_default) - { - g_cfgTelnet.set(_T("common"), _T("current_client"), w_name); - g_cfgTelnet.save(); - g_cfgTelnet.init(); - _create_json_ret(buf, TPE_OK); - return; - } - g_cfgTelnet.set(w_name, _T("path"), w_path); - g_cfgTelnet.set(w_name, _T("command_line"), w_commandline); - g_cfgTelnet.set(_T("common"), _T("current_client"), w_name); - - g_cfgTelnet.save(); - g_cfgTelnet.init(); - _create_json_ret(buf, TPE_OK); - return; - } - else { - _create_json_ret(buf, TPE_PARAM); - return; - } -} - -void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) { - - Json::Reader jreader; - Json::Value jsRoot; - - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TPE_JSON_FORMAT); - return; - } - // 判断参数是否正确 - if (!jsRoot["action"].isNumeric()) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - int action = jsRoot["action"].asUInt(); - - HWND hParent = GetForegroundWindow(); - if (NULL == hParent) - hParent = g_hDlgMain; - - BOOL ret = FALSE; - wchar_t wszReturnPath[MAX_PATH] = _T(""); - - if (action == 1 || action == 2) - { - OPENFILENAME ofn; - ex_wstr wsDefaultName; - ex_wstr wsDefaultPath; - StringCchCopy(wszReturnPath, MAX_PATH, wsDefaultName.c_str()); - - ZeroMemory(&ofn, sizeof(ofn)); - - ofn.lStructSize = sizeof(ofn); - ofn.lpstrTitle = _T("选择文件"); - ofn.hwndOwner = hParent; - ofn.lpstrFilter = _T("可执行程序 (*.exe)\0*.exe\0"); - ofn.lpstrFile = wszReturnPath; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrInitialDir = wsDefaultPath.c_str(); - ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST; - - if (action == 1) - { - ofn.Flags |= OFN_FILEMUSTEXIST; - ret = GetOpenFileName(&ofn); - } - else - { - ofn.Flags |= OFN_OVERWRITEPROMPT; - ret = GetSaveFileName(&ofn); - } - } - else if (action == 3) - { - BROWSEINFO bi; - ZeroMemory(&bi, sizeof(BROWSEINFO)); - bi.hwndOwner = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = wszReturnPath; //此参数如为NULL则不能显示对话框 - bi.lpszTitle = _T("选择目录"); - bi.ulFlags = BIF_RETURNONLYFSDIRS; - bi.lpfn = NULL; - bi.iImage = 0; //初始化入口参数bi结束 - LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框 - if (pIDList) - { - ret = true; - SHGetPathFromIDList(pIDList, wszReturnPath); - } - else - { - ret = false; - } - } - else if (action == 4) - { - ex_wstr wsDefaultName; - ex_wstr wsDefaultPath; - - if (wsDefaultPath.length() == 0) - { - _create_json_ret(buf, TPE_PARAM); - return; - } - - ex_wstr::size_type pos = 0; - - while (ex_wstr::npos != (pos = wsDefaultPath.find(L"/", pos))) - { - wsDefaultPath.replace(pos, 1, L"\\"); - pos += 1; - } - - ex_wstr wArg = L"/select, \""; - wArg += wsDefaultPath; - wArg += L"\""; - if ((int)ShellExecute(hParent, _T("open"), _T("explorer"), wArg.c_str(), NULL, SW_SHOW) > 32) - ret = true; - else - ret = false; - } - - if (ret) - { - if (action == 1 || action == 2 || action == 3) - { - ex_astr utf8_path; - ex_wstr2astr(wszReturnPath, utf8_path, EX_CODEPAGE_UTF8); - Json::Value root; - root["path"] = utf8_path; - _create_json_ret(buf, root); - - return; - } - else - { - _create_json_ret(buf, TPE_OK); - return; - } - } - else - { - _create_json_ret(buf, TPE_DATA); - return; - } -} - -void TsHttpRpc::_rpc_func_get_version(const ex_astr& func_args, ex_astr& buf) -{ - Json::Value root_ret; - ex_wstr w_version = TP_ASSIST_VER; - ex_astr version; - ex_wstr2astr(w_version, version, EX_CODEPAGE_UTF8); - root_ret["version"] = version; - root_ret["code"] = TPE_OK; - _create_json_ret(buf, root_ret); - return; -} +#include "stdafx.h" + +#pragma warning(disable:4091) + +#include +#include + +#include + +#include "ts_http_rpc.h" +#include "dlg_main.h" +#include "ts_ver.h" + +/* +1. +SecureCRT支持设置标签页的标题,命令行参数 /N "tab name"就可以 +Example: +To launch a new Telnet session, displaying the name "Houston, TX" on the tab, use the following: +/T /N "Houston, TX" /TELNET 192.168.0.6 + +2. +多次启动的SecureCRT放到一个窗口的不同标签页中,使用参数: /T + SecureCRT.exe /T /N "TP#ssh://192.168.1.3" /SSH2 /L root /PASSWORD 1234 120.26.109.25 + +3. +telnet客户端的启动: + putty.exe telnet://administrator@127.0.0.1:52389 +如果是SecureCRT,则需要 + SecureCRT.exe /T /N "TP#telnet://192.168.1.3" /SCRIPT X:\path\to\startup.vbs /TELNET 127.0.0.1 52389 +其中,startup.vbs的内容为: +---------文件开始--------- +#$language = "VBScript" +#$interface = "1.0" +Sub main + crt.Screen.Synchronous = True + crt.Screen.WaitForString "ogin: " + crt.Screen.Send "SESSION-ID" & VbCr + crt.Screen.Synchronous = False +End Sub +---------文件结束--------- + +4. 为了让putty的窗口标签显示正常的IP,可以尝试在连接成功后,主动向服务端发送下列命令: + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@192.168.1.2: \w\a\]$PS1" +手工测试了,ubuntu服务器可以,不知道是否能够支持所有的Linux。SecureCRT对此表示忽略。 +*/ + +// #define RDP_CLIENT_SYSTEM_BUILTIN +// #define RDP_CLIENT_SYSTEM_ACTIVE_CONTROL +#define RDP_CLIENT_FREERDP + + +#ifdef RDP_CLIENT_SYSTEM_BUILTIN +#include +#pragma comment(lib, "Crypt32.lib") + +std::string rdp_content = "\ +connect to console:i:%d\n\ +screen mode id:i:%d\n\ +desktopwidth:i:%d\n\ +desktopheight:i:%d\n\ +winposstr:s:0,1,%d,%d,%d,%d\n\ +full address:s:%s:%d\n\ +username:s:%s\n\ +prompt for credentials:i:0\n\ +use multimon:i:0\n\ +authentication level:i:3\n\ +session bpp:i:16\n\ +compression:i:1\n\ +keyboardhook:i:2\n\ +audiocapturemode:i:0\n\ +negotiate security layer:i:1\n\ +videoplaybackmode:i:1\n\ +connection type:i:2\n\ +prompt for credentials on client:i:0\n\ +displayconnectionbar:i:1\n\ +disable wallpaper:i:1\n\ +allow font smoothing:i:0\n\ +allow desktop composition:i:0\n\ +disable full window drag:i:1\n\ +disable menu anims:i:1\n\ +disable themes:i:1\n\ +disable cursor setting:i:0\n\ +bitmapcachepersistenable:i:1\n\ +audiomode:i:0\n\ +redirectprinters:i:0\n\ +redirectcomports:i:0\n\ +redirectsmartcards:i:0\n\ +redirectclipboard:i:1\n\ +redirectposdevices:i:0\n\ +redirectdirectx:i:0\n\ +autoreconnection enabled:i:0\n\ +drivestoredirect:s:*\n\ +password 51:b:%s\n\ +"; + +//password 51:b:01000000D08C9DDF0115D1118C7A00C04FC297EB0100000052A9E191EA75A948B359790578C9371A0000000008000000700073007700000003660000A8000000100000000A1DCCD2E50775CA25EC3857164B34DC0000000004800000A000000010000000FCE1A645B9B61AA450946BB6F955058108020000D83591CA47562D6DDAA689F050AE145039EBE22E00D1D3AEAA98373C7B63C3E8E7149072DF989EA43EFCE20513AD3D27B11BE7F17066A688E1DCE828AF85460AAC327B38E90776DB962888E4393D19637578984B19A187AAD95F6D2726ADE7DD315FF56C15FF5B3031014EDDCC3C24D1B81779AFDB006EE575F5BEFB8D2D2138D9D9D642BBB251CC5ED7226968764856EC660A646BACE748A13D6002A9A537AA70710615650B9387EED66DE28BD57B304BBDD7B581B943DA628EB0289E30A8BA784B76F7885BECCAB4FEF7820E97EE3C6E036EEAF6EAA669288DF2FCACC9BEC045C907EBBDE87AFB8CC6B07A600BD63AC891B61D95C2265DD9FD5E635D61BFBF5EDC28311375066611C610FB533D64515B643C82F57D9B183B05C156D91BC0974D38E546022B139E82452E6F1EDF76E52F732C3904E5E433F8F3D488DB0698427DBB0791A9F207F8CB6654CB8410BAF4A59C4F9E821E589ABC1E6E6E1D432181B690408F6884FE1007895A4D26D4A5A2C7458EE747DA35D44AC9FB08AB5477EA3E7CCDB3E37EE20FAFD0D0CF9584E420598B7003B347943AC28048F45E0FD21AD08148FFADCE0E7877219259A7BE722FFAE845A429BA2CF0A71F2D19EA7495530FABDB5106E8D404A38A7E6394C38457640EA7398C5D55F0C4D342CC6A39C77E10A2A5145AEA40B14F5C7C3760334D83C9BE748383FADE231248537353817D51F7B44F61B406ABC61400000071C354139F458B02D978015F785B97F7F6B307380\n\ +//password 51:b:01000000"; + +#endif + + +TsHttpRpc g_http_interface; + +void http_rpc_main_loop(void) +{ + if (!g_http_interface.init(TS_HTTP_RPC_HOST, TS_HTTP_RPC_PORT)) + { + EXLOGE("[ERROR] can not start HTTP-RPC listener, maybe port %d is already in use.\n", TS_HTTP_RPC_PORT); + return; + } + + EXLOGW("======================================================\n"); + EXLOGW("[rpc] TeleportAssist-HTTP-RPC ready on %s:%d\n", TS_HTTP_RPC_HOST, TS_HTTP_RPC_PORT); + + g_http_interface.run(); + + EXLOGW("[rpc] main loop end.\n"); +} + +void http_rpc_stop(void) +{ + g_http_interface.stop(); +} + +#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') + +int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded) +{ + int i, j, a, b; + + for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) + { + if (src[i] == '%') + { + if (i < src_len - 2 && isxdigit(*(const unsigned char *)(src + i + 1)) && + isxdigit(*(const unsigned char *)(src + i + 2))) { + a = tolower(*(const unsigned char *)(src + i + 1)); + b = tolower(*(const unsigned char *)(src + i + 2)); + dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b)); + i += 2; + } + else + { + return -1; + } + } + else if (is_form_url_encoded && src[i] == '+') + { + dst[j] = ' '; + } + else + { + dst[j] = src[i]; + } + } + + dst[j] = '\0'; /* Null-terminate the destination */ + + return i >= src_len ? j : -1; +} + +#ifdef RDP_CLIENT_SYSTEM_BUILTIN +bool calc_psw51b(const char* password, std::string& ret) +{ + DATA_BLOB DataIn; + DATA_BLOB DataOut; + + ex_wstr w_pswd; + ex_astr2wstr(password, w_pswd, EX_CODEPAGE_ACP); + + DataIn.cbData = w_pswd.length() * sizeof(wchar_t); + DataIn.pbData = (BYTE*)w_pswd.c_str(); + + + if (!CryptProtectData(&DataIn, L"psw", NULL, NULL, NULL, 0, &DataOut)) + return false; + + char szRet[5] = {0}; + for (int i = 0; i < DataOut.cbData; ++i) + { + sprintf_s(szRet, 5, "%02X", DataOut.pbData[i]); + ret += szRet; + } + + LocalFree(DataOut.pbData); + return true; +} +#endif + +TsHttpRpc::TsHttpRpc() +{ + m_stop = false; + mg_mgr_init(&m_mg_mgr, NULL); +} + +TsHttpRpc::~TsHttpRpc() +{ + mg_mgr_free(&m_mg_mgr); +} + +bool TsHttpRpc::init(const char* ip, int port) +{ + char file_name[MAX_PATH] = { 0 }; + if (!GetModuleFileNameA(NULL, file_name, MAX_PATH)) + return false; + + int len = strlen(file_name); + + if (file_name[len] == '\\') + { + file_name[len] = '\0'; + } + char* match = strrchr(file_name, '\\'); + if (match != NULL) + { + *match = '\0'; + } + + struct mg_connection* nc = NULL; + + char addr[128] = { 0 }; + if (0 == strcmp(ip, "127.0.0.1") || 0 == strcmp(ip, "localhost")) + sprintf_s(addr, 128, ":%d", port); + else + sprintf_s(addr, 128, "%s:%d", ip, port); + + nc = mg_bind(&m_mg_mgr, addr, _mg_event_handler); + if (nc == NULL) + { + EXLOGE("[rpc] TsHttpRpc::init %s:%d\n", ip, port); + return false; + } + nc->user_data = this; + + mg_set_protocol_http_websocket(nc); + + m_content_type_map[".js"] = "application/javascript"; + m_content_type_map[".png"] = "image/png"; + m_content_type_map[".jpeg"] = "image/jpeg"; + m_content_type_map[".jpg"] = "image/jpeg"; + m_content_type_map[".gif"] = "image/gif"; + m_content_type_map[".ico"] = "image/x-icon"; + m_content_type_map[".json"] = "image/json"; + m_content_type_map[".html"] = "text/html"; + m_content_type_map[".css"] = "text/css"; + m_content_type_map[".tif"] = "image/tiff"; + m_content_type_map[".tiff"] = "image/tiff"; + m_content_type_map[".svg"] = "text/html"; + + return true; +} + +void TsHttpRpc::run(void) +{ + while(!m_stop) + { + mg_mgr_poll(&m_mg_mgr, 500); + } +} + +void TsHttpRpc::stop(void) +{ + m_stop = true; +} + +void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_data) +{ + struct http_message *hm = (struct http_message*)ev_data; + + TsHttpRpc* _this = (TsHttpRpc*)nc->user_data; + if (NULL == _this) + { + EXLOGE("[ERROR] invalid http request.\n"); + return; + } + + switch (ev) + { + case MG_EV_HTTP_REQUEST: + { + ex_astr uri; + ex_chars _uri; + _uri.resize(hm->uri.len + 1); + memset(&_uri[0], 0, hm->uri.len + 1); + memcpy(&_uri[0], hm->uri.p, hm->uri.len); + uri = &_uri[0]; + +#ifdef EX_DEBUG + char* dbg_method = NULL; + if (hm->method.len == 3 && 0 == memcmp(hm->method.p, "GET", hm->method.len)) + dbg_method = "GET"; + else if (hm->method.len == 4 && 0 == memcmp(hm->method.p, "POST", hm->method.len)) + dbg_method = "POST"; + else + dbg_method = "UNSUPPORTED-HTTP-METHOD"; + + EXLOGV("[rpc] got %s request: %s\n", dbg_method, uri.c_str()); +#endif + ex_astr ret_buf; + bool b_is_index = false; + + if (uri == "/") + { + ex_wstr page = L"Teleport助手\n\n
Teleport助手工作正常!
"; + ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); + + mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); + nc->flags |= MG_F_SEND_AND_CLOSE; + return; + } + else if (uri == "/config") + { + uri = "/index.html"; + b_is_index = true; + } + + { + while (true) + { + int offset = uri.find("/"); + if (offset < 0) + { + break; + } + uri = uri.replace(offset, 1, "\\"); + } + ex_astr file_suffix; + int offset = uri.rfind("."); + if (offset > 0) + { + file_suffix = uri.substr(offset, uri.length()); + } + + ex_astr temp; + ex_wstr2astr(g_env.m_site_path, temp); + ex_astr index_path = temp + uri; + FILE* file = NULL; + //fopen(index_path.c_str(), "rb"); + fopen_s(&file, index_path.c_str(), "rb"); + unsigned long file_size = 0; + char* buf = 0; + int ret = 0; + if (file) + { + fseek(file, 0, SEEK_END); + file_size = ftell(file); + buf = new char[file_size]; + memset(buf, 0, file_size); + fseek(file, 0, SEEK_SET); + ret = fread(buf, 1, file_size, file); + fclose(file); + + ex_astr content_type = _this->get_content_type(file_suffix); + + mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: %s\r\n\r\n", file_size, content_type.c_str()); + mg_send(nc, buf, file_size); + delete []buf; + nc->flags |= MG_F_SEND_AND_CLOSE; + return; + } + else if (b_is_index) + { + ex_wstr page = L"404 Not Found

404 Not Found


未能找到TELEPORT助手配置页面文件!

"; + ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); + + mg_printf(nc, "HTTP/1.0 404 File Not Found\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); + nc->flags |= MG_F_SEND_AND_CLOSE; + return; + } + } + + ex_astr method; + ex_astr json_param; + int rv = _this->_parse_request(hm, method, json_param); + if (0 != rv) + { + EXLOGE("[ERROR] http-rpc got invalid request.\n"); + _this->_create_json_ret(ret_buf, rv); + } + else + { + _this->_process_js_request(method, json_param, ret_buf); + } + + mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: application/json\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); + nc->flags |= MG_F_SEND_AND_CLOSE; + } + break; + default: + break; + } +} + +int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_astr& func_args) +{ + if (NULL == req) + return TPE_FAILED; + + bool is_get = true; + if (req->method.len == 3 && 0 == memcmp(req->method.p, "GET", req->method.len)) + is_get = true; + else if (req->method.len == 4 && 0 == memcmp(req->method.p, "POST", req->method.len)) + is_get = false; + else + return TPE_HTTP_METHOD; + + ex_astrs strs; + + size_t pos_start = 1; // 跳过第一个字节,一定是 '/' + + size_t i = 0; + for (i = pos_start; i < req->uri.len; ++i) + { + if (req->uri.p[i] == '/') + { + if (i - pos_start > 0) + { + ex_astr tmp_uri; + tmp_uri.assign(req->uri.p + pos_start, i - pos_start); + strs.push_back(tmp_uri); + } + pos_start = i + 1; // 跳过当前找到的分隔符 + } + } + if (pos_start < req->uri.len) + { + ex_astr tmp_uri; + tmp_uri.assign(req->uri.p + pos_start, req->uri.len - pos_start); + strs.push_back(tmp_uri); + } + + if (0 == strs.size()) + return TPE_PARAM; + + if (is_get) + { + if (1 == strs.size()) + { + func_cmd = strs[0]; + } + else if (2 == strs.size()) + { + func_cmd = strs[0]; + func_args = strs[1]; + } + else + { + return TPE_PARAM; + } + } + else + { + if (1 == strs.size()) + { + func_cmd = strs[0]; + } + else + { + return TPE_PARAM; + } + + if (req->body.len > 0) + { + func_args.assign(req->body.p, req->body.len); + } + } + + if (func_args.length() > 0) + { + // 将参数进行 url-decode 解码 + int len = func_args.length() * 2; + ex_chars sztmp; + sztmp.resize(len); + memset(&sztmp[0], 0, len); + if (-1 == ts_url_decode(func_args.c_str(), func_args.length(), &sztmp[0], len, 0)) + return TPE_HTTP_URL_ENCODE; + + func_args = &sztmp[0]; + } + + EXLOGV("[rpc] method=%s, json_param=%s\n", func_cmd.c_str(), func_args.c_str()); + + return TPE_OK; +} + +void TsHttpRpc::_process_js_request(const ex_astr& func_cmd, const ex_astr& func_args, ex_astr& buf) +{ + if (func_cmd == "ts_get_version") + { + _rpc_func_get_version(func_args, buf); + } + else if (func_cmd == "ts_op") + { + _rpc_func_create_ts_client(func_args, buf); + } + else if (func_cmd == "ts_check") + { + _rpc_func_ts_check(func_args, buf); + } + else if (func_cmd == "ts_rdp_play") + { + _rpc_func_ts_rdp_play(func_args, buf); + } + else if (func_cmd == "ts_get_config") + { + _rpc_func_get_config(func_args, buf); + } + else if (func_cmd == "ts_set_config") + { + _rpc_func_set_config(func_args, buf); + } + else if (func_cmd == "ts_file_action") + { + _rpc_func_file_action(func_args, buf); + } + else + { + EXLOGE("[rpc] got unknown command: %s\n", func_cmd.c_str()); + _create_json_ret(buf, TPE_UNKNOWN_CMD); + } +} + +void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode) +{ + // 返回: {"code":123} + + Json::FastWriter jr_writer; + Json::Value jr_root; + + jr_root["code"] = errcode; + buf = jr_writer.write(jr_root); +} + +void TsHttpRpc::_create_json_ret(ex_astr& buf, Json::Value& jr_root) +{ + Json::FastWriter jr_writer; + buf = jr_writer.write(jr_root); +} + +void TsHttpRpc::_rpc_func_create_ts_client(const ex_astr& func_args, ex_astr& buf) +{ + // 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} + // authmode: 1=password, 2=private-key + // protocol: 1=rdp, 2=ssh + // SSH返回: {"code":0, "data":{"sid":"0123abcde"}} + // RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}} + + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + if (jsRoot.isArray()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + + // 判断参数是否正确 + if (!jsRoot["teleport_ip"].isString() || !jsRoot["size"].isNumeric() + || !jsRoot["teleport_port"].isNumeric() || !jsRoot["remote_host_ip"].isString() + || !jsRoot["session_id"].isString() || !jsRoot["protocol_type"].isNumeric() || !jsRoot["protocol_sub_type"].isNumeric() + ) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + +// int pro_sub = 0; +// if (!jsRoot["protocol_sub_type"].isNull()) { +// if (jsRoot["protocol_sub_type"].isNumeric()) { +// pro_sub = jsRoot["protocol_sub_type"].asInt(); +// } +// } + int pro_sub = jsRoot["protocol_sub_type"].asInt(); + + std::string teleport_ip = jsRoot["teleport_ip"].asCString(); + int teleport_port = jsRoot["teleport_port"].asUInt(); + + int windows_size = 2; + if (jsRoot["size"].isNull()) + windows_size = 2; + else + windows_size = jsRoot["size"].asUInt(); + + int console = 0; + if (jsRoot["console"].isNull()) + console = 0; + else + console = jsRoot["console"].asUInt(); + + std::string real_host_ip = jsRoot["remote_host_ip"].asCString(); + std::string sid = jsRoot["session_id"].asCString(); + + int pro_type = jsRoot["protocol_type"].asUInt(); + + ex_wstr w_exe_path; + WCHAR w_szCommandLine[MAX_PATH] = { 0 }; + + + ex_wstr w_sid; + ex_astr2wstr(sid, w_sid); + ex_wstr w_teleport_ip; + ex_astr2wstr(teleport_ip, w_teleport_ip); + ex_wstr w_real_host_ip; + ex_astr2wstr(real_host_ip, w_real_host_ip); + WCHAR w_port[32] = { 0 }; + swprintf_s(w_port, _T("%d"), teleport_port); + + + if (pro_type == TP_PROTOCOL_TYPE_RDP) + { + //============================================== + // RDP + //============================================== +//#if 1 + +#if defined(RDP_CLIENT_SYSTEM_ACTIVE_CONTROL) + int split_pos = session_id.length() - 2; + std::string real_s_id = session_id.substr(0, split_pos); + std::string str_pwd_len = session_id.substr(split_pos, session_id.length()); + int n_pwd_len = strtol(str_pwd_len.c_str(), NULL, 16); + n_pwd_len -= real_s_id.length(); + WCHAR w_szPwd[256] = { 0 }; + for (int i = 0; i < n_pwd_len; i++) + { + w_szPwd[i] = '*'; + } + + w_exe_path = g_env.m_tools_path + _T("\\tprdp\\tp_rdp.exe"); + ex_wstr w_s_id; + ex_astr2str(real_s_id, w_s_id); + ex_wstr w_server_ip; + ex_astr2str(server_ip, w_server_ip); + + ex_wstr w_host_ip; + ex_astr2str(host_ip, w_host_ip); + + swprintf_s(w_szCommandLine, _T(" -h%s -u%s -p%s -x%d -d%s -r%d"), w_server_ip.c_str(), w_s_id.c_str(), w_szPwd, host_port, w_host_ip.c_str(), windows_size); + + // sprintf_s(sz_file_name, ("%s\\%s.rdp"), temp_path, temp_host_ip.c_str()); + // FILE* f = fopen(sz_file_name, ("wt")); + // if (f == NULL) + // { + // printf("fopen failed (%d).\n", GetLastError()); + // _create_json_ret(buf, TSR_OPENFILE_ERROR); + // return; + // } + // // Write a string into the file. + // fwrite(sz_rdp_file_content, strlen(sz_rdp_file_content), 1, f); + // fclose(f); + // ex_wstr w_sz_file_name; + // ex_astr2str(sz_file_name, w_sz_file_name); + // swprintf_s(w_szCommandLine, _T("mstsc %s"), w_sz_file_name.c_str()); + + w_exe_path += w_szCommandLine; + //BOOL bRet = DeleteFile(w_sz_file_name.c_str()); +#elif defined(RDP_CLIENT_FREERDP) + wchar_t* w_screen = NULL; + + switch (windows_size) + { + case 0: //全屏 + w_screen = _T("/f"); + break; + case 2: + w_screen = _T("/size:1024x768"); + break; + case 3: + w_screen = _T("/size:1280x1024"); + break; + case 1: + default: + w_screen = _T("/size:800x600"); + break; + } + + int split_pos = sid.length() - 2; + std::string real_sid = sid.substr(0, split_pos); + std::string str_pwd_len = sid.substr(split_pos, sid.length()); + int n_pwd_len = strtol(str_pwd_len.c_str(), NULL, 16); + n_pwd_len -= real_sid.length(); + WCHAR w_szPwd[256] = { 0 }; + for (int i = 0; i < n_pwd_len; i++) + { + w_szPwd[i] = '*'; + } + + ex_astr2wstr(real_sid, w_sid); + + + w_exe_path = _T("\""); + w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-client.exe\""); + + // use /gdi:sw otherwise the display will be yellow. + if (console != 0) + { + swprintf_s(w_szCommandLine, _T(" %s /v:{host_ip}:{host_port} /admin /u:{user_name} /p:%s +clipboard /drives /gdi:sw /t:\"TP#{real_ip}\""), + w_screen, w_szPwd + ); + } + else + { + swprintf_s(w_szCommandLine, _T(" %s /v:{host_ip}:{host_port} /u:{user_name} /p:%s +clipboard /drives /gdi:sw /t:\"TP#{real_ip}\""), + w_screen, w_szPwd + ); + } + + w_exe_path += w_szCommandLine; + +//#endif + +#elif defined(RDP_CLIENT_SYSTEM_BUILTIN) + int width = 800; + int higth = 600; + int cx = 0; + int cy = 0; + + int display = 1; + int iWidth = GetSystemMetrics(SM_CXSCREEN); + int iHeight = GetSystemMetrics(SM_CYSCREEN); + switch (windows_size) + { + case 0: + //全屏 + width = iWidth; + higth = iHeight; + display = 2; + break; + case 1: + { + width = 800; + higth = 600; + display = 1; + break; + } + case 2: + { + width = 1024; + higth = 768; + display = 1; + break; + } + case 3: + { + width = 1280; + higth = 1024; + display = 1; + break; + } + default: + //int iWidth = GetSystemMetrics(SM_CXSCREEN); + //int iHeight = GetSystemMetrics(SM_CYSCREEN); + //width = iWidth; + //width = iHeight - 50; + width = 800; + higth = 600; + break; + } + + cx = (iWidth - width) / 2; + cy = (iHeight - higth) / 2; + if (cx < 0) + { + cx = 0; + } + if (cy < 0) + { + cy = 0; + } + + int split_pos = sid.length() - 2; + std::string real_sid = sid.substr(0, split_pos); + + std::string psw51b; + if (!calc_psw51b("Abcd1234", psw51b)) + { + printf("calc password failed.\n"); + _create_json_ret(buf, TPE_FAILED); + return; + } + + char sz_rdp_file_content[4096] = { 0 }; + sprintf_s(sz_rdp_file_content, rdp_content.c_str(), + console, display, width, higth + , cx, cy, cx + width + 20, cy + higth + 40 + , teleport_ip.c_str(), teleport_port + , real_sid.c_str() + , psw51b.c_str() + ); + + char sz_file_name[MAX_PATH] = { 0 }; + char temp_path[MAX_PATH] = { 0 }; + DWORD ret = GetTempPathA(MAX_PATH, temp_path); + if (ret <= 0) + { + printf("fopen failed (%d).\n", GetLastError()); + _create_json_ret(buf, TPE_FAILED); + return; + } + ex_wstr w_s_id; + ex_astr2wstr(real_sid, w_s_id); + + ex_astr temp_host_ip = real_host_ip;// replace_all_distinct(real_host_ip, ("."), "-"); + ex_replace_all(temp_host_ip, ".", "-"); + + sprintf_s(sz_file_name, ("%s%s.rdp"), temp_path, temp_host_ip.c_str()); + //FILE* f = fopen(sz_file_name, ("wt")); + //if (f == NULL) + FILE* f = NULL; + if(fopen_s(&f, sz_file_name, "wt") != 0) + { + printf("fopen failed (%d).\n", GetLastError()); + _create_json_ret(buf, TPE_OPENFILE); + return; + } + // Write a string into the file. + fwrite(sz_rdp_file_content, strlen(sz_rdp_file_content), 1, f); + fclose(f); + ex_wstr w_sz_file_name; + ex_astr2wstr(sz_file_name, w_sz_file_name); + + swprintf_s(w_szCommandLine, _T("mstsc \"%s\""), w_sz_file_name.c_str()); + w_exe_path = w_szCommandLine; + //BOOL bRet = DeleteFile(w_sz_file_name.c_str()); +#endif + } + else if (pro_type == TP_PROTOCOL_TYPE_SSH) + { + //============================================== + // SSH + //============================================== + + if (pro_sub == TP_PROTOCOL_SUB_TYPE_SSH) + { + clientsetmap::iterator it = g_cfgSSH.m_clientsetmap.find(g_cfgSSH.m_current_client); + if (it == g_cfgSSH.m_clientsetmap.end()) + { + w_exe_path = _T("\""); + w_exe_path += g_env.m_tools_path; + w_exe_path += _T("\\putty\\putty.exe\""); + w_exe_path += _T(" -ssh -pw **** -P {host_port} -l {user_name} {host_ip}"); + } + else + { + w_exe_path = _T("\""); + w_exe_path += it->second.path + _T("\" "); + w_exe_path += it->second.commandline; + } + } + else + { + clientsetmap::iterator it = g_cfgScp.m_clientsetmap.find(g_cfgScp.m_current_client); + if (it == g_cfgScp.m_clientsetmap.end()) + { + w_exe_path = _T("\""); + w_exe_path += g_env.m_tools_path; + w_exe_path += _T("\\winscp\\winscp.exe\""); + w_exe_path += _T(" /sessionname=\"TP#{real_ip}\" {user_name}:****@{host_ip}:{host_port}"); + } + else { + w_exe_path = it->second.path + _T(" "); + w_exe_path += it->second.commandline; + } + } + } + else if (pro_type == TP_PROTOCOL_TYPE_TELNET) + { + //============================================== + // TELNET + //============================================== + + clientsetmap::iterator it = g_cfgTelnet.m_clientsetmap.find(g_cfgTelnet.m_current_client); + if (it == g_cfgTelnet.m_clientsetmap.end()) + { + w_exe_path = _T("\""); + w_exe_path += g_env.m_tools_path; + w_exe_path += _T("\\putty\\putty.exe\""); + w_exe_path += _T(" telnet://{user_name}@{host_ip}:{host_port}"); + } + else + { + w_exe_path = _T("\""); + w_exe_path += it->second.path + _T("\" "); + w_exe_path += it->second.commandline; + } + } + + ex_replace_all(w_exe_path, _T("{host_port}"), w_port); + ex_replace_all(w_exe_path, _T("{host_ip}"), w_teleport_ip.c_str()); + ex_replace_all(w_exe_path, _T("{user_name}"), w_sid.c_str()); + ex_replace_all(w_exe_path, _T("{real_ip}"), w_real_host_ip.c_str()); + ex_replace_all(w_exe_path, _T("{assist_tools_path}"), g_env.m_tools_path.c_str()); + + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + Json::Value root_ret; + ex_astr utf8_path; + ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8); + root_ret["path"] = utf8_path; + + if (!CreateProcess(NULL, (wchar_t *)w_exe_path.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + EXLOGE(_T("CreateProcess() failed. Error=0x%08X.\n %s\n"), GetLastError(), w_exe_path.c_str()); + root_ret["code"] = TPE_START_CLIENT; + _create_json_ret(buf, root_ret); + return; + } + + root_ret["code"] = TPE_OK; + _create_json_ret(buf, root_ret); +} + +bool isIPAddress(const char *s) +{ + const char *pChar; + bool rv = true; + int tmp1, tmp2, tmp3, tmp4, i; + while (1) + { + i = sscanf_s(s, "%d.%d.%d.%d", &tmp1, &tmp2, &tmp3, &tmp4); + if (i != 4) + { + rv = false; + break; + } + + if ((tmp1 > 255) || (tmp2 > 255) || (tmp3 > 255) || (tmp4 > 255)) + { + rv = false; + break; + } + + for (pChar = s; *pChar != 0; pChar++) + { + if ((*pChar != '.') + && ((*pChar < '0') || (*pChar > '9'))) + { + rv = false; + break; + } + } + break; + } + + return rv; +} + +void TsHttpRpc::_rpc_func_ts_check(const ex_astr& func_args, ex_astr& buf) +{ + // 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} + // authmode: 1=password, 2=private-key + // protocol: 1=rdp, 2=ssh + // SSH返回: {"code":0, "data":{"sid":"0123abcde"}} + // RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}} + + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + if (jsRoot.isArray()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + int windows_size = 2; + + + + // 判断参数是否正确 + if (!jsRoot["server_ip"].isString() || !jsRoot["ssh_port"].isNumeric() + || !jsRoot["rdp_port"].isNumeric() + ) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + + std::string host = jsRoot["server_ip"].asCString(); + int rdp_port = jsRoot["rdp_port"].asUInt(); + int ssh_port = jsRoot["rdp_port"].asUInt(); + std::string server_ip; + if (isIPAddress(host.c_str())) + { + server_ip = host; + } + else + { + char *ptr, **pptr; + struct hostent *hptr; + char IP[128] = { 0 }; + /* 取得命令后第一个参数,即要解析的域名或主机名 */ + ptr = (char*)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; /* 如果调用gethostbyname发生错误,返回1 */ + } + /* 将主机的规范名打出来 */ + //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; + //printf(" address:%s/n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); + break; + default: + printf("unknown address type/n"); + break; + } + } + if (!isIPAddress(server_ip.c_str())) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (TestTCPPort(server_ip, rdp_port) && TestTCPPort(server_ip, ssh_port)) + { + _create_json_ret(buf, TPE_OK); + return; + } + ICMPheaderRet temp = { 0 }; + int b_ok = ICMPSendTo(&temp, (char*)server_ip.c_str(), 16, 8); + if (b_ok == 0) + { + _create_json_ret(buf, TPE_OK); + return; + } + else + { + _create_json_ret(buf, TPE_NETWORK); + } + + return; +} + +void TsHttpRpc::_rpc_func_ts_rdp_play(const ex_astr& func_args, ex_astr& buf) +{ + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + + // 判断参数是否正确 + if (!jsRoot["host"].isString()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (!jsRoot["port"].isInt()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (!jsRoot["tail"].isString()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + ex_astr a_host = jsRoot["host"].asCString(); + int port = jsRoot["port"].asInt(); + 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; + 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_wstr w_host; + ex_astr2wstr(a_host, w_host); + + ex_wstr w_exe_path; + w_exe_path = _T("\""); + w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\""); + //swprintf_s(w_szCommandLine, _T(" -ssh -pw **** -P %d -l %s %s"), teleport_port, w_s_id.c_str(), w_teleport_ip.c_str()); + w_exe_path += _T(" "); + w_exe_path += w_url; + + w_exe_path += _T(" "); + w_exe_path += w_host; + + Json::Value root_ret; + ex_astr utf8_path; + ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8); + root_ret["path"] = utf8_path; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + if (!CreateProcess(NULL, (wchar_t *)w_exe_path.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + EXLOGE(_T("CreateProcess() failed. Error=0x%08X.\n %s\n"), GetLastError(), w_exe_path.c_str()); + root_ret["code"] = TPE_START_CLIENT; + _create_json_ret(buf, root_ret); + return; + } + + root_ret["code"] = TPE_OK; + _create_json_ret(buf, root_ret); + return; +} + +void TsHttpRpc::_rpc_func_get_config(const ex_astr& func_args, ex_astr& buf) +{ + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + // 判断参数是否正确 + if (!jsRoot["type"].isNumeric()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + int type = jsRoot["type"].asUInt(); + if (type == 1) + { + Json::Value jr_root; + Json::Value config_list; + + jr_root["code"] = 0; + + clientsetmap::iterator it; + for (it = g_cfgSSH.m_clientsetmap.begin(); it != g_cfgSSH.m_clientsetmap.end(); it++) + { + + Json::Value config; + ex_astr temp; + ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); + config["name"] = temp; + + ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); + config["path"] = temp; + + ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); + config["commandline"] = temp; + + ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); + config["alias_name"] = temp; + + ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); + config["desc"] = temp; + + config["build_in"] = it->second.is_default ? 1 : 0; + if (it->first == g_cfgSSH.m_current_client) + { + config["current"] = 1; + } + else { + config["current"] = 0; + } + + + config_list.append(config); + } + + jr_root["config_list"] = config_list; + _create_json_ret(buf, jr_root); + + return; + } + else if (type == 2) + { + Json::Value jr_root; + Json::Value config_list; + + jr_root["code"] = 0; + + clientsetmap::iterator it; + for (it = g_cfgScp.m_clientsetmap.begin(); it != g_cfgScp.m_clientsetmap.end(); it++) + { + + Json::Value config; + ex_astr temp; + ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); + config["name"] = temp; + + ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); + config["path"] = temp; + + ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); + config["commandline"] = temp; + + ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); + config["desc"] = temp; + + ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); + config["alias_name"] = temp; + + config["build_in"] = it->second.is_default ? 1 : 0; + + if (it->first == g_cfgScp.m_current_client) + config["current"] = 1; + else + config["current"] = 0; + + config_list.append(config); + } + + jr_root["config_list"] = config_list; + _create_json_ret(buf, jr_root); + return; + } + else if (type == 3) + { + Json::Value jr_root; + Json::Value config_list; + + jr_root["code"] = 0; + + clientsetmap::iterator it; + for (it = g_cfgTelnet.m_clientsetmap.begin(); it != g_cfgTelnet.m_clientsetmap.end(); it++) + { + Json::Value config; + ex_astr temp; + ex_wstr2astr(it->first, temp, EX_CODEPAGE_UTF8); + config["name"] = temp; + + ex_wstr2astr(it->second.path, temp, EX_CODEPAGE_UTF8); + config["path"] = temp; + + ex_wstr2astr(it->second.commandline, temp, EX_CODEPAGE_UTF8); + config["commandline"] = temp; + + ex_wstr2astr(it->second.desc, temp, EX_CODEPAGE_UTF8); + config["desc"] = temp; + + ex_wstr2astr(it->second.alias_name, temp, EX_CODEPAGE_UTF8); + config["alias_name"] = temp; + + config["build_in"] = it->second.is_default ? 1 : 0; + + if (it->first == g_cfgTelnet.m_current_client) + config["current"] = 1; + else + config["current"] = 0; + + config_list.append(config); + } + + jr_root["config_list"] = config_list; + _create_json_ret(buf, jr_root); + return; + } + else + { + _create_json_ret(buf, TPE_PARAM); + return; + } +} + +void TsHttpRpc::_rpc_func_set_config(const ex_astr& func_args, ex_astr& buf) +{ + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + if (jsRoot.isArray()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + + // 判断参数是否正确 + if (!jsRoot["name"].isString() || !jsRoot["path"].isString() || + !jsRoot["commandline"].isString() || + !jsRoot["type"].isNumeric()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + int type = jsRoot["type"].asUInt(); + ex_astr name = jsRoot["name"].asCString(); + ex_astr path = jsRoot["path"].asCString(); + ex_astr commandline = jsRoot["commandline"].asCString(); + + ex_wstr w_path; + ex_astr2wstr(path, w_path, EX_CODEPAGE_UTF8); + ex_wstr w_name; + ex_astr2wstr(name, w_name, EX_CODEPAGE_UTF8); + + ex_wstr w_commandline; + ex_astr2wstr(commandline, w_commandline, EX_CODEPAGE_UTF8); + + if (type == 1) + { + + clientsetmap::iterator it = g_cfgSSH.m_clientsetmap.find(w_name); + if (it == g_cfgSSH.m_clientsetmap.end()) { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (it->second.is_default) + { + g_cfgSSH.set(_T("common"), _T("current_client"), w_name); + g_cfgSSH.save(); + g_cfgSSH.init(); + _create_json_ret(buf, TPE_OK); + return; + } + g_cfgSSH.set(w_name, _T("path"), w_path); + g_cfgSSH.set(w_name, _T("command_line"), w_commandline); + g_cfgSSH.set(_T("common"), _T("current_client"), w_name); + + g_cfgSSH.save(); + g_cfgSSH.init(); + _create_json_ret(buf, TPE_OK); + return; + + } + else if (type == 2) + { + clientsetmap::iterator it = g_cfgScp.m_clientsetmap.find(w_name); + if (it == g_cfgScp.m_clientsetmap.end()) { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (it->second.is_default) + { + g_cfgScp.set(_T("common"), _T("current_client"), w_name); + g_cfgScp.save(); + g_cfgScp.init(); + _create_json_ret(buf, TPE_OK); + return; + } + g_cfgScp.set(w_name, _T("path"), w_path); + g_cfgScp.set(w_name, _T("command_line"), w_commandline); + g_cfgScp.set(_T("common"), _T("current_client"), w_name); + + g_cfgScp.save(); + g_cfgScp.init(); + _create_json_ret(buf, TPE_OK); + return; + } + else if (type == 3) + { + clientsetmap::iterator it = g_cfgTelnet.m_clientsetmap.find(w_name); + if (it == g_cfgTelnet.m_clientsetmap.end()) { + _create_json_ret(buf, TPE_PARAM); + return; + } + if (it->second.is_default) + { + g_cfgTelnet.set(_T("common"), _T("current_client"), w_name); + g_cfgTelnet.save(); + g_cfgTelnet.init(); + _create_json_ret(buf, TPE_OK); + return; + } + g_cfgTelnet.set(w_name, _T("path"), w_path); + g_cfgTelnet.set(w_name, _T("command_line"), w_commandline); + g_cfgTelnet.set(_T("common"), _T("current_client"), w_name); + + g_cfgTelnet.save(); + g_cfgTelnet.init(); + _create_json_ret(buf, TPE_OK); + return; + } + else { + _create_json_ret(buf, TPE_PARAM); + return; + } +} + +void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) { + + Json::Reader jreader; + Json::Value jsRoot; + + if (!jreader.parse(func_args.c_str(), jsRoot)) + { + _create_json_ret(buf, TPE_JSON_FORMAT); + return; + } + // 判断参数是否正确 + if (!jsRoot["action"].isNumeric()) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + int action = jsRoot["action"].asUInt(); + + HWND hParent = GetForegroundWindow(); + if (NULL == hParent) + hParent = g_hDlgMain; + + BOOL ret = FALSE; + wchar_t wszReturnPath[MAX_PATH] = _T(""); + + if (action == 1 || action == 2) + { + OPENFILENAME ofn; + ex_wstr wsDefaultName; + ex_wstr wsDefaultPath; + StringCchCopy(wszReturnPath, MAX_PATH, wsDefaultName.c_str()); + + ZeroMemory(&ofn, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.lpstrTitle = _T("选择文件"); + ofn.hwndOwner = hParent; + ofn.lpstrFilter = _T("可执行程序 (*.exe)\0*.exe\0"); + ofn.lpstrFile = wszReturnPath; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrInitialDir = wsDefaultPath.c_str(); + ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST; + + if (action == 1) + { + ofn.Flags |= OFN_FILEMUSTEXIST; + ret = GetOpenFileName(&ofn); + } + else + { + ofn.Flags |= OFN_OVERWRITEPROMPT; + ret = GetSaveFileName(&ofn); + } + } + else if (action == 3) + { + BROWSEINFO bi; + ZeroMemory(&bi, sizeof(BROWSEINFO)); + bi.hwndOwner = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = wszReturnPath; //此参数如为NULL则不能显示对话框 + bi.lpszTitle = _T("选择目录"); + bi.ulFlags = BIF_RETURNONLYFSDIRS; + bi.lpfn = NULL; + bi.iImage = 0; //初始化入口参数bi结束 + LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框 + if (pIDList) + { + ret = true; + SHGetPathFromIDList(pIDList, wszReturnPath); + } + else + { + ret = false; + } + } + else if (action == 4) + { + ex_wstr wsDefaultName; + ex_wstr wsDefaultPath; + + if (wsDefaultPath.length() == 0) + { + _create_json_ret(buf, TPE_PARAM); + return; + } + + ex_wstr::size_type pos = 0; + + while (ex_wstr::npos != (pos = wsDefaultPath.find(L"/", pos))) + { + wsDefaultPath.replace(pos, 1, L"\\"); + pos += 1; + } + + ex_wstr wArg = L"/select, \""; + wArg += wsDefaultPath; + wArg += L"\""; + if ((int)ShellExecute(hParent, _T("open"), _T("explorer"), wArg.c_str(), NULL, SW_SHOW) > 32) + ret = true; + else + ret = false; + } + + if (ret) + { + if (action == 1 || action == 2 || action == 3) + { + ex_astr utf8_path; + ex_wstr2astr(wszReturnPath, utf8_path, EX_CODEPAGE_UTF8); + Json::Value root; + root["path"] = utf8_path; + _create_json_ret(buf, root); + + return; + } + else + { + _create_json_ret(buf, TPE_OK); + return; + } + } + else + { + _create_json_ret(buf, TPE_DATA); + return; + } +} + +void TsHttpRpc::_rpc_func_get_version(const ex_astr& func_args, ex_astr& buf) +{ + Json::Value root_ret; + ex_wstr w_version = TP_ASSIST_VER; + ex_astr version; + ex_wstr2astr(w_version, version, EX_CODEPAGE_UTF8); + root_ret["version"] = version; + root_ret["code"] = TPE_OK; + _create_json_ret(buf, root_ret); + return; +} diff --git a/server/tp_core/common/base_env.cpp b/server/tp_core/common/base_env.cpp index 7c8aa92..ade1cd3 100644 --- a/server/tp_core/common/base_env.cpp +++ b/server/tp_core/common/base_env.cpp @@ -1,47 +1,47 @@ -#include "base_env.h" - -TppEnvBase::TppEnvBase() -{} - -TppEnvBase::~TppEnvBase() -{} - -bool TppEnvBase::init(TPP_INIT_ARGS* args) -{ - if (NULL == args) - { - EXLOGE("invalid init args(1).\n"); - return false; - } - - EXLOG_USE_LOGGER(args->logger); - - exec_path = args->exec_path; - etc_path = args->etc_path; - replay_path = args->replay_path; - - take_session = args->func_take_session; - free_session = args->func_free_session; - session_begin = args->func_session_begin; - session_end = args->func_session_end; - - if (NULL == take_session || NULL == free_session || NULL == session_begin || NULL == session_end) - { - EXLOGE("invalid init args(2).\n"); - return false; - } - - if (NULL == args->cfg) - { - EXLOGE("invalid init args(3).\n"); - return false; - } - - if (!_on_init(args)) - { - EXLOGE("invalid init args(4).\n"); - return false; - } - - return true; -} +#include "base_env.h" + +TppEnvBase::TppEnvBase() +{} + +TppEnvBase::~TppEnvBase() +{} + +bool TppEnvBase::init(TPP_INIT_ARGS* args) +{ + if (NULL == args) + { + EXLOGE("invalid init args(1).\n"); + return false; + } + + EXLOG_USE_LOGGER(args->logger); + + exec_path = args->exec_path; + etc_path = args->etc_path; + replay_path = args->replay_path; + + get_session = args->func_get_connect_info; + free_session = args->func_free_connect_info; + session_begin = args->func_session_begin; + session_end = args->func_session_end; + + if (NULL == get_session || NULL == free_session || NULL == session_begin || NULL == session_end) + { + EXLOGE("invalid init args(2).\n"); + return false; + } + + if (NULL == args->cfg) + { + EXLOGE("invalid init args(3).\n"); + return false; + } + + if (!_on_init(args)) + { + EXLOGE("invalid init args(4).\n"); + return false; + } + + return true; +} diff --git a/server/tp_core/common/base_env.h b/server/tp_core/common/base_env.h index 49fa6b7..237d0ef 100644 --- a/server/tp_core/common/base_env.h +++ b/server/tp_core/common/base_env.h @@ -1,28 +1,28 @@ -#ifndef __TS_BASE_ENV_H__ -#define __TS_BASE_ENV_H__ - -#include "protocol_interface.h" - -class TppEnvBase -{ -public: - TppEnvBase(); - virtual ~TppEnvBase(); - - bool init(TPP_INIT_ARGS* args); - -public: - ex_wstr exec_path; - ex_wstr etc_path; // 配置文件、SSH服务器的私钥文件的存放路径 - ex_wstr replay_path; - - TPP_TAKE_SESSION_FUNC take_session; - TPP_FREE_SESSION_FUNC free_session; - TPP_SESSION_BEGIN_FUNC session_begin; - TPP_SESSION_END_FUNC session_end; - -protected: - virtual bool _on_init(TPP_INIT_ARGS* args) = 0; -}; - -#endif // __TS_BASE_ENV_H__ +#ifndef __TS_BASE_ENV_H__ +#define __TS_BASE_ENV_H__ + +#include "protocol_interface.h" + +class TppEnvBase +{ +public: + TppEnvBase(); + virtual ~TppEnvBase(); + + bool init(TPP_INIT_ARGS* args); + +public: + ex_wstr exec_path; + ex_wstr etc_path; // 配置文件、SSH服务器的私钥文件的存放路径 + ex_wstr replay_path; + + TPP_GET_CONNNECT_INFO_FUNC get_session; + TPP_FREE_CONNECT_INFO_FUNC free_session; + TPP_SESSION_BEGIN_FUNC session_begin; + TPP_SESSION_END_FUNC session_end; + +protected: + virtual bool _on_init(TPP_INIT_ARGS* args) = 0; +}; + +#endif // __TS_BASE_ENV_H__ diff --git a/server/tp_core/common/base_record.cpp b/server/tp_core/common/base_record.cpp index a6a55f6..3a617fc 100644 --- a/server/tp_core/common/base_record.cpp +++ b/server/tp_core/common/base_record.cpp @@ -16,7 +16,7 @@ TppRecBase::~TppRecBase() { } -void TppRecBase::begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_SESSION_INFO* info) +void TppRecBase::begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info) { m_start_time = ex_get_tick_count(); diff --git a/server/tp_core/common/base_record.h b/server/tp_core/common/base_record.h index 8306a59..e060835 100644 --- a/server/tp_core/common/base_record.h +++ b/server/tp_core/common/base_record.h @@ -1,76 +1,97 @@ -#ifndef __TS_BASE_RECORD_H__ -#define __TS_BASE_RECORD_H__ - -#include "base_env.h" -#include "ts_membuf.h" -#include "protocol_interface.h" - -#include - -#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4 - -#pragma pack(push,1) - -// 录像文件头 -typedef struct TS_RECORD_HEADER -{ - ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record - ex_u16 ver; // 录像文件版本,目前为2 - ex_u16 protocol; // 协议:1=RDP, 2=SSH, 3=Telnet - ex_u64 timestamp; // 本次录像的起始时间(UTC时间戳) - ex_u32 packages; // 总包数 - ex_u32 time_ms; // 总耗时(毫秒) - ex_u16 width; // 初始屏幕尺寸:宽 - ex_u16 height; // 初始屏幕尺寸:高 - ex_u16 file_count; // 数据文件总数 - ex_u32 file_size; // 所有数据文件的总大小(不包括每个数据文件的头,即4字节的每文件大小) - char account[16]; // teleport账号 - char username[16]; // 远程主机用户名 - char ip[18]; - ex_u16 port; - - // RDP专有 - ex_u8 rdp_security; // 0 = RDP, 1 = TLS - - ex_u8 reserve[128 - 4 - 2 - 2 - 8 - 4 - 4 - 2 - 2 - 2 - 4 - 16 - 16 - 18 - 2 - 1]; // 保留 -}TS_RECORD_HEADER; - -// 一个数据包的头 -typedef struct TS_RECORD_PKG -{ - ex_u8 type; // 包的数据类型 - ex_u32 size; // 这个包的总大小(不含包头) - ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天) - ex_u8 reserve[3]; // 保留 -}TS_RECORD_PKG; - -#pragma pack(pop) - -class TppRecBase -{ -public: - TppRecBase(); - virtual ~TppRecBase(); - - void begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_SESSION_INFO* info); - void end(void); - - virtual void record(ex_u8 type, const ex_u8* data, size_t size) = 0; - -protected: - virtual void _on_begin(const TPP_SESSION_INFO* info) = 0; - virtual void _on_end(void) = 0; - -protected: - int m_protocol; - - ex_wstr m_base_path; // 录像文件基础路径,例如 /usr/local/eom/teleport/data/replay/ssh/123,数字编号是内部附加的,作为本次会话录像文件的目录名称 - ex_wstr m_base_fname; // 录像文件的文件名,不含扩展名部分,内部会以此为基础合成文件全名,并将录像文件存放在 m_base_path 指向的目录中 - - ex_u64 m_start_time; - ex_u64 m_last_time; - - MemBuffer m_cache; -}; - -#endif // __TS_BASE_RECORD_H__ +#ifndef __TS_BASE_RECORD_H__ +#define __TS_BASE_RECORD_H__ + +#include "base_env.h" +#include "ts_membuf.h" +#include "protocol_interface.h" + +#include + +#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4 + +#pragma pack(push,1) + +// 录像文件头(随着录像数据写入,会改变的部分) +typedef struct TS_RECORD_HEADER_INFO +{ + ex_u32 packages; // 总包数 + ex_u32 time_ms; // 总耗时(毫秒) + ex_u32 file_size; // 数据总大小(不包括文件头) +}TS_RECORD_HEADER_INFO; + +// 录像文件头(固定不变部分) +typedef struct TS_RECORD_HEADER_BASIC +{ + ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record + ex_u16 ver; // 录像文件版本,目前为3 + + ex_u16 protocol_type; // 协议:1=RDP, 2=SSH, 3=Telnet + ex_u16 protocol_sub_type; // 子协议:100=RDP, 200=SSH, 201=SFTP, 300=Telnet + ex_u64 timestamp; // 本次录像的起始时间(UTC时间戳) + ex_u16 width; // 初始屏幕尺寸:宽 + ex_u16 height; // 初始屏幕尺寸:高 + char user_name[32]; // teleport账号 + char account_name[32]; // 远程主机用户名 + + char real_remote_host_ip[40]; // 远程主机IP + char remote_host_ip[40]; // 远程主机IP + ex_u16 remote_host_port; // 远程主机端口 + + char client_ip[40]; // 客户端IP + + // RDP专有 + ex_u8 rdp_security; // 0 = RDP, 1 = TLS + + ex_u8 reserve[256 - 4 - 2 - 2 - 2 - 8 - 2 - 2 - 32 - 32 - 40 - 2 - 40 - 40 - 1 - 12]; // 保留,其中,最后12B是为header-info留出的空间 +}TS_RECORD_HEADER_BASIC; +#define ts_record_header_basic_size sizeof(TS_RECORD_HEADER_BASIC) + +typedef struct TS_RECORD_HEADER +{ + TS_RECORD_HEADER_INFO info; + TS_RECORD_HEADER_BASIC basic; +}TS_RECORD_HEADER; + +// header部分(header-info + header-basic) = 256B +#define ts_record_header_size sizeof(TS_RECORD_HEADER) + + +// 一个数据包的头 +typedef struct TS_RECORD_PKG +{ + ex_u8 type; // 包的数据类型 + ex_u32 size; // 这个包的总大小(不含包头) + ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天) + ex_u8 reserve[3]; // 保留 +}TS_RECORD_PKG; + +#pragma pack(pop) + +class TppRecBase +{ +public: + TppRecBase(); + virtual ~TppRecBase(); + + void begin(const wchar_t* base_path, const wchar_t* base_fname, int record_id, const TPP_CONNECT_INFO* info); + void end(void); + + virtual void record(ex_u8 type, const ex_u8* data, size_t size) = 0; + +protected: + virtual void _on_begin(const TPP_CONNECT_INFO* info) = 0; + virtual void _on_end(void) = 0; + +protected: + int m_protocol; + + ex_wstr m_base_path; // 录像文件基础路径,例如 /usr/local/eom/teleport/data/replay/ssh/123,数字编号是内部附加的,作为本次会话录像文件的目录名称 + ex_wstr m_base_fname; // 录像文件的文件名,不含扩展名部分,内部会以此为基础合成文件全名,并将录像文件存放在 m_base_path 指向的目录中 + + ex_u64 m_start_time; + ex_u64 m_last_time; + + MemBuffer m_cache; +}; + +#endif // __TS_BASE_RECORD_H__ diff --git a/server/tp_core/common/protocol_interface.h b/server/tp_core/common/protocol_interface.h index f47fcca..06ecd02 100644 --- a/server/tp_core/common/protocol_interface.h +++ b/server/tp_core/common/protocol_interface.h @@ -1,73 +1,75 @@ -#ifndef __TP_PROTOCOL_INTERFACE_H__ -#define __TP_PROTOCOL_INTERFACE_H__ - -#include "ts_const.h" -#include - -#ifdef EX_OS_WIN32 -# ifdef TPP_EXPORTS -# define TPP_API __declspec(dllexport) -# else -# define TPP_API __declspec(dllimport) -# endif -#else -# define TPP_API -#endif - -typedef struct TPP_SESSION_INFO -{ - char* sid; - char* account_name; // 申请本次连接的用户名 - char* host_ip; - char* user_name; - char* user_auth; - char* user_param; - int host_port; - int protocol; - int auth_id; - int auth_mode; - int sys_type; - int ref_count; // 这个session可以被take_session()多少次 - ex_u64 ticket_start; -}TPP_SESSION_INFO; - -typedef TPP_SESSION_INFO* (*TPP_TAKE_SESSION_FUNC)(const char* sid); -typedef void(*TPP_FREE_SESSION_FUNC)(TPP_SESSION_INFO* info); -typedef bool(*TPP_SESSION_BEGIN_FUNC)(const TPP_SESSION_INFO* info, int* db_id); -typedef bool(*TPP_SESSION_END_FUNC)(int db_id, int ret); - - -typedef struct TPP_INIT_ARGS -{ - ExLogger* logger; - ex_wstr exec_path; - ex_wstr etc_path; - ex_wstr replay_path; - ExIniFile* cfg; - - TPP_TAKE_SESSION_FUNC func_take_session; - TPP_FREE_SESSION_FUNC func_free_session; - TPP_SESSION_BEGIN_FUNC func_session_begin; - TPP_SESSION_END_FUNC func_session_end; -}TPP_INIT_ARGS; - - - -#ifdef __cplusplus -extern "C" -{ -#endif - - TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args); - TPP_API ex_rv tpp_start(void); - TPP_API ex_rv tpp_stop(void); - -#ifdef __cplusplus -} -#endif - -typedef ex_rv (*TPP_INIT_FUNC)(TPP_INIT_ARGS* init_args); -typedef ex_rv (*TPP_START_FUNC)(void); -typedef ex_rv (*TPP_STOP_FUNC)(void); - -#endif // __TP_PROTOCOL_INTERFACE_H__ +#ifndef __TP_PROTOCOL_INTERFACE_H__ +#define __TP_PROTOCOL_INTERFACE_H__ + +#include "ts_const.h" +#include + +#ifdef EX_OS_WIN32 +# ifdef TPP_EXPORTS +# define TPP_API __declspec(dllexport) +# else +# define TPP_API __declspec(dllimport) +# endif +#else +# define TPP_API +#endif + +typedef struct TPP_CONNECT_INFO +{ + char* sid; + char* user_name; // 申请本次连接的用户名 + char* real_remote_host_ip; // 真正的远程主机IP(如果是直接连接模式,则与remote_host_ip相同) + char* remote_host_ip; // 要连接的远程主机的IP(如果是端口映射模式,则为路由主机的IP) + char* account_name; // 远程主机的账号 + char* account_secret; // 远程主机账号的密码(或者私钥) + char* user_param; + int remote_host_port; // 要连接的远程主机的端口(如果是端口映射模式,则为路由主机的端口) + int protocol_type; + int protocol_sub_type; + //int auth_id; + int auth_type; + int sys_type; + int ref_count; // 这个连接信息的引用计数,如果创建的连接信息从来未被使用,则超过60秒后自动销毁 + ex_u64 ticket_start; // 此连接信息的创建时间(用于超时未使用就销毁的功能) +}TPP_CONNECT_INFO; + +typedef TPP_CONNECT_INFO* (*TPP_GET_CONNNECT_INFO_FUNC)(const char* sid); +typedef void(*TPP_FREE_CONNECT_INFO_FUNC)(TPP_CONNECT_INFO* info); +typedef bool(*TPP_SESSION_BEGIN_FUNC)(const TPP_CONNECT_INFO* info, int* db_id); +typedef bool(*TPP_SESSION_END_FUNC)(const char* sid, int db_id, int ret); + + +typedef struct TPP_INIT_ARGS +{ + ExLogger* logger; + ex_wstr exec_path; + ex_wstr etc_path; + ex_wstr replay_path; + ExIniFile* cfg; + + TPP_GET_CONNNECT_INFO_FUNC func_get_connect_info; + TPP_FREE_CONNECT_INFO_FUNC func_free_connect_info; + TPP_SESSION_BEGIN_FUNC func_session_begin; + TPP_SESSION_END_FUNC func_session_end; +}TPP_INIT_ARGS; + + + +#ifdef __cplusplus +extern "C" +{ +#endif + + TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args); + TPP_API ex_rv tpp_start(void); + TPP_API ex_rv tpp_stop(void); + +#ifdef __cplusplus +} +#endif + +typedef ex_rv (*TPP_INIT_FUNC)(TPP_INIT_ARGS* init_args); +typedef ex_rv (*TPP_START_FUNC)(void); +typedef ex_rv (*TPP_STOP_FUNC)(void); + +#endif // __TP_PROTOCOL_INTERFACE_H__ diff --git a/server/tp_core/common/ts_const.h b/server/tp_core/common/ts_const.h index 70acb7d..060bae2 100644 --- a/server/tp_core/common/ts_const.h +++ b/server/tp_core/common/ts_const.h @@ -3,18 +3,18 @@ //#include "ts_types.h" -// #define TS_RDP_PROXY_PORT 3389 -// #define TS_RDP_PROXY_HOST "0.0.0.0" -// -// #define TS_SSH_PROXY_PORT 22 -// #define TS_SSH_PROXY_HOST "0.0.0.0" -// -// #define TS_TELNET_PROXY_PORT 23 -// #define TS_TELNET_PROXY_HOST "0.0.0.0" +#define TS_RDP_PROXY_PORT 52089 +#define TS_RDP_PROXY_HOST "0.0.0.0" + +#define TS_SSH_PROXY_PORT 52189 +#define TS_SSH_PROXY_HOST "0.0.0.0" + +#define TS_TELNET_PROXY_PORT 52389 +#define TS_TELNET_PROXY_HOST "0.0.0.0" #define TS_HTTP_RPC_PORT 52080 -#define TS_HTTP_RPC_HOST "127.0.0.1" -//#define TS_HTTP_RPC_HOST "0.0.0.0" +//#define TS_HTTP_RPC_HOST "127.0.0.1" +#define TS_HTTP_RPC_HOST "localhost" #define TS_RDP_PROTOCOL_RDP 0 diff --git a/server/tp_core/core/ts_env.cpp b/server/tp_core/core/ts_env.cpp index f5466a7..06a3a4c 100644 --- a/server/tp_core/core/ts_env.cpp +++ b/server/tp_core/core/ts_env.cpp @@ -128,8 +128,8 @@ bool TsEnv::init(bool load_config) else { ex_wstr2astr(tmp, rpc_bind_ip); - if (rpc_bind_ip == "localhost") - rpc_bind_ip = "127.0.0.1"; + //if (rpc_bind_ip == "localhost") + // rpc_bind_ip = "127.0.0.1"; } if (!ps->GetInt(L"bind-port", rpc_bind_port)) diff --git a/server/tp_core/core/ts_http_rpc.cpp b/server/tp_core/core/ts_http_rpc.cpp index d00a01a..2b5d600 100644 --- a/server/tp_core/core/ts_http_rpc.cpp +++ b/server/tp_core/core/ts_http_rpc.cpp @@ -647,181 +647,3 @@ void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf) jr_data["c"] = cipher_text; _create_json_ret(buf, TPE_OK, jr_data); } - -#if 0 -void TsHttpRpc::_rpc_func_get_auth_id(const ex_astr& func_args, ex_astr& buf) -{ - // 获取所有的或者指定主机的认证ID - // 入参: {"host":"host-ip-address"} 或者 无 - // 示例: {"host":"123.45.67.89"} - // host: 要查询的主机的IP地址 - // 返回: - // data域为一个列表,其中每一个元素为一组键值对。 - // - // 错误返回: {"code":1234} - - Json::Reader jreader; - Json::Value jsRoot; - - AuthInfo2Vec ret; - - if (0 == func_args.length()) - { - if (!g_db.get_auth_id_list_by_all(ret)) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - } - else - { - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TSR_INVALID_JSON_FORMAT); - return; - } - if (jsRoot.isArray()) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - ex_astr host_ip; - - if (jsRoot["host"].isNull() || !jsRoot["host"].isString()) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - host_ip = jsRoot["host"].asCString(); - if (host_ip.length() == 0) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - if (!g_db.get_auth_id_list_by_ip(host_ip, ret)) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - } - - if (ret.size() == 0) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - - //EXLOGV("encrypt: [%s]=>[%s]\n", plain_text.c_str(), cipher_text.c_str()); - - Json::Value jr_root; - jr_root["code"] = TSR_OK; - - int i = 0; - AuthInfo2Vec::iterator it = ret.begin(); - for (; it != ret.end(); ++it) - { - jr_root["data"][i]["auth_id"] = (*it).auth_id; - jr_root["data"][i]["host_id"] = (*it).host_id; - jr_root["data"][i]["host_ip"] = (*it).host_ip; - jr_root["data"][i]["protocol"] = (*it).pro_type; - jr_root["data"][i]["auth_mode"] = (*it).auth_mode; - jr_root["data"][i]["host_status"] = (*it).host_lock; - - i++; - } - - _create_json_ret(buf, jr_root); -} - -void TsHttpRpc::_rpc_func_get_auth_info(const ex_astr& func_args, ex_astr& buf) -{ - // 获取所有的或者指定主机的认证INFO - // 入参: {"host":"host-ip-address"} 或者 无 - // 示例: {"host":"123.45.67.89"} - // host: 要查询的主机的IP地址 - // 返回: - // data域为一个列表,其中每一个元素为一组键值对。 - // - // 错误返回: {"code":1234} - - Json::Reader jreader; - Json::Value jsRoot; - - AuthInfo3Vec ret; - - if (0 == func_args.length()) - { - if (!g_db.get_auth_info_list_by_all(ret)) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - } - else - { - if (!jreader.parse(func_args.c_str(), jsRoot)) - { - _create_json_ret(buf, TSR_INVALID_JSON_FORMAT); - return; - } - if (jsRoot.isArray()) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - ex_astr host_ip; - - if (jsRoot["host"].isNull() || !jsRoot["host"].isString()) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - host_ip = jsRoot["host"].asCString(); - if (host_ip.length() == 0) - { - _create_json_ret(buf, TSR_INVALID_JSON_PARAM); - return; - } - - if (!g_db.get_auth_info_list_by_ip(host_ip, ret)) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - } - - if (ret.size() == 0) - { - _create_json_ret(buf, TSR_DATA_LEN_ZERO); - return; - } - - //EXLOGV("encrypt: [%s]=>[%s]\n", plain_text.c_str(), cipher_text.c_str()); - - Json::Value jr_root; - jr_root["code"] = TSR_OK; - - int i = 0; - AuthInfo3Vec::iterator it = ret.begin(); - for (; it != ret.end(); ++it) - { - jr_root["data"][i]["host_id"] = (*it).host_id; - jr_root["data"][i]["host_ip"] = (*it).host_ip; - jr_root["data"][i]["username"] = (*it).host_user_name; - jr_root["data"][i]["password"] = (*it).host_user_pwd; - jr_root["data"][i]["auth_mode"] = (*it).auth_mode; - jr_root["data"][i]["key_id"] = (*it).cert_id; - jr_root["data"][i]["key_pri"] = (*it).cert_pri; - jr_root["data"][i]["key_pub"] = (*it).cert_pub; - - i++; - } - - _create_json_ret(buf, jr_root); -} -#endif diff --git a/server/tp_core/core/ts_main.cpp b/server/tp_core/core/ts_main.cpp index 9c312a1..3c90050 100644 --- a/server/tp_core/core/ts_main.cpp +++ b/server/tp_core/core/ts_main.cpp @@ -9,32 +9,34 @@ bool g_exit_flag = false; -TPP_SESSION_INFO* tpp_take_session(const char* sid) +TPP_CONNECT_INFO* tpp_get_session(const char* sid) { TS_SESSION_INFO sinfo; bool ret = g_session_mgr.take_session(sid, sinfo); if (!ret) return NULL; - TPP_SESSION_INFO* info = (TPP_SESSION_INFO*)calloc(1, sizeof(TPP_SESSION_INFO)); + TPP_CONNECT_INFO* info = (TPP_CONNECT_INFO*)calloc(1, sizeof(TPP_CONNECT_INFO)); info->sid = (char*)calloc(1, sinfo.sid.length() + 1); ex_strcpy(info->sid, sinfo.sid.length() + 1, sinfo.sid.c_str()); info->account_name = (char*)calloc(1, sinfo.account_name.length() + 1); ex_strcpy(info->account_name, sinfo.account_name.length() + 1, sinfo.account_name.c_str()); - info->host_ip = (char*)calloc(1, sinfo.host_ip.length() + 1); - ex_strcpy(info->host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str()); + info->real_remote_host_ip = (char*)calloc(1, sinfo.host_ip.length() + 1); + ex_strcpy(info->real_remote_host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str()); + info->remote_host_ip = (char*)calloc(1, sinfo.host_ip.length() + 1); + ex_strcpy(info->remote_host_ip, sinfo.host_ip.length() + 1, sinfo.host_ip.c_str()); info->user_name = (char*)calloc(1, sinfo.user_name.length() + 1); ex_strcpy(info->user_name, sinfo.user_name.length() + 1, sinfo.user_name.c_str()); - info->user_auth = (char*)calloc(1, sinfo.user_auth.length() + 1); - ex_strcpy(info->user_auth, sinfo.user_auth.length() + 1, sinfo.user_auth.c_str()); + info->account_secret = (char*)calloc(1, sinfo.user_auth.length() + 1); + ex_strcpy(info->account_secret, sinfo.user_auth.length() + 1, sinfo.user_auth.c_str()); info->user_param = (char*)calloc(1, sinfo.user_param.length() + 1); ex_strcpy(info->user_param, sinfo.user_param.length() + 1, sinfo.user_param.c_str()); - info->auth_id = sinfo.auth_id; - info->host_port = sinfo.host_port; - info->protocol = sinfo.protocol; - info->auth_mode = sinfo.auth_mode; + //info->auth_id = sinfo.auth_id; + info->remote_host_port = sinfo.host_port; + info->protocol_type = sinfo.protocol; + info->auth_type= sinfo.auth_mode; info->sys_type = sinfo.sys_type; info->ref_count = sinfo.ref_count; info->ticket_start = sinfo.ticket_start; @@ -42,21 +44,22 @@ TPP_SESSION_INFO* tpp_take_session(const char* sid) return info; } -void tpp_free_session(TPP_SESSION_INFO* info) +void tpp_free_session(TPP_CONNECT_INFO* info) { if (NULL == info) return; free(info->sid); - free(info->account_name); - free(info->host_ip); free(info->user_name); - free(info->user_auth); + free(info->real_remote_host_ip); + free(info->remote_host_ip); + free(info->account_name); + free(info->account_secret); free(info->user_param); free(info); } -bool tpp_session_begin(const TPP_SESSION_INFO* info, int* db_id) +bool tpp_session_begin(const TPP_CONNECT_INFO* info, int* db_id) { if (NULL == info || NULL == db_id) return false; @@ -79,9 +82,9 @@ bool tpp_session_begin(const TPP_SESSION_INFO* info, int* db_id) return ts_web_rpc_session_begin(sinfo, *db_id); } -bool tpp_session_end(int db_id, int ret) +bool tpp_session_end(const char* sid, int db_id, int ret) { - return ts_web_rpc_session_end(db_id, ret); + return ts_web_rpc_session_end(sid, db_id, ret); } typedef struct TPP_LIB diff --git a/server/tp_core/core/ts_session.cpp b/server/tp_core/core/ts_session.cpp index 070ffcc..3aeb3d9 100644 --- a/server/tp_core/core/ts_session.cpp +++ b/server/tp_core/core/ts_session.cpp @@ -105,7 +105,7 @@ ex_rv TsSessionManager::request_session( return EXRV_FAILED; } -bool TsSessionManager::take_session(const ex_astr& sid, TS_SESSION_INFO& info) +bool TsSessionManager::get_session(const ex_astr& sid, TS_SESSION_INFO& info) { ExThreadSmartLock locker(m_lock); @@ -129,12 +129,12 @@ bool TsSessionManager::take_session(const ex_astr& sid, TS_SESSION_INFO& info) info.ref_count = it->second->ref_count; info.ticket_start = it->second->ticket_start; - it->second->ref_count--; - if (it->second->ref_count <= 0) - { - delete it->second; - m_sessions.erase(it); - } + it->second->ref_count++; +// if (it->second->ref_count <= 0) +// { +// delete it->second; +// m_sessions.erase(it); +// } return true; } diff --git a/server/tp_core/core/ts_session.h b/server/tp_core/core/ts_session.h index 76d3dc6..651341e 100644 --- a/server/tp_core/core/ts_session.h +++ b/server/tp_core/core/ts_session.h @@ -1,73 +1,73 @@ -#ifndef __TS_SESSION_H__ -#define __TS_SESSION_H__ - -#include "../common/ts_const.h" -#include "../common/protocol_interface.h" - -#include - -typedef struct TS_SESSION_INFO -{ - ex_astr sid; - ex_astr account_name; // 申请本次连接的用户名 - - int auth_id; - ex_astr host_ip; - int host_port; - int protocol; - ex_astr user_name; - ex_astr user_auth; - ex_astr user_param; - int auth_mode; - int sys_type; - - int ref_count; // 这个session可以被take_session()多少次 - ex_u64 ticket_start; -}TS_SESSION_INFO; - -typedef std::map ts_sessiones; - -class TsSessionManager : public ExThreadBase -{ -public: - TsSessionManager(); - ~TsSessionManager(); - - // 申请一个session-id。 - ex_rv request_session( - ex_astr& sid, // 返回的session-id - ex_astr account_name, - int auth_id, - const ex_astr& host_ip, // 要连接的主机IP - int host_port, // 要连接的主机端口 - int sys_type, // 主机操作系统类型 - int protocol, // 要使用的协议,1=rdp, 2=ssh - const ex_astr& user_name, // 认证信息中的用户名 - const ex_astr& user_auth, // 认证信息,密码或私钥 - const ex_astr& user_param, // - int auth_mode // 认证方式,1=password,2=private-key - ); - - // 根据sid得到session信息,然后被查询的sid被从session管理器列表中移除 - bool take_session(const ex_astr& sid, TS_SESSION_INFO& info); - -protected: - // 线程循环 - void _thread_loop(void); - // 设置停止标志,让线程能够正常结束 - void _set_stop_flag(void); - -private: - bool _add_session(ex_astr& sid, TS_SESSION_INFO* info); - void _gen_session_id(ex_astr& sid, const TS_SESSION_INFO* info, int len); - void _check_sessions(void); - -private: - ExThreadLock m_lock; - ts_sessiones m_sessions; -}; - -extern TsSessionManager g_session_mgr; - -#endif // __TS_SESSION_H__ - +#ifndef __TS_SESSION_H__ +#define __TS_SESSION_H__ + +#include "../common/ts_const.h" +#include "../common/protocol_interface.h" + +#include + +typedef struct TS_SESSION_INFO +{ + ex_astr sid; + ex_astr account_name; // 申请本次连接的用户名 + + //int auth_id; + ex_astr host_ip; + int host_port; + int protocol; + ex_astr user_name; + ex_astr user_auth; + ex_astr user_param; + int auth_mode; + int sys_type; + + int ref_count; + ex_u64 ticket_start; +}TS_SESSION_INFO; + +typedef std::map ts_sessiones; + +class TsSessionManager : public ExThreadBase +{ +public: + TsSessionManager(); + ~TsSessionManager(); + + // 申请一个session-id。 + ex_rv request_session( + ex_astr& sid, // 返回的session-id + ex_astr account_name, + int auth_id, + const ex_astr& host_ip, // 要连接的主机IP + int host_port, // 要连接的主机端口 + int sys_type, // 主机操作系统类型 + int protocol, // 要使用的协议,1=rdp, 2=ssh + const ex_astr& user_name, // 认证信息中的用户名 + const ex_astr& user_auth, // 认证信息,密码或私钥 + const ex_astr& user_param, // + int auth_mode // 认证方式,1=password,2=private-key + ); + + // 根据sid得到session信息 + bool get_session(const ex_astr& sid, TS_SESSION_INFO& info); + +protected: + // 线程循环 + void _thread_loop(void); + // 设置停止标志,让线程能够正常结束 + void _set_stop_flag(void); + +private: + bool _add_session(ex_astr& sid, TS_SESSION_INFO* info); + void _gen_session_id(ex_astr& sid, const TS_SESSION_INFO* info, int len); + void _check_sessions(void); + +private: + ExThreadLock m_lock; + ts_sessiones m_sessions; +}; + +extern TsSessionManager g_session_mgr; + +#endif // __TS_SESSION_H__ + diff --git a/server/tp_core/core/ts_web_rpc.cpp b/server/tp_core/core/ts_web_rpc.cpp index ac85c86..349d31b 100644 --- a/server/tp_core/core/ts_web_rpc.cpp +++ b/server/tp_core/core/ts_web_rpc.cpp @@ -144,8 +144,11 @@ bool ts_web_rpc_session_begin(TS_SESSION_INFO& info, int& record_id) } //session 结束 -bool ts_web_rpc_session_end(int record_id, int ret_code) +bool ts_web_rpc_session_end(const char* sid, int record_id, int ret_code) { + // TODO: 对指定的sid相关的会话的引用计数减一(但减到0时销毁) + + Json::FastWriter json_writer; Json::Value jreq; jreq["method"] = "session_end"; diff --git a/server/tp_core/core/ts_web_rpc.h b/server/tp_core/core/ts_web_rpc.h index 331a28e..a9d3a91 100644 --- a/server/tp_core/core/ts_web_rpc.h +++ b/server/tp_core/core/ts_web_rpc.h @@ -14,7 +14,7 @@ int ts_web_rpc_get_conn_info(int conn_id, Json::Value& jret); // 记录会话的开始 bool ts_web_rpc_session_begin(TS_SESSION_INFO& info, int& record_id); //session 结束 -bool ts_web_rpc_session_end(int id, int ret_code); +bool ts_web_rpc_session_end(const char* sid, int id, int ret_code); #endif // __TS_WEB_RPC_H__ diff --git a/server/tp_core/protocol/ssh/ssh_recorder.cpp b/server/tp_core/protocol/ssh/ssh_recorder.cpp index 6e0f5a2..0fc24f0 100644 --- a/server/tp_core/protocol/ssh/ssh_recorder.cpp +++ b/server/tp_core/protocol/ssh/ssh_recorder.cpp @@ -1,4 +1,5 @@ #include "ssh_recorder.h" +#include static ex_u8 TPP_RECORD_MAGIC[4] = { 'T', 'P', 'P', 'R' }; @@ -7,9 +8,8 @@ TppSshRec::TppSshRec() m_cmd_cache.reserve(MAX_SIZE_PER_FILE); memset(&m_head, 0, sizeof(TS_RECORD_HEADER)); - memcpy((ex_u8*)(&m_head.magic), TPP_RECORD_MAGIC, sizeof(ex_u32)); - m_head.ver = 0x02; - m_head.protocol = TS_PROXY_PROTOCOL_SSH; + memcpy((ex_u8*)(&m_head.basic.magic), TPP_RECORD_MAGIC, sizeof(ex_u32)); + m_head.basic.ver = 0x02; } TppSshRec::~TppSshRec() @@ -17,19 +17,22 @@ TppSshRec::~TppSshRec() end(); } -void TppSshRec::_on_begin(const TPP_SESSION_INFO* info) +void TppSshRec::_on_begin(const TPP_CONNECT_INFO* info) { if (NULL == info) return; - m_head.timestamp = time(NULL); - m_head.port = info->host_port; + m_head.basic.timestamp = time(NULL); + m_head.basic.protocol_type = info->protocol_type; + m_head.basic.protocol_sub_type = info->protocol_sub_type; + m_head.basic.remote_host_port = info->remote_host_port; // memcpy(m_head.account, info.account_name.c_str(), info.account_name.length() > 15 ? 15 : info.account_name.length()); // memcpy(m_head.username, info.user_name.c_str(), info.user_name.length() > 15 ? 15 : info.user_name.length()); // memcpy(m_head.ip, info.host_ip.c_str(), info.host_ip.length() > 17 ? 17 : info.host_ip.length()); - memcpy(m_head.account, info->account_name, strlen(info->account_name) > 15 ? 15 : strlen(info->account_name)); - memcpy(m_head.username, info->user_name, strlen(info->user_name) > 15 ? 15 : strlen(info->user_name)); - memcpy(m_head.ip, info->host_ip, strlen(info->host_ip) > 17 ? 17 : strlen(info->host_ip)); + memcpy(m_head.basic.account_name, info->account_name, strlen(info->account_name) >= 31 ? 31 : strlen(info->account_name)); + memcpy(m_head.basic.user_name, info->user_name, strlen(info->user_name) >= 31 ? 31 : strlen(info->user_name)); + memcpy(m_head.basic.real_remote_host_ip, info->real_remote_host_ip, strlen(info->real_remote_host_ip) >= 39 ? 39 : strlen(info->real_remote_host_ip)); + memcpy(m_head.basic.remote_host_ip, info->remote_host_ip, strlen(info->remote_host_ip) >= 39 ? 39 : strlen(info->remote_host_ip)); } void TppSshRec::_on_end(void) @@ -42,7 +45,7 @@ void TppSshRec::_on_end(void) // 更新头信息 //m_head.timestamp = m_start_time; - m_head.time_ms = (ex_u32)(m_last_time - m_start_time); + m_head.info.time_ms = (ex_u32)(m_last_time - m_start_time); ex_wstr fname = m_base_path; ex_path_join(fname, false, m_base_fname.c_str(), NULL); @@ -64,7 +67,7 @@ void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size) { if (data == NULL || 0 == size) return; - m_head.packages++; + m_head.info.packages++; if (sizeof(TS_RECORD_PKG) + size + m_cache.size() > m_cache.buffer_size()) _save_to_data_file(); @@ -86,8 +89,8 @@ void TppSshRec::record(ex_u8 type, const ex_u8* data, size_t size) void TppSshRec::record_win_size_startup(int width, int height) { - m_head.width = width; - m_head.height = height; + m_head.basic.width = width; + m_head.basic.height = height; } void TppSshRec::record_win_size_change(int width, int height) @@ -127,7 +130,7 @@ void TppSshRec::record_command(const ex_astr cmd) bool TppSshRec::_save_to_data_file(void) { wchar_t _str_file_id[24] = { 0 }; - ex_wcsformat(_str_file_id, 24, L".%03d", m_head.file_count); + ex_wcsformat(_str_file_id, 24, L".%03d", 0);// m_head.file_count); ex_wstr fname = m_base_path; ex_path_join(fname, false, m_base_fname.c_str(), NULL); @@ -148,8 +151,8 @@ bool TppSshRec::_save_to_data_file(void) fflush(f); fclose(f); - m_head.file_count++; - m_head.file_size += m_cache.size(); + //m_head.file_count++; + //m_head.file_size += m_cache.size(); m_cache.empty(); return true; diff --git a/server/tp_core/protocol/ssh/ssh_recorder.h b/server/tp_core/protocol/ssh/ssh_recorder.h index 08d52a8..f6c6d8a 100644 --- a/server/tp_core/protocol/ssh/ssh_recorder.h +++ b/server/tp_core/protocol/ssh/ssh_recorder.h @@ -1,72 +1,72 @@ -#ifndef __TPP_SSH_RECORDER_H__ -#define __TPP_SSH_RECORDER_H__ - -#include "../../common/base_record.h" - -#define TS_RECORD_TYPE_SSH_TERM_SIZE 0x01 // 终端大小(行数与列数) -#define TS_RECORD_TYPE_SSH_DATA 0x02 // 用于展示的数据内容 - -#pragma pack(push,1) - -// 录像文件头 -// typedef struct TS_RECORD_HEADER -// { -// ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record -// ex_u64 timestamp; // 本次录像的起始时间(UTC时间戳) -// ex_u32 packages; // 总包数 -// ex_u32 time_ms; // 总耗时(毫秒) -// ex_u16 width; // 初始屏幕尺寸:宽 -// ex_u16 height; // 初始屏幕尺寸:高 -// ex_u16 file_count; // 数据文件总数 -// ex_u32 file_size; // 所有数据文件的总大小(不包括每个数据文件的头,即4字节的每文件大小) -// char account[16]; // teleport账号 -// char username[16]; // 远程主机用户名 -// char ip[18]; -// ex_u16 port; -// -// ex_u8 reserve[128 - 4 - 8 - 4 - 4 - 2 - 2 - 2 - 4 - 16 - 16 - 18 - 2]; // 保留 -// }TS_RECORD_HEADER; -// -// // 一个数据包的头 -// typedef struct TS_RECORD_PKG -// { -// ex_u8 type; // 包的数据类型 -// ex_u32 size; // 这个包的总大小(不含包头) -// ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天) -// ex_u8 reserve[3]; // 保留 -// }TS_RECORD_PKG; - -// 记录窗口大小改变的数据包 -typedef struct TS_RECORD_WIN_SIZE -{ - ex_u16 width; - ex_u16 height; -}TS_RECORD_WIN_SIZE; - -#pragma pack(pop) - -class TppSshRec : public TppRecBase -{ -public: - TppSshRec(); - virtual ~TppSshRec(); - - void record(ex_u8 type, const ex_u8* data, size_t size); - void record_win_size_startup(int width, int height); - void record_win_size_change(int width, int height); - void record_command(const ex_astr cmd); - -protected: - void _on_begin(const TPP_SESSION_INFO* info); - void _on_end(void); - - bool _save_to_data_file(void); - bool _save_to_cmd_file(void); - -protected: - TS_RECORD_HEADER m_head; - - MemBuffer m_cmd_cache; -}; - -#endif // __TPP_SSH_RECORDER_H__ +#ifndef __TPP_SSH_RECORDER_H__ +#define __TPP_SSH_RECORDER_H__ + +#include "../../common/base_record.h" + +#define TS_RECORD_TYPE_SSH_TERM_SIZE 0x01 // 终端大小(行数与列数) +#define TS_RECORD_TYPE_SSH_DATA 0x02 // 用于展示的数据内容 + +#pragma pack(push,1) + +// 录像文件头 +// typedef struct TS_RECORD_HEADER +// { +// ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record +// ex_u64 timestamp; // 本次录像的起始时间(UTC时间戳) +// ex_u32 packages; // 总包数 +// ex_u32 time_ms; // 总耗时(毫秒) +// ex_u16 width; // 初始屏幕尺寸:宽 +// ex_u16 height; // 初始屏幕尺寸:高 +// ex_u16 file_count; // 数据文件总数 +// ex_u32 file_size; // 所有数据文件的总大小(不包括每个数据文件的头,即4字节的每文件大小) +// char account[16]; // teleport账号 +// char username[16]; // 远程主机用户名 +// char ip[18]; +// ex_u16 port; +// +// ex_u8 reserve[128 - 4 - 8 - 4 - 4 - 2 - 2 - 2 - 4 - 16 - 16 - 18 - 2]; // 保留 +// }TS_RECORD_HEADER; +// +// // 一个数据包的头 +// typedef struct TS_RECORD_PKG +// { +// ex_u8 type; // 包的数据类型 +// ex_u32 size; // 这个包的总大小(不含包头) +// ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天) +// ex_u8 reserve[3]; // 保留 +// }TS_RECORD_PKG; + +// 记录窗口大小改变的数据包 +typedef struct TS_RECORD_WIN_SIZE +{ + ex_u16 width; + ex_u16 height; +}TS_RECORD_WIN_SIZE; + +#pragma pack(pop) + +class TppSshRec : public TppRecBase +{ +public: + TppSshRec(); + virtual ~TppSshRec(); + + void record(ex_u8 type, const ex_u8* data, size_t size); + void record_win_size_startup(int width, int height); + void record_win_size_change(int width, int height); + void record_command(const ex_astr cmd); + +protected: + void _on_begin(const TPP_CONNECT_INFO* info); + void _on_end(void); + + bool _save_to_data_file(void); + bool _save_to_cmd_file(void); + +protected: + TS_RECORD_HEADER m_head; + + MemBuffer m_cmd_cache; +}; + +#endif // __TPP_SSH_RECORDER_H__ diff --git a/server/tp_core/protocol/ssh/ssh_session.cpp b/server/tp_core/protocol/ssh/ssh_session.cpp index 28dfc04..1a438f8 100644 --- a/server/tp_core/protocol/ssh/ssh_session.cpp +++ b/server/tp_core/protocol/ssh/ssh_session.cpp @@ -3,6 +3,7 @@ #include "tpp_env.h" #include +#include SshSession::SshSession(SshProxy *proxy, ssh_session sess_client) : ExThreadBase("ssh-session-thread"), @@ -10,10 +11,10 @@ SshSession::SshSession(SshProxy *proxy, ssh_session sess_client) : m_cli_session(sess_client), m_srv_session(NULL) { - m_retcode = SESS_STAT_RUNNING; + m_retcode = TP_SESS_STAT_RUNNING; m_db_id = 0; - m_auth_mode = TS_AUTH_MODE_PASSWORD; + m_auth_type = TP_AUTH_TYPE_PASSWORD; m_is_first_server_data = true; m_is_sftp = false; @@ -71,7 +72,7 @@ void SshSession::_set_stop_flag(void) { } } -bool SshSession::_on_session_begin(const TPP_SESSION_INFO* info) +bool SshSession::_on_session_begin(const TPP_CONNECT_INFO* info) { if (!g_ssh_env.session_begin(info, &m_db_id)) { @@ -91,10 +92,10 @@ bool SshSession::_on_session_end(void) EXLOGD("[ssh] session ret-code: %d\n", m_retcode); // 如果会话过程中没有发生错误,则将其状态改为结束,否则记录下错误值 - if (m_retcode == SESS_STAT_RUNNING) - m_retcode = SESS_STAT_END; + if (m_retcode == TP_SESS_STAT_RUNNING) + m_retcode = TP_SESS_STAT_END; - g_ssh_env.session_end(m_db_id, m_retcode); + g_ssh_env.session_end(m_sid.c_str(), m_db_id, m_retcode); } return true; @@ -227,43 +228,43 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, EXLOGV("[ssh] authenticating, session-id: %s\n", _this->m_sid.c_str()); int protocol = 0; - TPP_SESSION_INFO* sess_info = g_ssh_env.take_session(_this->m_sid.c_str()); + TPP_CONNECT_INFO* sess_info = g_ssh_env.get_session(_this->m_sid.c_str()); if (NULL == sess_info) { - EXLOGW("[ssh] try to get login-info from ssh-sftp-session.\n"); +// EXLOGW("[ssh] try to get login-info from ssh-sftp-session.\n"); // 尝试从sftp连接记录中获取连接信息(一个ssh会话如果成为sftp会话,内部会将连接信息记录下来备用) - TS_SFTP_SESSION_INFO sftp_info; - if (!_this->m_proxy->get_sftp_session_info(_this->m_sid, sftp_info)) { +// TS_SFTP_SESSION_INFO sftp_info; +// if (!_this->m_proxy->get_sftp_session_info(_this->m_sid, sftp_info)) { EXLOGE("[ssh] no such session: %s\n", _this->m_sid.c_str()); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_DENIED; - } - - _this->m_server_ip = sftp_info.host_ip; - _this->m_server_port = sftp_info.host_port; - _this->m_auth_mode = sftp_info.auth_mode; - _this->m_user_name = sftp_info.user_name; - _this->m_user_auth = sftp_info.user_auth; - protocol = TS_PROXY_PROTOCOL_SSH; - - // 因为是从sftp会话得来的登录数据,因此限制本会话只能用于sftp,不允许再使用shell了。 - _this->_enter_sftp_mode(); +// } +// +// _this->m_remote_host_ip = sftp_info.host_ip; +// _this->m_remote_host_port = sftp_info.host_port; +// _this->m_auth_type = sftp_info.auth_mode; +// _this->m_account_name = sftp_info.user_name; +// _this->m_account_secret = sftp_info.user_auth; +// protocol = TP_PROTOCOL_TYPE_SSH; +// +// // 因为是从sftp会话得来的登录数据,因此限制本会话只能用于sftp,不允许再使用shell了。 +// _this->_enter_sftp_mode(); } else { - _this->m_server_ip = sess_info->host_ip; - _this->m_server_port = sess_info->host_port; - _this->m_auth_mode = sess_info->auth_mode; - _this->m_user_name = sess_info->user_name; - _this->m_user_auth = sess_info->user_auth; - protocol = sess_info->protocol; + _this->m_remote_host_ip = sess_info->remote_host_ip; + _this->m_remote_host_port = sess_info->remote_host_port; + _this->m_auth_type = sess_info->auth_type; + _this->m_account_name = sess_info->account_name; + _this->m_account_secret = sess_info->account_secret; + protocol = sess_info->protocol_type; } - if (protocol != TS_PROXY_PROTOCOL_SSH) { + if (protocol != TP_PROTOCOL_TYPE_SSH) { g_ssh_env.free_session(sess_info); EXLOGE("[ssh] session '%s' is not for SSH.\n", _this->m_sid.c_str()); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_DENIED; } @@ -271,7 +272,7 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, { g_ssh_env.free_session(sess_info); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_DENIED; } @@ -279,18 +280,18 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, sess_info = NULL; // 现在尝试根据session-id获取得到的信息,连接并登录真正的SSH服务器 - EXLOGV("[ssh] try to connect to real SSH server %s:%d\n", _this->m_server_ip.c_str(), _this->m_server_port); + EXLOGV("[ssh] try to connect to real SSH server %s:%d\n", _this->m_remote_host_ip.c_str(), _this->m_remote_host_port); _this->m_srv_session = ssh_new(); - ssh_options_set(_this->m_srv_session, SSH_OPTIONS_HOST, _this->m_server_ip.c_str()); - int port = (int)_this->m_server_port; + ssh_options_set(_this->m_srv_session, SSH_OPTIONS_HOST, _this->m_remote_host_ip.c_str()); + int port = (int)_this->m_remote_host_port; ssh_options_set(_this->m_srv_session, SSH_OPTIONS_PORT, &port); #ifdef EX_DEBUG // int flag = SSH_LOG_FUNCTIONS; // ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &flag); #endif - if (_this->m_auth_mode != TS_AUTH_MODE_NONE) - ssh_options_set(_this->m_srv_session, SSH_OPTIONS_USER, _this->m_user_name.c_str()); + if (_this->m_auth_type != TP_AUTH_TYPE_NONE) + ssh_options_set(_this->m_srv_session, SSH_OPTIONS_USER, _this->m_account_name.c_str()); //#ifdef EX_DEBUG // // int _timeout_us = 500000000; // 5 sec. @@ -303,9 +304,9 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, int rc = 0; rc = ssh_connect(_this->m_srv_session); if (rc != SSH_OK) { - EXLOGE("[ssh] can not connect to real SSH server %s:%d. [%d]%s\n", _this->m_server_ip.c_str(), _this->m_server_port, rc, ssh_get_error(_this->m_srv_session)); + EXLOGE("[ssh] can not connect to real SSH server %s:%d. [%d]%s\n", _this->m_remote_host_ip.c_str(), _this->m_remote_host_port, rc, ssh_get_error(_this->m_srv_session)); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_CONNECT; + _this->m_retcode = TP_SESS_STAT_ERR_CONNECT; return SSH_AUTH_ERROR; } @@ -324,7 +325,7 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, // } - if (_this->m_auth_mode == TS_AUTH_MODE_PASSWORD) { + if (_this->m_auth_type == TP_AUTH_TYPE_PASSWORD) { // 优先尝试交互式登录(SSHv2推荐) int retry_count = 0; rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL); @@ -351,11 +352,11 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, const char* prompt = ssh_userauth_kbdint_getprompt(_this->m_srv_session, iprompt, &echo); EXLOGV("[ssh] interactive login prompt: %s\n", prompt); - rc = ssh_userauth_kbdint_setanswer(_this->m_srv_session, iprompt, _this->m_user_auth.c_str()); + rc = ssh_userauth_kbdint_setanswer(_this->m_srv_session, iprompt, _this->m_account_secret.c_str()); if (rc < 0) { - EXLOGE("[ssh] invalid password for interactive mode to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port); + EXLOGE("[ssh] invalid password for interactive mode to login to real SSH server %s:%d.\n", _this->m_remote_host_ip.c_str(), _this->m_remote_host_port); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_ERROR; } } @@ -373,7 +374,7 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, } // 不支持交互式登录,则尝试密码方式 - rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_user_auth.c_str()); + rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_account_secret.c_str()); if (rc == SSH_AUTH_SUCCESS) { EXLOGW("[ssh] logon with password mode.\n"); _this->m_is_logon = true; @@ -383,17 +384,17 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, EXLOGD("[ssh] failed to login with password mode, got %d.\n", rc); } - EXLOGE("[ssh] can not use password mode or interactive mode ot login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port); + EXLOGE("[ssh] can not use password mode or interactive mode ot login to real SSH server %s:%d.\n", _this->m_remote_host_ip.c_str(), _this->m_remote_host_port); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_ERROR; } - else if (_this->m_auth_mode == TS_AUTH_MODE_PRIVATE_KEY) { + else if (_this->m_auth_type == TP_AUTH_TYPE_PRIVATE_KEY) { ssh_key key = NULL; - if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_user_auth.c_str(), NULL, NULL, NULL, &key)) { + if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_account_secret.c_str(), NULL, NULL, NULL, &key)) { EXLOGE("[ssh] can not import private-key for auth.\n"); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_BAD_SSH_KEY; + _this->m_retcode = TP_SESS_STAT_ERR_BAD_SSH_KEY; return SSH_AUTH_ERROR; } @@ -406,19 +407,19 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user, return SSH_AUTH_SUCCESS; } else { - EXLOGE("[ssh] failed to use private-key to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port); + EXLOGE("[ssh] failed to use private-key to login to real SSH server %s:%d.\n", _this->m_remote_host_ip.c_str(), _this->m_remote_host_port); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_ERROR; } } - else if (_this->m_auth_mode == TS_AUTH_MODE_NONE) { + else if (_this->m_auth_type == TP_AUTH_TYPE_NONE) { return SSH_AUTH_ERROR; } else { EXLOGE("[ssh] invalid auth mode.\n"); _this->m_have_error = true; - _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED; + _this->m_retcode = TP_SESS_STAT_ERR_AUTH_DENIED; return SSH_AUTH_ERROR; } } @@ -1017,7 +1018,7 @@ int SshSession::_on_client_channel_subsystem_request(ssh_session session, ssh_ch // 目前只支持SFTP子系统 if (strcmp(subsystem, "sftp") != 0) { EXLOGE("[ssh] support `sftp` subsystem only, but got `%s`.\n", subsystem); - _this->m_retcode = SESS_STAT_ERR_UNSUPPORT_PROTOCOL; + _this->m_retcode = TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL; return SSH_ERROR; } @@ -1044,7 +1045,7 @@ int SshSession::_on_client_channel_subsystem_request(ssh_session session, ssh_ch void SshSession::_enter_sftp_mode(void) { if (!m_is_sftp) { m_is_sftp = true; - m_proxy->add_sftp_session_info(m_sid, m_server_ip, m_server_port, m_user_name, m_user_auth, m_auth_mode); + m_proxy->add_sftp_session_info(m_sid, m_remote_host_ip, m_remote_host_port, m_account_name, m_account_secret, m_auth_type); } } @@ -1066,7 +1067,7 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel TS_SSH_CHANNEL_INFO *info = _this->_get_cli_channel(channel); if (NULL == info || NULL == info->channel) { EXLOGE("[ssh] when receive server channel data, not found client channel.\n"); - _this->m_retcode = SESS_STAT_ERR_INTERNAL; + _this->m_retcode = TP_SESS_STAT_ERR_INTERNAL; return SSH_ERROR; } @@ -1110,9 +1111,9 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel char buf[256] = { 0 }; const char *auth_mode = NULL; - if (_this->m_auth_mode == TS_AUTH_MODE_PASSWORD) + if (_this->m_auth_type == TP_AUTH_TYPE_PASSWORD) auth_mode = "password"; - else if (_this->m_auth_mode == TS_AUTH_MODE_PRIVATE_KEY) + else if (_this->m_auth_type == TP_AUTH_TYPE_PRIVATE_KEY) auth_mode = "private-key"; else auth_mode = "unknown"; @@ -1125,8 +1126,8 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel " - authroized by %s\r\n"\ "=============================================\r\n"\ "\r\n", - _this->m_server_ip.c_str(), - _this->m_server_port, auth_mode + _this->m_remote_host_ip.c_str(), + _this->m_remote_host_port, auth_mode ); int buf_len = strlen(buf); diff --git a/server/tp_core/protocol/ssh/ssh_session.h b/server/tp_core/protocol/ssh/ssh_session.h index 3ece32b..f3affe5 100644 --- a/server/tp_core/protocol/ssh/ssh_session.h +++ b/server/tp_core/protocol/ssh/ssh_session.h @@ -55,7 +55,7 @@ public: protected: // 继承自 TppSessionBase - bool _on_session_begin(const TPP_SESSION_INFO* info); + bool _on_session_begin(const TPP_CONNECT_INFO* info); bool _on_session_end(void); @@ -102,11 +102,11 @@ private: ex_u16 m_client_port; ex_astr m_sid; - ex_astr m_server_ip; - ex_u16 m_server_port; - ex_astr m_user_name; - ex_astr m_user_auth; - int m_auth_mode; + ex_astr m_remote_host_ip; + ex_u16 m_remote_host_port; + ex_astr m_account_name; + ex_astr m_account_secret; + int m_auth_type; bool m_is_first_server_data; bool m_is_sftp; diff --git a/server/tp_core/protocol/ssh/tpssh.cpp b/server/tp_core/protocol/ssh/tpssh.cpp index 76d3b2a..4831493 100644 --- a/server/tp_core/protocol/ssh/tpssh.cpp +++ b/server/tp_core/protocol/ssh/tpssh.cpp @@ -1,6 +1,8 @@ #include "ssh_proxy.h" #include "tpp_env.h" +#include + TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args) { #ifdef EX_OS_UNIX @@ -11,7 +13,7 @@ TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args) #endif if (!g_ssh_env.init(init_args)) - return TSR_FAILED; + return TPE_FAILED; return 0; } @@ -19,9 +21,9 @@ TPP_API ex_rv tpp_init(TPP_INIT_ARGS* init_args) TPP_API ex_rv tpp_start(void) { if (!g_ssh_proxy.init()) - return TSR_FAILED; + return TPE_FAILED; if (!g_ssh_proxy.start()) - return TSR_FAILED; + return TPE_FAILED; return 0; } diff --git a/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj b/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj index eac2a2f..213e064 100644 --- a/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj +++ b/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj @@ -68,7 +68,7 @@ Level3 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) - ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) + ..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) MultiThreadedDebug @@ -86,7 +86,7 @@ true true WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) - ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) + ..\..\..\..\common\teleport;..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) MultiThreaded