teleport/client/tp_assist_win/ts_http_rpc.cpp

1186 lines
29 KiB
C++
Raw Normal View History

#include "stdafx.h"
#pragma warning(disable:4091)
#include <commdlg.h>
#include <ShlObj.h>
#include <WinCrypt.h>
#pragma comment(lib, "Crypt32.lib")
#include <teleport_const.h>
#include "ts_http_rpc.h"
#include "dlg_main.h"
#include "ts_ver.h"
/*
1.
SecureCRT֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD>ǩҳ<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD><EFBFBD> /N "tab name"<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD>
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.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SecureCRT<EFBFBD>ŵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵIJ<EFBFBD>ͬ<EFBFBD><EFBFBD>ǩҳ<EFBFBD>У<EFBFBD>ʹ<EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /T
SecureCRT.exe /T /N "TP#ssh://192.168.1.3" /SSH2 /L root /PASSWORD 1234 120.26.109.25
3.
telnet<EFBFBD>ͻ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
putty.exe telnet://administrator@127.0.0.1:52389
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SecureCRT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ
SecureCRT.exe /T /N "TP#telnet://192.168.1.3" /SCRIPT X:\path\to\startup.vbs /TELNET 127.0.0.1 52389
<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>startup.vbs<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
---------<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ʼ---------
#$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
---------<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---------
4. Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>putty<EFBFBD>Ĵ<EFBFBD><EFBFBD>ڱ<EFBFBD>ǩ<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@192.168.1.2: \w\a\]$PS1"
<EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ubuntu<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ܹ<EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Linux<EFBFBD><EFBFBD>SecureCRT<EFBFBD>Դ˱<EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
*/
//#define RDP_CLIENT_SYSTEM_BUILTIN
// #define RDP_CLIENT_SYSTEM_ACTIVE_CONTROL
//#define RDP_CLIENT_FREERDP
//#ifdef RDP_CLIENT_SYSTEM_BUILTIN
//connect to console:i:%d
//compression:i:1
//bitmapcachepersistenable:i:1
std::string rdp_content = "\
administrative session:i:%d\n\
screen mode id:i:%d\n\
use multimon:i:0\n\
desktopwidth:i:%d\n\
desktopheight:i:%d\n\
session bpp:i:16\n\
winposstr:s:0,1,%d,%d,%d,%d\n\
compression:i:1\n\
bitmapcachepersistenable:i:1\n\
keyboardhook:i:2\n\
audiocapturemode:i:0\n\
videoplaybackmode:i:1\n\
connection type:i:7\n\
networkautodetect:i:1\n\
bandwidthautodetect:i:1\n\
displayconnectionbar:i:1\n\
enableworkspacereconnect:i:0\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:1\n\
full address:s:%s:%d\n\
audiomode:i:0\n\
redirectprinters:i:0\n\
redirectcomports:i:0\n\
redirectsmartcards:i:0\n\
redirectclipboard:i:%d\n\
redirectposdevices:i:0\n\
autoreconnection enabled:i:0\n\
authentication level:i:2\n\
prompt for credentials:i:0\n\
negotiate security layer:i:1\n\
remoteapplicationmode:i:0\n\
alternate shell:s:\n\
shell working directory:s:\n\
gatewayhostname:s:\n\
gatewayusagemethod:i:4\n\
gatewaycredentialssource:i:4\n\
gatewayprofileusagemethod:i:0\n\
promptcredentialonce:i:0\n\
gatewaybrokeringtype:i:0\n\
use redirection server name:i:0\n\
rdgiskdcproxy:i:0\n\
kdcproxyname:s:\n\
drivestoredirect:s:%s\n\
username:s:%s\n\
password 51:b:%s\n\
";
//redirectdirectx:i:0\n\
//prompt for credentials on client:i:0\n\
//#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;
}
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;
}
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"))
ex_strformat(addr, 128, "tcp://127.0.0.1:%d", port);
else
ex_strformat(addr, 128, "tcp://%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"<html lang=\"zh_CN\"><head><meta charset=\"utf-8\"/><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>Teleport<72><74><EFBFBD><EFBFBD></title>\n<style type=\"text/css\">\n.box{padding:20px;margin:40px;border:1px solid #78b17c;background-color:#e4ffe5;}\n</style>\n</head><body><div class=\"box\">Teleport<72><74><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></div></body></html>";
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;
}
if (uri == "/config")
{
uri = "/index.html";
b_is_index = true;
}
ex_astr temp;
int offset = uri.find("/", 1);
if (offset > 0)
{
temp = uri.substr(1, offset-1);
if(temp == "api") {
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: %ld\r\nContent-Type: application/json\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]);
nc->flags |= MG_F_SEND_AND_CLOSE;
return;
}
}
ex_astr file_suffix;
offset = uri.rfind(".");
if (offset > 0)
{
file_suffix = uri.substr(offset, uri.length());
}
ex_wstr2astr(g_env.m_site_path, temp);
ex_astr index_path = temp + uri;
FILE* file = ex_fopen(index_path.c_str(), "rb");
if (file)
{
unsigned long file_size = 0;
char* buf = 0;
size_t ret = 0;
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: %ld\r\nContent-Type: %s\r\n\r\n", file_size, content_type.c_str());
mg_send(nc, buf, (int)file_size);
delete []buf;
nc->flags |= MG_F_SEND_AND_CLOSE;
return;
}
else if (b_is_index)
{
ex_wstr page = L"<html lang=\"zh_CN\"><html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr><center><p>Teleport Assistor configuration page not found.</p></center></body></html>";
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: %ld\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;
}
}
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڣ<D6BD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD> '/'
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ҵ<EFBFBD><D2B5>ķָ<C4B7><D6B8><EFBFBD>
}
}
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() || strs[0] != "api")
return TPE_PARAM;
if (is_get)
{
if (2 == strs.size())
{
func_cmd = strs[1];
}
else if (3 == strs.size())
{
func_cmd = strs[1];
func_args = strs[2];
}
else
{
return TPE_PARAM;
}
}
else
{
if (2 == strs.size())
{
func_cmd = strs[1];
}
else
{
return TPE_PARAM;
}
if (req->body.len > 0)
{
func_args.assign(req->body.p, req->body.len);
}
}
if (func_args.length() > 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> url-decode <20><><EFBFBD><EFBFBD>
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 == "get_version")
{
_rpc_func_get_version(func_args, buf);
}
else if (func_cmd == "run")
{
_rpc_func_run_client(func_args, buf);
}
else if (func_cmd == "rdp_play")
{
_rpc_func_rdp_play(func_args, buf);
}
else if (func_cmd == "get_config")
{
_rpc_func_get_config(func_args, buf);
}
else if (func_cmd == "set_config")
{
_rpc_func_set_config(func_args, buf);
}
else if (func_cmd == "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)
{
// <20><><EFBFBD>أ<EFBFBD> {"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_run_client(const ex_astr& func_args, ex_astr& buf)
{
// <20><><EFBFBD>Σ<EFBFBD>{"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<53><48><EFBFBD>أ<EFBFBD> {"code":0, "data":{"sid":"0123abcde"}}
// RDP<44><50><EFBFBD>أ<EFBFBD> {"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.isObject())
{
_create_json_ret(buf, TPE_PARAM);
return;
}
// <20>жϲ<D0B6><CFB2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ȷ
if (!jsRoot["teleport_ip"].isString()
|| !jsRoot["teleport_port"].isNumeric() || !jsRoot["remote_host_ip"].isString()
|| !jsRoot["session_id"].isString() || !jsRoot["protocol_type"].isNumeric() || !jsRoot["protocol_sub_type"].isNumeric()
|| !jsRoot["protocol_flag"].isNumeric()
)
{
_create_json_ret(buf, TPE_PARAM);
return;
}
int pro_type = jsRoot["protocol_type"].asUInt();
int pro_sub = jsRoot["protocol_sub_type"].asInt();
ex_u32 protocol_flag = jsRoot["protocol_flag"].asUInt();
ex_astr teleport_ip = jsRoot["teleport_ip"].asCString();
int teleport_port = jsRoot["teleport_port"].asUInt();
ex_astr real_host_ip = jsRoot["remote_host_ip"].asCString();
ex_astr sid = jsRoot["session_id"].asCString();
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);
ex_wstr tmp_rdp_file; // for .rdp file
if (pro_type == TP_PROTOCOL_TYPE_RDP)
{
//==============================================
// RDP
//==============================================
bool flag_clipboard = (protocol_flag & TP_FLAG_RDP_CLIPBOARD);
bool flag_disk = (protocol_flag & TP_FLAG_RDP_DISK);
bool flag_console = (protocol_flag & TP_FLAG_RDP_CONSOLE);
int rdp_w = 800;
int rdp_h = 640;
bool rdp_console = false;
if (!jsRoot["rdp_width"].isNull()) {
if (jsRoot["rdp_width"].isNumeric()) {
rdp_w = jsRoot["rdp_width"].asUInt();
}
else {
_create_json_ret(buf, TPE_PARAM);
return;
}
}
if (!jsRoot["rdp_height"].isNull()) {
if (jsRoot["rdp_height"].isNumeric()) {
rdp_h = jsRoot["rdp_height"].asUInt();
}
else {
_create_json_ret(buf, TPE_PARAM);
return;
}
}
if (!jsRoot["rdp_console"].isNull()) {
if (jsRoot["rdp_console"].isBool()) {
rdp_console = jsRoot["rdp_console"].asBool();
}
else {
_create_json_ret(buf, TPE_PARAM);
return;
}
}
if (!flag_console)
rdp_console = false;
int split_pos = sid.length() - 2;
ex_astr real_sid = sid.substr(0, split_pos);
ex_astr 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();
n_pwd_len -= 2;
char szPwd[256] = { 0 };
for (int i = 0; i < n_pwd_len; i++)
{
szPwd[i] = '*';
}
ex_astr2wstr(real_sid, w_sid);
w_exe_path = _T("\"");
w_exe_path += g_cfg.rdp_app + _T("\" ");
ex_wstr rdp_name = g_cfg.rdp_name;
if (rdp_name == L"mstsc") {
w_exe_path += g_cfg.rdp_cmdline;
int width = 0;
int higth = 0;
int cx = 0;
int cy = 0;
int display = 1;
int iWidth = GetSystemMetrics(SM_CXSCREEN);
int iHeight = GetSystemMetrics(SM_CYSCREEN);
if (rdp_w == 0 || rdp_h == 0) {
//ȫ<><C8AB>
width = iWidth;
higth = iHeight;
display = 2;
}
else {
width = rdp_w;
higth = rdp_h;
display = 1;
}
cx = (iWidth - width) / 2;
cy = (iHeight - higth) / 2;
if (cx < 0)
{
cx = 0;
}
if (cy < 0)
{
cy = 0;
}
// int console_mode = 0;
// if (rdp_console)
// console_mode = 1;
std::string psw51b;
if (!calc_psw51b(szPwd, psw51b))
{
EXLOGE("calc password failed.\n");
_create_json_ret(buf, TPE_FAILED);
return;
}
real_sid = "01" + real_sid;
char sz_rdp_file_content[4096] = { 0 };
sprintf_s(sz_rdp_file_content, rdp_content.c_str()
, (flag_console && rdp_console) ? 1 : 0
, display, width, higth
, cx, cy, cx + width + 100, cy + higth + 100
, flag_clipboard ? 1 : 0
, teleport_ip.c_str(), teleport_port
, flag_disk ? "*" : ""
, 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)
{
EXLOGE("fopen failed (%d).\n", GetLastError());
_create_json_ret(buf, TPE_FAILED);
return;
}
ex_astr temp_host_ip = 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 = NULL;
if (fopen_s(&f, sz_file_name, "wt") != 0)
{
EXLOGE("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_astr2wstr(sz_file_name, tmp_rdp_file);
// <20><><EFBFBD><EFBFBD><EFBFBD>
ex_replace_all(w_exe_path, _T("{tmp_rdp_file}"), tmp_rdp_file);
}
else if (g_cfg.rdp_name == L"freerdp") {
w_exe_path += L"{size} {console} {clipboard} {drives} ";
w_exe_path += g_cfg.rdp_cmdline;
ex_wstr w_screen;
if (rdp_w == 0 || rdp_h == 0) {
//ȫ<><C8AB>
w_screen = _T("/f");
}
else {
char sz_size[64] = {0};
ex_strformat(sz_size, 63, "/size:%dx%d", rdp_w, rdp_h);
ex_astr2wstr(sz_size, w_screen);
}
// wchar_t* w_console = NULL;
//
// if (flag_console && rdp_console)
// {
// w_console = L"/admin";
// }
// else
// {
// w_console = L"";
// }
ex_wstr w_password;
ex_astr2wstr(szPwd, w_password);
w_exe_path += L" /p:";
w_exe_path += w_password;
w_sid = L"02" + w_sid;
w_exe_path += L" /gdi:sw"; // ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE>gdi:hwʹ<77><CAB9>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD>ֺܶ<D6BA><DCB6>ڿ飨¼<E9A3A8><C2BC><EFBFBD>ط<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>
w_exe_path += L" -grab-keyboard"; // [new style] <20><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>FreeRDP<44><50><EFBFBD><EFBFBD>ʧȥ<CAA7><C8A5><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>һ<EFBFBD><D2BB>FreeRDP<44><50><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>Ʋ<EFBFBD><C6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>
ex_replace_all(w_exe_path, _T("{size}"), w_screen);
if (flag_console && rdp_console)
ex_replace_all(w_exe_path, _T("{console}"), L"/admin");
else
ex_replace_all(w_exe_path, _T("{console}"), L"");
//ex_replace_all(w_exe_path, _T("{clipboard}"), L"+clipboard");
if(flag_clipboard)
ex_replace_all(w_exe_path, _T("{clipboard}"), L"/clipboard");
else
ex_replace_all(w_exe_path, _T("{clipboard}"), L"-clipboard");
if(flag_disk)
ex_replace_all(w_exe_path, _T("{drives}"), L"/drives");
else
ex_replace_all(w_exe_path, _T("{drives}"), L"-drives");
}
else {
_create_json_ret(buf, TPE_FAILED);
return;
}
}
else if (pro_type == TP_PROTOCOL_TYPE_SSH)
{
//==============================================
// SSH
//==============================================
if (pro_sub == TP_PROTOCOL_TYPE_SSH_SHELL)
{
w_exe_path = _T("\"");
w_exe_path += g_cfg.ssh_app + _T("\" ");
w_exe_path += g_cfg.ssh_cmdline;
}
else
{
w_exe_path = _T("\"");
w_exe_path += g_cfg.scp_app + _T("\" ");
w_exe_path += g_cfg.scp_cmdline;
}
}
else if (pro_type == TP_PROTOCOL_TYPE_TELNET)
{
//==============================================
// TELNET
//==============================================
w_exe_path = _T("\"");
w_exe_path += g_cfg.telnet_app + _T("\" ");
w_exe_path += g_cfg.telnet_cmdline;
}
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);
}
void TsHttpRpc::_rpc_func_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;
}
// <20>жϲ<D0B6><CFB2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ȷ
if (!jsRoot["rid"].isInt()
|| !jsRoot["web"].isString()
|| !jsRoot["sid"].isString()
|| !jsRoot["user"].isString()
|| !jsRoot["acc"].isString()
|| !jsRoot["host"].isString()
|| !jsRoot["start"].isString()
)
{
_create_json_ret(buf, TPE_PARAM);
return;
}
int rid = jsRoot["rid"].asInt();
ex_astr a_url_base = jsRoot["web"].asCString();
ex_astr a_sid = jsRoot["sid"].asCString();
ex_astr a_user = jsRoot["user"].asCString();
ex_astr a_acc = jsRoot["acc"].asCString();
ex_astr a_host = jsRoot["host"].asCString();
ex_astr a_start = jsRoot["start"].asCString();
char cmd_args[1024] = { 0 };
ex_strformat(cmd_args, 1023, "%d \"%s\" \"%09d-%s-%s-%s-%s\"", rid, a_sid.c_str(), rid, a_user.c_str(), a_acc.c_str(), a_host.c_str(), a_start.c_str());
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>תΪIP<49><50><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><C9B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD>FreeRDP<44><50><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ϊ<EFBFBD>˴ӷ<CBB4><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Mongoose<73><EFBFBD><E2A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣨ò<E2A3A8><C3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><ECB2BD>ѯDNS<4E><53><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IPת<50><D7AA><EFBFBD><EFBFBD>
{
unsigned int port_i = 0;
struct mg_str scheme, query, fragment, user_info, host, path;
if (mg_parse_uri(mg_mk_str(a_url_base.c_str()), &scheme, &user_info, &host, &port_i, &path, &query, &fragment) != 0) {
EXLOGE(_T("parse url failed.\n"));
Json::Value root_ret;
root_ret["code"] = TPE_PARAM;
_create_json_ret(buf, root_ret);
return;
}
ex_astr _scheme;
_scheme.assign(scheme.p, scheme.len);
// <20><>host<73><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ΪIP
ex_astr str_tp_host;
str_tp_host.assign(host.p, host.len);
struct hostent *tp_host = gethostbyname(str_tp_host.c_str());
if (NULL == tp_host) {
EXLOGE(_T("resolve host name failed.\n"));
Json::Value root_ret;
root_ret["code"] = TPE_PARAM;
_create_json_ret(buf, root_ret);
return;
}
int i = 0;
char* _ip = NULL;
if (tp_host->h_addrtype == AF_INET)
{
struct in_addr addr;
while (tp_host->h_addr_list[i] != 0) {
addr.s_addr = *(u_long *)tp_host->h_addr_list[i++];
_ip = inet_ntoa(addr);
break;
}
}
if (NULL == _ip) {
EXLOGE(_T("resolve host name failed.\n"));
Json::Value root_ret;
root_ret["code"] = TPE_PARAM;
_create_json_ret(buf, root_ret);
return;
}
char _url_base[256];
ex_strformat(_url_base, 255, "%s://%s:%d", _scheme.c_str(), _ip, port_i);
a_url_base = _url_base;
}
ex_wstr w_url_base;
ex_astr2wstr(a_url_base, w_url_base);
ex_wstr w_cmd_args;
ex_astr2wstr(cmd_args, w_cmd_args);
ex_wstr w_exe_path;
w_exe_path = _T("\"");
w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\"");
w_exe_path += _T(" \"");
w_exe_path += w_url_base;
w_exe_path += _T("\" ");
w_exe_path += w_cmd_args;
Json::Value root_ret;
ex_astr utf8_path;
ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8);
root_ret["cmdline"] = utf8_path;
EXLOGD(w_exe_path.c_str());
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::Value jr_root;
jr_root["code"] = 0;
jr_root["data"] = g_cfg.get_root();
_create_json_ret(buf, jr_root);
}
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(!g_cfg.save(func_args))
_create_json_ret(buf, TPE_FAILED);
else
_create_json_ret(buf, TPE_OK);
}
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;
}
// <20>жϲ<D0B6><CFB2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ȷ
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("ѡ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>");
ofn.hwndOwner = hParent;
ofn.lpstrFilter = _T("<EFBFBD><EFBFBD>ִ<EFBFBD>г<EFBFBD><EFBFBD><EFBFBD> (*.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; //<2F>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD>ΪNULL<4C><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ի<EFBFBD><D4BB><EFBFBD>
bi.lpszTitle = _T("ѡ<EFBFBD><EFBFBD>Ŀ¼");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.iImage = 0; //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>bi<62><69><EFBFBD><EFBFBD>
LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾѡ<CABE><D1A1><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD>
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["code"] = TPE_OK;
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;
}