From dcc207c3e02a08aee2e5f895d2240b2d1109c5f4 Mon Sep 17 00:00:00 2001 From: c64cosmin Date: Fri, 15 May 2015 13:42:40 +0300 Subject: [PATCH 001/130] ignored wsgate/build for ubuntu builds --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9dada0bb..5f97b6b9 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ wsgate/setup/.dlldeps wsgate/setup/.setupdir wsgate/setup/.stripsetup wsgate/setup/setupdir +wsgate/build/ # Windows *.vcxproj From 354ffa948207f5700e4835fe8b4ef9166d190c9c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 4 Jun 2015 19:03:08 +0300 Subject: [PATCH 002/130] Added compiling support for Ubuntu 14.04 LTS --- install_prereqs.sh | 27 +++++++++++++++++++++++++++ setup-all.sh | 37 ++++++++++++++++++++++++++----------- wsgate/CMakeLists.txt | 4 +++- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/install_prereqs.sh b/install_prereqs.sh index 018e0a6f..56a97ce6 100755 --- a/install_prereqs.sh +++ b/install_prereqs.sh @@ -20,6 +20,33 @@ fi #Get distro (snipper take from alsa-info.sh) DISTRO=`grep -ihs "buntu\|SUSE\|Fedora\|Debian\|CentOS\|Red Hat Enterprise Linux Server" /etc/{issue,*release,*version}` case $DISTRO in + *buntu*14*) + echo 'Ubuntu 14.04 detected. Installing required packages...' + apt-get update + apt-get install -y python-software-properties + echo | add-apt-repository ppa:ubuntu-toolchain-r/test + apt-get update + apt-get install -y build-essential g++-4.8 libxml++2.6-dev libssl-dev \ + libboost-all-dev libpng-dev libdwarf-dev subversion subversion-tools \ + autotools-dev autoconf libtool cmake + # replace old gcc/g++ with new one + rm /usr/bin/g++ + ln -s /usr/bin/g++-4.8 /usr/bin/g++ + rm /usr/bin/gcc + ln -s /usr/bin/gcc-4.8 /usr/bin/gcc + # installing things for FreeRDP + apt-get -y install build-essential git-core cmake libssl-dev libx11-dev libxext-dev libxinerama-dev \ + libxcursor-dev libxdamage-dev libxv-dev libxkbfile-dev libasound2-dev libcups2-dev libxml2 libxml2-dev \ + libxrandr-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libxi-dev libavutil-dev \ + libavcodec-dev libxtst-dev libgtk-3-dev libgcrypt11-dev libssh-dev libpulse-dev \ + libvte-2.90-dev libxkbfile-dev libfreerdp-dev libtelepathy-glib-dev libjpeg-dev \ + libgnutls-dev libgnome-keyring-dev libavahi-ui-gtk3-dev libvncserver-dev \ + libappindicator3-dev intltool + + apt-get -y --purge remove freerdp-x11 \ + remmina remmina-common remmina-plugin-rdp remmina-plugin-vnc remmina-plugin-gnome \ + remmina-plugin-nx remmina-plugin-telepathy remmina-plugin-xdmcp + ;; *buntu*12*) echo 'Ubuntu 12.04 detected. Installing required packages...' apt-get update diff --git a/setup-all.sh b/setup-all.sh index e575e63e..60ce81f9 100755 --- a/setup-all.sh +++ b/setup-all.sh @@ -38,18 +38,31 @@ function cleanup() rm -rf $HOME/local/include/winpr fi } - +function change_branch() +{ + local REPO_PATH=$1 + local BRANCH=$2 + if [ ! -z "$BRANCH" ]; then + local current=`pwd` + cd $REPO_PATH + git checkout $BRANCH + cd $current + fi +} function git_clone_pull() { local REPO_PATH=$1 local REPO_URL=$2 + local BRANCH=$3 if [ -d "$REPO_PATH" ]; then pushd . cd $REPO_PATH git pull + change_branch $REPO_PATH $BRANCH popd else git clone $REPO_URL + change_branch $REPO_PATH $BRANCH fi } @@ -224,7 +237,6 @@ git_clone_pull EHS https://github.com/cloudbase/EHS.git || { echo 'Unable to dow cd EHS || exit 99 echo '---- Starting ehs build ----' mkdir -p build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make || exit 4 -make || exit 4 echo '---- Finished building ehs ----' if [[ $sudo_present -eq 1 ]]; then echo 'sudo available. Please enter your password to install ehs: ' @@ -236,8 +248,9 @@ fi echo '---- Finished installing ehs ----' cd ../.. || exit 99 echo '---- Checking out freerdp master ----' -git_clone_pull FreeRDP https://github.com/FreeRDP/FreeRDP.git || { echo 'Unable to download FreeRDP from github'; exit 99; } +git_clone_pull FreeRDP https://github.com/FreeRDP/FreeRDP.git stable-1.1 || { echo 'Unable to download FreeRDP'; exit 99; } cd FreeRDP || exit 99 +echo '---- Start installing freerdp ----' mkdir -p build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/usr .. || exit 6 echo '---- Building freerdp ----' make || exit 6 @@ -247,7 +260,8 @@ if [[ $sudo_present -eq 1 ]]; then sudo make install || exit 7 if [ -d /etc/ld.so.conf.d ]; then sudo touch /etc/ld.so.conf.d/freerdp.conf - sudo echo '/usr/lib/x86_64-linux-gnu' > /etc/ld.so.conf.d/freerdp.conf + echo '/usr/lib/x86_64-linux-gnu' > ./freerdp.conf + sudo mv ./freerdp.conf /etc/ld.so.conf.d/ sudo ldconfig fi else @@ -255,30 +269,31 @@ else su -c make install || exit 7 if [ -d /etc/ld.so.conf.d ]; then su -c touch /etc/ld.so.conf.d/freerdp.conf - su -c echo '/usr/lib/x86_64-linux-gnu' > /etc/ld.so.conf.d/freerdp.conf + echo '/usr/lib/x86_64-linux-gnu' > ./freerdp.conf + su -c mv ./freerdp.conf /etc/ld.so.conf.d/ su -c ldconfig fi fi echo '---- Finished installing freerdp ----' cd ../.. || exit 99 echo '---- Checking out casablanca master ----' -git_clone_pull casablanca https://git01.codeplex.com/casablanca || { echo 'Unable to download casablanca from codeplex'; exit 99; } -cd casablanca/Binaries/Release$BITNESS/ || exit 99 -cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release ../../Release || exit 8 +git_clone_pull casablanca https://git.codeplex.com/casablanca || { echo 'Unable to download casablanca from codeplex'; exit 99; } +cd casablanca/Release || exit 99 +cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release . || exit 8 make || exit 8 -make test || exit 9 +#make test || exit 9 if [[ $sudo_present -eq 1 ]]; then echo 'sudo available. Please enter your password to install casablanca: ' sudo cp Binaries/libcpprest.so /usr/lib || exit 10 sudo ldconfig || exit 10 sudo mkdir -p /usr/include/casablanca || exit 10 - sudo cp -r ../../Release/include/* /usr/include/casablanca || exit 10 + sudo cp -r ../Release/include/* /usr/include/casablanca || exit 10 else echo 'sudo command unavailable. Please enter root password to install casablanca' su -c cp Binaries/libcpprest.so /usr/lib$BITNESS || exit 10 su -c ldconfig || exit 10 su -c mkdir -p /usr/include/casablanca || exit 10 - su -c cp -r ../../Release/include/* /usr/include/casablanca || exit 10 + su -c cp -r ../Release/include/* /usr/include/casablanca || exit 10 fi echo '---- Going back to webconnect ----' popd diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 8e88009a..ff645073 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -186,6 +186,8 @@ if(CMAKE_COMPILER_IS_GNUCC) # option to enable compiler warnings option(GCC_ENABLE_WARNINGS "Enable gcc/g++ compiler warnings" OFF) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + if(GCC_ENABLE_WARNINGS) # set compiler warnings set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") @@ -601,4 +603,4 @@ endif() add_executable(wsgate ${WSGATE_SOURCES}) -target_link_libraries(wsgate ${LIBS}) \ No newline at end of file +target_link_libraries(wsgate ${LIBS}) From 9e9bf945d90d58980b0e5857e334dcf5f3541dfe Mon Sep 17 00:00:00 2001 From: c64cosmin Date: Wed, 3 Jun 2015 10:41:11 -0400 Subject: [PATCH 003/130] Added CentOS 7 to install script --- install_prereqs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_prereqs.sh b/install_prereqs.sh index 56a97ce6..24edfd61 100755 --- a/install_prereqs.sh +++ b/install_prereqs.sh @@ -84,7 +84,7 @@ case $DISTRO in echo 'git, svn-devel, autotools, gcc, g++, boost, openssl-devel and libpng-devel. For tracing to work, libdwarf is also required' exit 1 ;; - Red\sHat\sEnterprise\sLinux\sServer*6*|CentOS*6*) + Red\sHat\sEnterprise\sLinux\sServer*6*|CentOS*6*|Red\sHat\sEnterprise\sLinux\sServer*7*|CentOS*7*) echo 'CentOS detected. Installing required packages...' yum install -y gcc-c++ svn subversion-svn2cl openssl-devel \ libpng-devel elfutils-devel glib2-devel From f1a0f1b6cdbf21a07fa46ff2b946664c6704940a Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 5 Jun 2015 22:28:19 +0300 Subject: [PATCH 004/130] Removed Ubuntu 12,13 from install_prereqs.sh - not supported anymore --- install_prereqs.sh | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/install_prereqs.sh b/install_prereqs.sh index 24edfd61..beb8654b 100755 --- a/install_prereqs.sh +++ b/install_prereqs.sh @@ -47,33 +47,6 @@ case $DISTRO in remmina remmina-common remmina-plugin-rdp remmina-plugin-vnc remmina-plugin-gnome \ remmina-plugin-nx remmina-plugin-telepathy remmina-plugin-xdmcp ;; - *buntu*12*) - echo 'Ubuntu 12.04 detected. Installing required packages...' - apt-get update - apt-get install -y python-software-properties - echo | add-apt-repository ppa:ubuntu-toolchain-r/test - apt-get update - apt-get install -y build-essential g++-4.8 libxml++2.6-dev libssl-dev \ - libboost1.48-all-dev libpng-dev libdwarf-dev subversion subversion-tools \ - autotools-dev autoconf libtool cmake - # replace old gcc/g++ with new one - rm /usr/bin/g++ - ln -s /usr/bin/g++-4.8 /usr/bin/g++ - rm /usr/bin/gcc - ln -s /usr/bin/gcc-4.8 /usr/bin/gcc - ;; - *buntu*13*) - echo 'Ubuntu 13.10 detected. Installing required packages...' - apt-get update - apt-get install -y build-essential g++-4.8 libxml++2.6-dev libssl-dev \ - libboost1.49-all-dev libpng-dev libdwarf-dev subversion subversion-tools svn2cl \ - autotools-dev autoconf libtool cmake - # replace old gcc/g++ with new one - rm /usr/bin/g++ - ln -s /usr/bin/g++-4.8 /usr/bin/g++ - rm /usr/bin/gcc - ln -s /usr/bin/gcc-4.8 /usr/bin/gcc - ;; Fedora*) echo 'Fedora detected.Installing required packages...' yum install -y gcc-c++ autoconf automake libtool cmake svn svn2cl \ From c6a3381df62b4c8335f750032f6f49c51631b86d Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Sat, 6 Jun 2015 00:26:55 +0300 Subject: [PATCH 005/130] Removed CentOS 6 --- install_prereqs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_prereqs.sh b/install_prereqs.sh index beb8654b..05fa03a6 100755 --- a/install_prereqs.sh +++ b/install_prereqs.sh @@ -57,7 +57,7 @@ case $DISTRO in echo 'git, svn-devel, autotools, gcc, g++, boost, openssl-devel and libpng-devel. For tracing to work, libdwarf is also required' exit 1 ;; - Red\sHat\sEnterprise\sLinux\sServer*6*|CentOS*6*|Red\sHat\sEnterprise\sLinux\sServer*7*|CentOS*7*) + Red\sHat\sEnterprise\sLinux\sServer*7*|CentOS*7*) echo 'CentOS detected. Installing required packages...' yum install -y gcc-c++ svn subversion-svn2cl openssl-devel \ libpng-devel elfutils-devel glib2-devel From 96afe9f3abdd81a94a00b73d67847b98310a65d8 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 16 Jun 2015 20:53:57 +0300 Subject: [PATCH 006/130] Fixed authentication issue --- wsgate/RDP.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 836a3105..38aa7cc8 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -388,14 +388,18 @@ namespace wsgate { m_rdpSettings->IgnoreCertificate = TRUE; m_rdpSettings->NegotiateSecurityLayer = FALSE; m_rdpSettings->ServerHostname = strdup(host.c_str()); - m_rdpSettings->Username = strdup(user.c_str()); + if (!user.empty()) { + m_rdpSettings->Username = strdup(user.c_str()); + } if (!domain.empty()) { m_rdpSettings->Domain = strdup(domain.c_str()); } if (!pass.empty()) { m_rdpSettings->Password = strdup(pass.c_str()); - } else { - m_rdpSettings->Authentication = 0; + } + //authentication is not needed when username and password is not specified + if (user.empty() && pass.empty()){ + m_freerdp->Authenticate = nullptr; } switch (params.perf) { case 0: From 4eeb3f40262a323bc91d657d9202ed382afd00c4 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 10 Jul 2015 01:23:22 +0300 Subject: [PATCH 007/130] Removed debugging for websocket URL --- wsgate/wsgate_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 5af37d5e..1bcfb0f2 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -320,8 +320,7 @@ namespace wsgate { void LogInfo(std::basic_string remoteAdress, string uri, const char response[]) { - log::info << "Request FROM: " << remoteAdress << endl; - log::info << "To URI: " << uri << " => " << response << endl; + log::info << "Request FROM: " << remoteAdress << " replied with " << response << endl; } ResponseCode HandleRobotsRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) From 708214467c8724fde795919c6fbbd2f24ba5d218 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 15 Jul 2015 02:19:20 +0300 Subject: [PATCH 008/130] Removed GET parameters from link, uses WebSocket instead --- wsgate/RDP.cpp | 63 +++++++++++++++++++++++++++- wsgate/RDP.hpp | 5 ++- wsgate/myrawsocket.hpp | 15 +++++-- wsgate/rdpcommon.hpp | 3 +- wsgate/webroot/index-debug.html | 19 +-------- wsgate/webroot/js/wsgate-debug.js | 27 ++++++++++++ wsgate/wsgate_main.cpp | 68 ++++++++++++++++--------------- 7 files changed, 144 insertions(+), 56 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 38aa7cc8..24a374da 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -30,6 +30,11 @@ #include "Update.hpp" #include "Primary.hpp" #include "Png.hpp" +#include +#include +#include +#include "myrawsocket.hpp" +#include "base64.hpp" #include "btexception.hpp" extern "C" { @@ -313,7 +318,7 @@ namespace wsgate { uint32_t id; } MyPointer; - RDP::RDP(wspp::wshandler *h) + RDP::RDP(wspp::wshandler *h, MyRawSocketHandler *rsh) : m_freerdp(freerdp_new()) , m_rdpContext(0) , m_rdpInput(0) @@ -321,6 +326,7 @@ namespace wsgate { , m_bThreadLoop(false) , m_worker() , m_wshandler(h) + , m_rsh(rsh) , m_errMsg() , m_State(STATE_INITIAL) , m_pUpdate(new Update(h)) @@ -603,6 +609,61 @@ namespace wsgate { break; } } + if ((STATE_INITIAL == m_State) && (data.length() >= 4) && this->m_rsh->isPostponed()) { + const uint32_t *op = reinterpret_cast(data.data()); + switch (*op) { + case WSOP_CS_CREDENTIAL_JSON: + std::wstring infoJSON = L""; + for (int i = 1; i < data.length() / 4; i++){ + infoJSON += (wchar_t)op[i]; + } + try{ + web::json::value jsonValue = web::json::value::parse(infoJSON); + std::wstring w_host = jsonValue[L"host"].as_string(); + std::wstring w_pcb = jsonValue[L"pcb"].as_string(); + std::wstring w_user = jsonValue[L"user"].as_string(); + std::wstring w_pass = jsonValue[L"pass"].as_string(); + std::wstring w_dtsize = jsonValue[L"dtsize"].as_string(); + + std::string size(w_dtsize.begin(), w_dtsize.end()); + + WsRdpParams params; + params.fntlm = jsonValue[L"fntlm"].as_integer(); + params.nomani = jsonValue[L"nomani"].as_integer(); + params.nonla = jsonValue[L"nonla"].as_integer(); + params.notheme = jsonValue[L"notheme"].as_integer(); + params.notls = jsonValue[L"notls"].as_integer(); + params.nowallp = jsonValue[L"nowallp"].as_integer(); + params.nowdrag = jsonValue[L"nowdrag"].as_integer(); + params.perf = jsonValue[L"perf"].as_integer(); + params.port = jsonValue[L"port"].as_integer(); + + if (!size.empty()) { + try { + vector wh; + boost::split(wh, size, boost::algorithm::is_any_of("x")); + if (wh.size() == 2) { + params.width = boost::lexical_cast(wh[0]); + params.height = boost::lexical_cast(wh[1]); + } + } + catch (const exception &e) { + params.width = 1024; + params.height = 768; + } + } + this->m_rsh->PrepareRDP(std::string(w_host.begin(), w_host.end()), + std::string(w_pcb.begin() , w_pcb.end()), + std::string(w_user.begin(), w_user.end()), + std::string(w_pass.begin(), w_pass.end()), + params); + } + catch (exception &e){ + log::err << "Error starting RDP session:" << e.what() << std::endl; + } + break; + } + } } bool RDP::CheckFileDescriptor() diff --git a/wsgate/RDP.hpp b/wsgate/RDP.hpp index 45721198..3cd3d916 100644 --- a/wsgate/RDP.hpp +++ b/wsgate/RDP.hpp @@ -30,6 +30,7 @@ namespace wsgate { + class MyRawSocketHandler; /** * This class serves as a wrapper around the * main FreeRDP API. @@ -54,8 +55,9 @@ namespace wsgate { /** * Constructor * @param h The WebSockets handler to be used for communication with the client. + * @param rsh The Raw Socket handler that is used for starting the RDP session */ - RDP(wspp::wshandler *h); + RDP(wspp::wshandler *h, MyRawSocketHandler *rsh); /// Destructor virtual ~RDP(); @@ -160,6 +162,7 @@ namespace wsgate { bool m_bThreadLoop; pthread_t m_worker; wspp::wshandler *m_wshandler; + MyRawSocketHandler *m_rsh; std::string m_errMsg; State m_State; Update *m_pUpdate; diff --git a/wsgate/myrawsocket.hpp b/wsgate/myrawsocket.hpp index faaca2ba..84ee9dd6 100644 --- a/wsgate/myrawsocket.hpp +++ b/wsgate/myrawsocket.hpp @@ -21,6 +21,8 @@ #define _MYRAWSOCKET_H_ #include "RDP.hpp" +#include +#include namespace wsgate { @@ -78,18 +80,22 @@ namespace wsgate { virtual void OnDisconnect(EHSConnection *conn); /** - * Creates an RDP session and instantiates the relevant - * handler classes. + * Instantiates the relevant handler classes. * @param conn The EHSConnection which triggered thsi action. * @param host The RDP host to connect to * @param user The user name to be used for the RDP session. * @param pass The password to be used for the RDP session. * @param params Additional RDP parameters. + * @param postpone Allows the RDP session to be created later (JSON credential sending through WebSocket) * @return true on success. */ bool Prepare(EHSConnection *conn, const std::string host, const std::string pcb, const std::string user, const std::string pass, - const WsRdpParams ¶ms); + const WsRdpParams ¶ms, bool postpone); + /** + * Creates an RDP session using parameters specified to wsgate::MyRawSocketHandler::Prepare + */ + void PrepareRDP(const std::string host, const std::string pcb, const std::string user, const std::string pass, const WsRdpParams ¶ms); /** * Event handler for WebSocket message events. @@ -100,12 +106,15 @@ namespace wsgate { */ void OnMessage(EHSConnection *conn, const std::string & data); + bool isPostponed(){return this->postponedRDPsession;} private: MyRawSocketHandler(const MyRawSocketHandler&); MyRawSocketHandler& operator=(const MyRawSocketHandler&); WsGate *m_parent; conn_map m_cmap; + bool postponedRDPsession; + EHSConnection *conn; }; } diff --git a/wsgate/rdpcommon.hpp b/wsgate/rdpcommon.hpp index c81fab8e..a7859bde 100644 --- a/wsgate/rdpcommon.hpp +++ b/wsgate/rdpcommon.hpp @@ -74,7 +74,8 @@ namespace wsgate { WSOP_CS_MOUSE, WSOP_CS_KUPDOWN, WSOP_CS_KPRESS, - WSOP_CS_SPECIALCOMB + WSOP_CS_SPECIALCOMB, + WSOP_CS_CREDENTIAL_JSON } WsOPcs; /** diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index 2a75267e..41c89493 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -71,25 +71,9 @@ } function RDPrun() { - var wsUri = wsBase - + '?host=' + encodeURIComponent($('rdphost').value.trim()) - + '&port=' + encodeURIComponent($('rdpport').value.trim()) - + '&pcb=' + encodeURIComponent($('rdppcb').value.trim()) - + '&user=' + encodeURIComponent($('rdpuser').value.trim()) - + '&pass=' + encodeURIComponent($('rdppass').value.toBase64()) - + '&perf=' + $('perf').value.trim() - + '&fntlm=' + $('fntlm').value.trim() - + '&nowallp=' + ($('nowallp').checked ? '1' : '0') - + '&nowdrag=' + ($('nowdrag').checked ? '1' : '0') - + '&nomani=' + ($('nomani').checked ? '1' : '0') - + '¬heme=' + ($('notheme').checked ? '1' : '0') - + '&nonla=' + ($('nonla').checked ? '1' : '0') - + '¬ls=' + ($('notls').checked ? '1' : '0') - + '&dtsize=' + $('screen').width + 'x' + $('screen').height - ; $('dvLoading').setStyles({'visibility':'visible'}); - rdp = new wsgate.RDP(wsUri, $('screen'), !RIMtablet, RIMtablet, vkbd); + rdp = new wsgate.RDP(wsBase, $('screen'), !RIMtablet, RIMtablet, vkbd); rdp.addEvent('alert', function(msg) { alert(msg); @@ -103,7 +87,6 @@ button.value = 'Disconnect'; button.addEvent('click', rdp.Disconnect.bind(rdp)); window.addEvent("beforeunload", rdp.Disconnect.bind(rdp)); - }); rdp.addEvent('disconnected', function() { showDialog(true); diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index e441c8e4..6b6b0de5 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -208,6 +208,32 @@ wsgate.RDP = new Class( { }; }, + SendCredentials: function() { + var infoJSON = {"host" : $('rdphost').value.trim() + ,"port" : parseInt($('rdpport').value.trim()) + ,"pcb" : $('rdppcb').value.trim() + ,"user" : $('rdpuser').value.trim() + ,"pass" : $('rdppass').value + ,"perf" : parseInt($('perf').value.trim()) + ,"fntlm" : parseInt($('fntlm').value.trim()) + ,"nowallp": parseInt($('nowallp').checked ? '1' : '0') + ,"nowdrag": parseInt($('nowdrag').checked ? '1' : '0') + ,"nomani" : parseInt($('nomani').checked ? '1' : '0') + ,"notheme": parseInt($('notheme').checked ? '1' : '0') + ,"nonla" : parseInt($('nonla').checked ? '1' : '0') + ,"notls" : parseInt($('notls').checked ? '1' : '0') + ,"dtsize" : $('screen').width + 'x' + $('screen').height + }; + var infoJSONstring = JSON.stringify(infoJSON); + var len = infoJSONstring.length; + var buf = new ArrayBuffer((len + 1)*4); // 4 bytes for each char + var bufView = new Uint32Array(buf); + bufView[0] = 4; // WSOP_CS_CREDENTIAL_JSON + for(var i = 0; iFormValues("host").m_sBody))); - rdppcb = request->FormValues("pcb").m_sBody; - rdpuser = to_utf8string(web::uri::decode(to_string_t(request->FormValues("user").m_sBody))); - istringstream(request->FormValues("port").m_sBody) >> rdpport; - rdppass = base64_decode(request->FormValues("pass").m_sBody); + postponeRDPsession = true; } params = @@ -620,7 +616,7 @@ namespace wsgate { response->EnableKeepAlive(true); try { - if (!sh->Prepare(request->Connection(), rdphost, rdppcb, rdpuser, rdppass, params)) + if (!sh->Prepare(request->Connection(), rdphost, rdppcb, rdpuser, rdppass, params, postponeRDPsession)) { LogInfo(request->RemoteAddress(), uri, "503 (RDP backend not available)"); response->EnableIdleTimeout(true); @@ -683,7 +679,7 @@ namespace wsgate { return HandleCursorRequest(request, response, uri, thisHost); } - if(boost::starts_with(uri, "/wsgate?")) + if(boost::starts_with(uri, "/wsgate")) { return HandleWsgateRequest(request, response, uri, thisHost); } @@ -1503,36 +1499,20 @@ namespace wsgate { } bool MyRawSocketHandler::Prepare(EHSConnection *conn, const string host, const string pcb, - const string user, const string pass, const WsRdpParams ¶ms) + const string user, const string pass, const WsRdpParams ¶ms, bool postpone) { - log::debug << "RDP Host: '" << host << "'" << endl; - log::debug << "RDP Pcb: '" << pcb << "'" << endl; - log::info << "RDP Port: '" << params.port << "'" << endl; - log::debug << "RDP User: '" << user << "'" << endl; - log::debug << "RDP Desktop size: " << params.width << "x" << params.height << endl; - log::debug << "RDP Performance: " << params.perf << endl; - log::debug << "RDP No wallpaper: " << params.nowallp << endl; - log::debug << "RDP No full windowdrag: " << params.nowdrag << endl; - log::debug << "RDP No menu animation: " << params.nomani << endl; - log::debug << "RDP No theming: " << params.nomani << endl; - log::debug << "RDP Disable TLS: " << params.notls << endl; - log::debug << "RDP Disable NLA: " << params.nonla << endl; - log::debug << "RDP NTLM auth: " << params.fntlm << endl; - - try { + this->postponedRDPsession = postpone; handler_ptr h(new MyWsHandler(conn, m_parent, this)); conn_ptr c(new wspp::wsendpoint(h.get())); - rdp_ptr r(new RDP(h.get())); + rdp_ptr r(new RDP(h.get(), this)); m_cmap[conn] = conn_tuple(c, h, r); - string username; - string domain; - SplitUserDomain(user, username, domain); - - r->Connect(host, pcb, username, domain, pass, params); - m_parent->RegisterRdpSession(r); + this->conn = conn; + if (!postpone){ + PrepareRDP(host, pcb, user, pass, params); + } } catch(...) { @@ -1542,6 +1522,30 @@ namespace wsgate { return true; } + void MyRawSocketHandler::PrepareRDP(const std::string host, const std::string pcb, const std::string user, const std::string pass, const WsRdpParams ¶ms){ + string username; + string domain; + SplitUserDomain(user, username, domain); + + rdp_ptr r = this->m_cmap[this->conn].get<2>(); + r->Connect(host, pcb, username, domain, pass, params); + m_parent->RegisterRdpSession(r); + + log::debug << "RDP Host: '" << host << "'" << endl; + log::debug << "RDP Pcb: '" << pcb << "'" << endl; + log::debug << "RDP User: '" << user << "'" << endl; + log::info << "RDP Port: '" << params.port << "'" << endl; + log::debug << "RDP Desktop size: " << params.width << "x" << params.height << endl; + log::debug << "RDP Performance: " << params.perf << endl; + log::debug << "RDP No wallpaper: " << params.nowallp << endl; + log::debug << "RDP No full windowdrag: " << params.nowdrag << endl; + log::debug << "RDP No menu animation: " << params.nomani << endl; + log::debug << "RDP No theming: " << params.nomani << endl; + log::debug << "RDP Disable TLS: " << params.notls << endl; + log::debug << "RDP Disable NLA: " << params.nonla << endl; + log::debug << "RDP NTLM auth: " << params.fntlm << endl; + } + } static bool g_signaled = false; From 18a29da17b5ae7139ebe9e73756b3b6835846076 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 15 Jul 2015 20:15:14 +0300 Subject: [PATCH 009/130] Removed cookie code on server-side --- wsgate/wsgate_main.cpp | 51 ------------------------------------------ 1 file changed, 51 deletions(-) diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index df2376a9..a07f59c6 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -443,51 +443,6 @@ namespace wsgate { return 0; } - void ManageCookies(HttpRequest *request, HttpResponse *response, string rdphost, string rdppcb, string rdpuser, string thisHost) - { - CookieParameters setcookie; - setcookie["path"] = "/"; - setcookie["host"] = thisHost; - setcookie["max-age"] = "864000"; - if (request->Secure()) { - setcookie["secure"] = ""; - } - CookieParameters delcookie; - delcookie["path"] = "/"; - delcookie["host"] = thisHost; - delcookie["max-age"] = "0"; - if (request->Secure()) { - delcookie["secure"] = ""; - } - if(rdppcb.empty()) { - delcookie["name"] = "lastpcb"; - delcookie["value"] = "%20"; - response->SetCookie(delcookie); - } else { - setcookie["name"] = "lastpcb"; - setcookie["value"] = (rdppcb); - response->SetCookie(setcookie); - } - if (rdphost.empty()) { - delcookie["name"] = "lasthost"; - delcookie["value"] = "%20"; - response->SetCookie(delcookie); - } else { - setcookie["name"] = "lasthost"; - setcookie["value"] = (m_bOverrideRdpHost ? "" : rdphost); - response->SetCookie(setcookie); - } - if (rdpuser.empty()) { - delcookie["name"] = "lastuser"; - delcookie["value"] = "%20"; - response->SetCookie(delcookie); - } else { - setcookie["name"] = "lastuser"; - setcookie["value"] = (m_bOverrideRdpUser ? "" : rdpuser); - response->SetCookie(setcookie); - } - } - ResponseCode HandleWsgateRequest(HttpRequest *request, HttpResponse *response, std::string uri, std::string thisHost) { //FreeRDP Params @@ -628,12 +583,6 @@ namespace wsgate { log::info << "caught exception!" << endl; } - //Use cookies only as standalone app - if (setCookie) - ManageCookies(request, response, rdphost, rdppcb, rdpuser, thisHost); - else - //openstack - wipe out any cookies - ManageCookies(request, response, "", "", "", thisHost); response->RemoveHeader("Content-Type"); response->RemoveHeader("Content-Length"); response->RemoveHeader("Last-Modified"); From 93c4ff0a0dbdf0b75fa8d5fb427a43e0ffd5da60 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 16 Jul 2015 01:01:42 +0300 Subject: [PATCH 010/130] Added cookies to the client-side --- wsgate/webroot/index-debug.html | 66 ++++++++++++++++++++++++++++++- wsgate/webroot/js/wsgate-debug.js | 18 +-------- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index 41c89493..19d300a1 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -32,6 +32,11 @@ var externalConnection = false; + function initBody(){ + //apply old settings + settingsApply(); + } + function RDPGet(uri, title) { var wsUri = wsBase + uri; @@ -266,6 +271,65 @@ } } + var RDPCookieKey = "RDPinfoJSON"; + //sets a cookie with the settings inserted in the form + function settingsSet(){ + var infoJSON = settingsGetJSON(); + //remove password + infoJSON.pass = ""; + document.cookie = RDPCookieKey + "=" + JSON.stringify(infoJSON) + "; expires=Fri, 31 Dec 2030 23:59:59 GMT;"; + } + //change the form fields with respect with the cookie + function settingsApply(){ + var cookie = document.cookie; + if(cookie){ + var cookieValues = cookie.split(';'); + var i = 0; + //get the cookie for infoJSON + while(cookieValues[i].indexOf(RDPCookieKey) == -1){ + i++; + } + //get the value of the cookie then parse it to a JSON + try{ + var infoJSON = JSON.parse(cookieValues[i].split('=')[1]); + //if we found a JSON we apply the values to the form fields + if(infoJSON){ + $('rdphost').set('value',infoJSON.host); + $('rdpport').set('value',infoJSON.port); + $('rdppcb').set('value',infoJSON.pcb); + $('rdpuser').set('value',infoJSON.user); + $('nowallp').set('checked', infoJSON.nowallp != 0); + $('nowdrag').set('checked', infoJSON.nowdrag != 0); + $('nomani').set('checked', infoJSON.nomani != 0); + $('notheme').set('checked', infoJSON.notheme != 0); + $('nonla').set('checked', infoJSON.nonla != 0); + $('notls').set('checked', infoJSON.notls != 0); + } + } catch (e){ + console.log("Bad JSON format"); + console.log(e.message); + } + } + } + //gets a JSON with the settings inserted in the form + function settingsGetJSON(){ + return {"host" : $('rdphost').value.trim() + ,"port" : parseInt($('rdpport').value.trim()) + ,"pcb" : $('rdppcb').value.trim() + ,"user" : $('rdpuser').value.trim() + ,"pass" : $('rdppass').value + ,"perf" : parseInt($('perf').value.trim()) + ,"fntlm" : parseInt($('fntlm').value.trim()) + ,"nowallp": parseInt($('nowallp').checked ? '1' : '0') + ,"nowdrag": parseInt($('nowdrag').checked ? '1' : '0') + ,"nomani" : parseInt($('nomani').checked ? '1' : '0') + ,"notheme": parseInt($('notheme').checked ? '1' : '0') + ,"nonla" : parseInt($('nonla').checked ? '1' : '0') + ,"notls" : parseInt($('notls').checked ? '1' : '0') + ,"dtsize" : $('screen').width + 'x' + $('screen').height + }; + } + window.addEventListener("beforeunload", function() { if ($('maindialog').hasClass('invisible')){ var ans = confirm("Are you sure you want to disconnect?"); @@ -348,7 +412,7 @@ }); - + +

Sorry, It looks as though your browser does not support the canvas tag.

diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 4db0bd71..047f0611 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -918,6 +918,13 @@ wsgate.RDP = new Class( { } } this.DumpTextArea(evt.code); + //IME helper div + if(this.IMEon){ + $('IMEhelper').setStyle('visibility','visible'); + $('IMEhelper').set('html',$('textareainput').get('value')); + }else{ + $('IMEhelper').setStyle('visibility','hidden'); + } }, /** * Sends unicode to the server From 3acfe03b15f7de34efcaea256819e28bdde3ba59 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 31 Jul 2015 04:53:11 +0300 Subject: [PATCH 037/130] Added toggler button for multilanguage input method --- wsgate/webroot/index-debug.html | 1 + wsgate/webroot/js/wsgate-debug.js | 91 +++++++++++++++++++------------ 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index f89c139a..e352faf8 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -520,6 +520,7 @@ + diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 047f0611..21038d75 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -187,6 +187,8 @@ wsgate.RDP = new Class( { this.msie = window.navigator.userAgent.indexOf('MSIE '); this.trident = window.navigator.userAgent.indexOf('Trident/'); this.parent(url); + //add the toggle function to the keyboard language button + $('keyboardlanguage').addEvent('click', this.ToggleLanguageButton.bind(this)); }, Disconnect: function() { this._reset(); @@ -219,6 +221,18 @@ wsgate.RDP = new Class( { } this.sock.send(buf); }, + /** + * Multilanguage mode + */ + useIME: false, + ToggleLanguageButton: function(){ + this.useIME = $('keyboardlanguage').get('text') == "Multilanguage keyboard"; + if(this.useIME){ + $('keyboardlanguage').set('text','Normal keyboard'); + }else{ + $('keyboardlanguage').set('text','Multilanguage keyboard'); + } + }, /** * Used when the special input method is on */ @@ -881,55 +895,64 @@ wsgate.RDP = new Class( { } this.sock.send(buf); }, + /** + * Sends a scancode key event + * down = 1 + * up = 0 + */ + SendKeyUpDown: function(key, upDown){ + if (this.sock.readyState == this.sock.OPEN) { + buf = new ArrayBuffer(12); + a = new Uint32Array(buf); + a[0] = 1; // WSOP_CS_KUPDOWN + a[1] = upDown; + a[2] = key; + this.sock.send(buf); + } + }, KeyDownEvent: function(evt){ - if(evt.code==229||evt.code==0)this.IMEon=true; - //send key presses only when IME is off - if(!this.IMEon){ - if(this.FunctionalKey(evt.code)){ - - if(evt.preventDefault) evt.preventDefault(); - if(evt.stopPropagation) evt.stopPropagation(); + if(!this.useIME){ + this.SendKeyUpDown(evt.code, 1); + }else{ + if(evt.code==229||evt.code==0)this.IMEon=true; + //send key presses only when IME is off + if(!this.IMEon){ + if(this.FunctionalKey(evt.code)){ + if(evt.preventDefault) evt.preventDefault(); + if(evt.stopPropagation) evt.stopPropagation(); - if (this.sock.readyState == this.sock.OPEN) { - buf = new ArrayBuffer(12); - a = new Uint32Array(buf); - a[0] = 1; // WSOP_CS_KUPDOWN - a[1] = 1; // down - a[2] = evt.code; - this.sock.send(buf); + this.SendKeyUpDown(evt.code, 1); } } } }, KeyUpEvent: function(evt){ - if(!this.IMEon) - if(this.FunctionalKey(evt.code)){ - - if(evt.preventDefault) evt.preventDefault(); - if(evt.stopPropagation) evt.stopPropagation(); + if(!this.useIME){ + this.SendKeyUpDown(evt.code, 0); + this.textAreaInput.set("value",""); + }else{ + if(!this.IMEon) + if(this.FunctionalKey(evt.code)){ + if(evt.preventDefault) evt.preventDefault(); + if(evt.stopPropagation) evt.stopPropagation(); - if (this.sock.readyState == this.sock.OPEN) { - var buf = new ArrayBuffer(12); - var a = new Uint32Array(buf); - a[0] = 1; // WSOP_CS_KUPDOWN - a[1] = 0; // up - a[2] = evt.code; - this.sock.send(buf); + this.SendKeyUpDown(evt.code, 0); + } + this.DumpTextArea(evt.code); + //IME helper div + if(this.IMEon){ + $('IMEhelper').setStyle('visibility','visible'); + $('IMEhelper').set('html',$('textareainput').get('value')); + }else{ + $('IMEhelper').setStyle('visibility','hidden'); } - } - this.DumpTextArea(evt.code); - //IME helper div - if(this.IMEon){ - $('IMEhelper').setStyle('visibility','visible'); - $('IMEhelper').set('html',$('textareainput').get('value')); - }else{ - $('IMEhelper').setStyle('visibility','hidden'); } }, /** * Sends unicode to the server */ KeyPressEvent: function(evt){ + if(this.useIME) if(!this.IMEon){ this.SendUnicodeString(String.fromCharCode(evt.code)); $('textareainput').set("value",""); From 5ad26c925324b1c4450dad021e5c4313cd4d0fe2 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 31 Jul 2015 04:58:13 +0300 Subject: [PATCH 038/130] Try catch the out of focus event --- wsgate/webroot/js/wsgate-debug.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 21038d75..f2a53c6a 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -277,7 +277,11 @@ wsgate.RDP = new Class( { //make sure the textarea is always on focus this.textAreaInput.focus(); this.textAreaInput.addEvent('blur', function(){ - setTimeout(function(){$('textareainput').focus();},20); + try{ + setTimeout(function(){$('textareainput').focus();},20); + } + catch(err){ + } }); }, /** From e7fb57feb31a02130d35b95e32304ee3973a8a25 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 10 Aug 2015 15:59:09 +0300 Subject: [PATCH 039/130] Fixed the mouse leave issue --- wsgate/webroot/js/wsgate-debug.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index f2a53c6a..7b17428d 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -825,6 +825,7 @@ wsgate.RDP = new Class( { a[2] = x; a[3] = y; this.sock.send(buf); + this.mouseDownStatus[which] = true; } } }, @@ -850,6 +851,7 @@ wsgate.RDP = new Class( { a[2] = x; a[3] = y; this.sock.send(buf); + this.mouseDownStatus[which] = false; } } }, @@ -872,7 +874,31 @@ wsgate.RDP = new Class( { this.sock.send(buf); } }, - + /** + * Field used to keep the states of the sent mouse events + */ + mouseDownStatus: {}, + /** + * Event handler for mouse leaving the canvas area + * used to send mouse release for any unsent mouse releases + */ + onMouseLeave: function(evt){ + for(var button in this.mouseDownStatus){ + if(this.mouseDownStatus[button]){ + var which = button; + if (this.sock.readyState == this.sock.OPEN) { + buf = new ArrayBuffer(16); + a = new Uint32Array(buf); + a[0] = 0; // WSOP_CS_MOUSE + a[1] = which; + a[2] = 0; + a[3] = 0; + this.sock.send(buf); + this.mouseDownStatus[which] = false; + } + } + } + }, /** * Event handler for sending array of keys to be pressed */ @@ -1111,6 +1137,7 @@ wsgate.RDP = new Class( { this.textAreaInput.addEvent('mousedown', this.onMd.bind(this)); this.textAreaInput.addEvent('mouseup', this.onMu.bind(this)); this.textAreaInput.addEvent('mousewheel', this.onMw.bind(this)); + this.textAreaInput.addEvent('mouseleave', this.onMouseLeave.bind(this)); // Disable the browser's context menu this.textAreaInput.addEvent('contextmenu', function(e) {e.stop();}); // For touch devices From 75239c1c84fd1354e02fbfdd41b9dff974bd1e15 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 10 Aug 2015 17:27:59 +0300 Subject: [PATCH 040/130] Moved postconnect code to proper callback --- wsgate/RDP.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 4bee710e..e07c0c44 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -853,6 +853,14 @@ namespace wsgate { graphics_register_pointer(rdp->context->graphics, &p); pointer_cache_register_callbacks(rdp->update); + //everything went ok, send a event to the client + std::string msg = "C:"; + if(this->m_embeddedContext == CONTEXT_EMBEDDED){ + msg.append("E:"); + } + msg.append("RDP session connection started."); + m_wshandler->send_text(msg); + return true; } @@ -1089,14 +1097,6 @@ namespace wsgate { case STATE_CONNECT: if(freerdp_connect(m_freerdp)) { m_State = STATE_CONNECTED; - //set all flags to off - //everything went ok, send a event to the client - std::string msg = "C:"; - if(this->m_embeddedContext == CONTEXT_EMBEDDED){ - msg.append("E:"); - } - msg.append("RDP session connection started."); - m_wshandler->send_text(msg); continue; } m_State = STATE_INITIAL; From 8ec1b75696a404ab31d53deb8572e51fe173ac87 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 10 Aug 2015 17:30:26 +0300 Subject: [PATCH 041/130] Fixed Horizon resize issue --- wsgate/RDP.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index e07c0c44..3c3ad172 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -860,6 +860,8 @@ namespace wsgate { } msg.append("RDP session connection started."); m_wshandler->send_text(msg); + //make sure that the client gets the resize event + m_freerdp->update->DesktopResize(m_freerdp->context); return true; } From 6db2f463a822cbfbb6a238bd5a9a33a5677f29cd Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 1 Sep 2015 19:39:13 +0300 Subject: [PATCH 042/130] Changed ini config file parsing method --- wsgate/wsgate_main.cpp | 234 +++++++++++++++++++---------------------- 1 file changed, 111 insertions(+), 123 deletions(-) diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 2d631e99..8419b748 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -42,6 +42,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -231,7 +235,7 @@ namespace wsgate { , m_sRdpOverridePass() , m_RdpOverrideParams() , m_sConfigFile() - , m_pVm(NULL) + , m_ptIniConfig() , m_bDaemon(false) , m_bRedirect(false) , m_StaticCache() @@ -243,8 +247,6 @@ namespace wsgate { if (!m_sPidFile.empty()) { unlink(m_sPidFile.c_str()); } - delete m_pVm; - m_pVm = NULL; } HttpResponse *HandleThreadException(ehs_threadid_t, HttpRequest *request, exception &ex) @@ -369,10 +371,10 @@ namespace wsgate { { string dest(boost::starts_with(uri, "/wsgate?") ? "wss" : "https"); //adding the sslPort to the dest Location - if (m_pVm->count("ssl.port")) + if (this->m_ptIniConfig.get_optional("ssl.port")) { stringstream sslPort; - sslPort << (*m_pVm)["ssl.port"].as(); + sslPort << this->m_ptIniConfig.get("ssl.port"); //Replace the http port with the ssl one string thisSslHost = thisHost.substr(0, thisHost.find(":")) + ":" + sslPort.str(); @@ -871,8 +873,8 @@ namespace wsgate { return HTTPRESPONSECODE_200_OK; } - po::variables_map *GetConfig() { - return m_pVm; + boost::property_tree::ptree GetConfig() { + return this->m_ptIniConfig; } const string & GetConfigFile() { @@ -941,90 +943,70 @@ namespace wsgate { ("hyperv.hostpassword", po::value(), "Hyper-V user's password") ; - m_pVm = new po::variables_map(); try { - ifstream f(m_sConfigFile.c_str()); - if (f.fail()) { -#ifdef _WIN32 - wsgate::log::err << "Could not read config file '" << m_sConfigFile << "'." << endl; -#endif - cerr << "Could not read config file '" << m_sConfigFile << "'." << endl; - return false; - } - po::store(po::parse_config_file(f, cfg, true), *m_pVm); - po::notify(*m_pVm); + boost::property_tree::ini_parser::read_ini(m_sConfigFile, this->m_ptIniConfig); + boost::property_tree::ptree pt = this->m_ptIniConfig; try { // Examine values from config file - - if (m_pVm->count("global.daemon")) { - m_bDaemon = str2bool((*m_pVm)["global.daemon"].as()); - } - m_bDebug = false; - if (m_pVm->count("global.debug")) { - m_bDebug = str2bool((*m_pVm)["global.debug"].as()); - } - m_bEnableCore = false; - if (m_pVm->count("global.enablecore")) { - m_bEnableCore = str2bool((*m_pVm)["global.enablecore"].as()); - } - if (m_pVm->count("global.logmask")) { + m_bDaemon = str2bool(pt.get("global.daemon","false")); + m_bDebug = str2bool(pt.get("global.debug","false")); + m_bEnableCore = str2bool(pt.get("global.enablecore","false")); + if (pt.get_optional("global.logmask")) { if (NULL != logger) { - logger->setmaskByName(to_upper_copy((*m_pVm)["global.logmask"].as())); + logger->setmaskByName(to_upper_copy(pt.get("global.logmask"))); } } - if (m_pVm->count("global.logfacility")) { + if (pt.get_optional("global.logfacility")) { if (NULL != logger) { - logger->setfacilityByName(to_upper_copy((*m_pVm)["global.logfacility"].as())); + logger->setfacilityByName(to_upper_copy(pt.get("global.logfacility"))); } } - if (0 == (m_pVm->count("global.port") + m_pVm->count("ssl.port"))) { + if (!pt.get_optional("global.port") && !pt.get_optional("ssl.port")) { throw tracing::invalid_argument("No listening ports defined."); } - if (0 == (m_pVm->count("http.documentroot"))) { + + if (!pt.get_optional("http.documentroot")) { throw tracing::invalid_argument("No documentroot defined."); } - m_sDocumentRoot.assign((*m_pVm)["http.documentroot"].as()); + m_sDocumentRoot.assign(pt.get("http.documentroot")); if (m_sDocumentRoot.empty()) { throw tracing::invalid_argument("documentroot is empty."); } - m_bRedirect = false; - if (m_pVm->count("global.redirect")) { - m_bRedirect = str2bool((*m_pVm)["global.redirect"].as()); - } - - if (m_pVm->count("acl.order")) { - setAclOrder((*m_pVm)["acl.order"].as()); + m_bRedirect = str2bool(pt.get("global.redirect","false")); + + if (pt.get_optional("acl.order")) { + setAclOrder(pt.get("acl.order")); } - if (m_pVm->count("acl.allow")) { - setHostList((*m_pVm)["acl.allow"].as>(), m_allowedHosts); + if (pt.get_child_optional("acl.allow")) { + setHostList(as_vector(pt, "acl.allow"), m_allowedHosts); } - if (m_pVm->count("acl.deny")) { - setHostList((*m_pVm)["acl.deny"].as>(), m_deniedHosts); + if (pt.get_child_optional("acl.deny")) { + setHostList(as_vector(pt, "acl.deny"), m_deniedHosts); } - if (m_pVm->count("rdpoverride.host")) { - m_sRdpOverrideHost.assign((*m_pVm)["rdpoverride.host"].as()); + if (pt.get_optional("rdpoverride.host")) { + m_sRdpOverrideHost.assign(pt.get("rdpoverride.host")); m_bOverrideRdpHost = true; } else { m_bOverrideRdpHost = false; } - if (m_pVm->count("rdpoverride.user")) { - m_sRdpOverrideUser.assign((*m_pVm)["rdpoverride.user"].as()); + if (pt.get_optional("rdpoverride.user")) { + m_sRdpOverrideUser.assign(pt.get("rdpoverride.user")); m_bOverrideRdpUser = true; } else { m_bOverrideRdpUser = false; } - if (m_pVm->count("rdpoverride.pass")) { - m_sRdpOverridePass.assign((*m_pVm)["rdpoverride.pass"].as()); + if (pt.get_optional("rdpoverride.pass")) { + m_sRdpOverridePass.assign(pt.get("rdpoverride.pass")); m_bOverrideRdpPass = true; } else { m_bOverrideRdpPass = false; } - if (m_pVm->count("rdpoverride.port")) { - int n = (*m_pVm)["rdpoverride.port"].as(); + if (pt.get_optional("rdpoverride.port")) { + int n = pt.get("rdpoverride.port"); if ((0 > n) || (2 < n)) { throw tracing::invalid_argument("Invalid port value."); } @@ -1034,8 +1016,8 @@ namespace wsgate { m_bOverrideRdpPort = false; } - if (m_pVm->count("rdpoverride.performance")) { - int n = (*m_pVm)["rdpoverride.performance"].as(); + if (pt.get_optional("rdpoverride.performance")) { + int n = pt.get("rdpoverride.performance"); if ((0 > n) || (2 < n)) { throw tracing::invalid_argument("Invalid performance value."); } @@ -1044,8 +1026,8 @@ namespace wsgate { } else { m_bOverrideRdpPerf = false; } - if (m_pVm->count("rdpoverride.forcentlm")) { - int n = (*m_pVm)["rdpoverride.forcentlm"].as(); + if (pt.get_optional("rdpoverride.forcentlm")) { + int n = pt.get("rdpoverride.forcentlm"); if ((0 > n) || (2 < n)) { throw tracing::invalid_argument("Invalid forcentlm value."); } @@ -1054,74 +1036,74 @@ namespace wsgate { } else { m_bOverrideRdpFntlm = false; } - if (m_pVm->count("rdpoverride.nowallpaper")) { - m_RdpOverrideParams.nowallp = str2bint((*m_pVm)["rdpoverride.nowallpaper"].as()); + if (pt.get_optional("rdpoverride.nowallpaper")) { + m_RdpOverrideParams.nowallp = str2bint(pt.get("rdpoverride.nowallpaper")); m_bOverrideRdpNowallp = true; } else { m_bOverrideRdpNowallp = false; } - if (m_pVm->count("rdpoverride.nofullwindowdrag")) { - m_RdpOverrideParams.nowdrag = str2bint((*m_pVm)["rdpoverride.nofullwindowdrag"].as()); + if (pt.get_optional("rdpoverride.nofullwindowdrag")) { + m_RdpOverrideParams.nowdrag = str2bint(pt.get("rdpoverride.nofullwindowdrag")); m_bOverrideRdpNowdrag = true; } else { m_bOverrideRdpNowdrag = false; } - if (m_pVm->count("rdpoverride.nomenuanimation")) { - m_RdpOverrideParams.nomani = str2bint((*m_pVm)["rdpoverride.nomenuanimation"].as()); + if (pt.get_optional("rdpoverride.nomenuanimation")) { + m_RdpOverrideParams.nomani = str2bint(pt.get("rdpoverride.nomenuanimation")); m_bOverrideRdpNomani = true; } else { m_bOverrideRdpNomani = false; } - if (m_pVm->count("rdpoverride.notheming")) { - m_RdpOverrideParams.notheme = str2bint((*m_pVm)["rdpoverride.notheming"].as()); + if (pt.get_optional("rdpoverride.notheming")) { + m_RdpOverrideParams.notheme = str2bint(pt.get("rdpoverride.notheming")); m_bOverrideRdpNotheme = true; } else { m_bOverrideRdpNotheme = false; } - if (m_pVm->count("rdpoverride.notls")) { - m_RdpOverrideParams.notls = str2bint((*m_pVm)["rdpoverride.notls"].as()); + if (pt.get_optional("rdpoverride.notls")) { + m_RdpOverrideParams.notls = str2bint(pt.get("rdpoverride.notls")); m_bOverrideRdpNotls = true; } else { m_bOverrideRdpNotls = false; } - if (m_pVm->count("rdpoverride.nonla")) { - m_RdpOverrideParams.nonla = str2bint((*m_pVm)["rdpoverride.nonla"].as()); + if (pt.get_optional("rdpoverride.nonla")) { + m_RdpOverrideParams.nonla = str2bint(pt.get("rdpoverride.nonla")); m_bOverrideRdpNonla = true; } else { m_bOverrideRdpNonla = false; } - if (m_pVm->count("global.hostname")) { - m_sHostname.assign((*m_pVm)["global.hostname"].as()); + if (pt.get_optional("global.hostname")) { + m_sHostname.assign(pt.get("global.hostname")); } else { m_sHostname.clear(); } - if (m_pVm->count("openstack.authurl")) { - m_sOpenStackAuthUrl.assign((*m_pVm)["openstack.authurl"].as()); + if (pt.get_optional("openstack.authurl")) { + m_sOpenStackAuthUrl.assign(pt.get("openstack.authurl")); } else { m_sOpenStackAuthUrl.clear(); } - if (m_pVm->count("openstack.username")) { - m_sOpenStackUsername.assign((*m_pVm)["openstack.username"].as()); + if (pt.get_optional("openstack.username")) { + m_sOpenStackUsername.assign(pt.get("openstack.username")); } else { m_sOpenStackUsername.clear(); } - if (m_pVm->count("openstack.password")) { - m_sOpenStackPassword.assign((*m_pVm)["openstack.password"].as()); + if (pt.get_optional("openstack.password")) { + m_sOpenStackPassword.assign(pt.get("openstack.password")); } else { m_sOpenStackPassword.clear(); } - if (m_pVm->count("openstack.tenantname")) { - m_sOpenStackTenantName.assign((*m_pVm)["openstack.tenantname"].as()); + if (pt.get_optional("openstack.tenantname")) { + m_sOpenStackTenantName.assign(pt.get("openstack.tenantname")); } else { m_sOpenStackTenantName.clear(); } - if (m_pVm->count("hyperv.hostusername")) { - m_sHyperVHostUsername.assign((*m_pVm)["hyperv.hostusername"].as()); + if (pt.get_optional("hyperv.hostusername")) { + m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); } else { m_sHyperVHostUsername.clear(); } - if (m_pVm->count("hyperv.hostpassword")) { - m_sHyperVHostPassword.assign((*m_pVm)["hyperv.hostpassword"].as()); + if (pt.get_optional("hyperv.hostpassword")) { + m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); } else { m_sHyperVHostPassword.clear(); } @@ -1132,7 +1114,7 @@ namespace wsgate { return false; } - } catch (const po::error &e) { + } catch (const boost::property_tree::ini_parser_error &e) { cerr << e.what() << endl; return false; } @@ -1141,6 +1123,14 @@ namespace wsgate { private: + template + std::vector as_vector(boost::property_tree::ptree const& pt, boost::property_tree::ptree::key_type const& key){ + std::vector r; + for (auto& item : pt.get_child(key)) + r.push_back(item.second.get_value()); + return r; + } + bool notModified(HttpRequest *request, HttpResponse *response, time_t mtime) { string ifms(request->Headers("if-modified-since")); @@ -1296,7 +1286,7 @@ namespace wsgate { string m_sRdpOverridePass; WsRdpParams m_RdpOverrideParams; string m_sConfigFile; - po::variables_map *m_pVm; + boost::property_tree::ptree m_ptIniConfig; bool m_bDaemon; bool m_bRedirect; StaticCache m_StaticCache; @@ -1579,22 +1569,20 @@ int main (int argc, char **argv) if (!srv.ReadConfig(&log)) { return -1; } - po::variables_map *pvm = srv.GetConfig(); - if (NULL == pvm) { - return -1; - } + + boost::property_tree::ptree pt = srv.GetConfig(); int port = -1; bool https = false; bool need2 = false; - if (pvm->count("ssl.port")) { - port = (*pvm)["ssl.port"].as(); + if (pt.get_optional("ssl.port")) { + port = pt.get("ssl.port"); https = true; - if (pvm->count("global.port")) { + if (pt.get_optional("global.port")) { need2 = true; } - } else if (pvm->count("global.port")) { - port = (*pvm)["global.port"].as(); + } else if (pt.get_optional("global.port")) { + port = pt.get("global.port"); } #ifndef _WIN32 @@ -1609,34 +1597,34 @@ int main (int argc, char **argv) oSP["bindaddress"] = "0.0.0.0"; oSP["norouterequest"] = 1; if (https) { - if (pvm->count("ssl.bindaddr")) { - oSP["bindaddress"] = (*pvm)["ssl.bindaddr"].as(); + if (pt.get_optional("ssl.bindaddr")) { + oSP["bindaddress"] = pt.get("ssl.bindaddr"); } oSP["https"] = 1; - if (pvm->count("ssl.certfile")) { - oSP["certificate"] = (*pvm)["ssl.certfile"].as(); + if (pt.get_optional("ssl.certfile")) { + oSP["certificate"] = pt.get("ssl.certfile"); } - if (pvm->count("ssl.certpass")) { - oSP["passphrase"] = (*pvm)["ssl.certpass"].as(); + if (pt.get_optional("ssl.certpass")) { + oSP["passphrase"] = pt.get("ssl.certpass"); } } else { - if (pvm->count("global.bindaddr")) { - oSP["bindaddress"] = (*pvm)["global.bindaddr"].as(); + if (pt.get_optional("global.bindaddr")) { + oSP["bindaddress"] = pt.get("global.bindaddr"); } } - if (pvm->count("http.maxrequestsize")) { - oSP["maxrequestsize"] = (*pvm)["http.maxrequestsize"].as(); + if (pt.get_optional("http.maxrequestsize")) { + oSP["maxrequestsize"] = pt.get("http.maxrequestsize"); } bool sleepInLoop = true; - if (pvm->count("threading.mode")) { - string mode((*pvm)["threading.mode"].as()); + if (pt.get_optional("threading.mode")) { + string mode(pt.get("threading.mode")); if (0 == mode.compare("single")) { oSP["mode"] = "singlethreaded"; sleepInLoop = false; } else if (0 == mode.compare("pool")) { oSP["mode"] = "threadpool"; - if (pvm->count("threading.poolsize")) { - oSP["threadcount"] = (*pvm)["threading.poolsize"].as(); + if (pt.get_optional("threading.poolsize")) { + oSP["threadcount"] = pt.get("threading.poolsize"); } } else if (0 == mode.compare("perrequest")) { oSP["mode"] = "onethreadperrequest"; @@ -1647,18 +1635,18 @@ int main (int argc, char **argv) } else { oSP["mode"] = "onethreadperrequest"; } - if (pvm->count("ssl.certfile")) { - oSP["certificate"] = (*pvm)["ssl.certfile"].as(); + if (pt.get_optional("ssl.certfile")) { + oSP["certificate"] = pt.get("ssl.certfile"); } - if (pvm->count("ssl.certpass")) { - oSP["passphrase"] = (*pvm)["ssl.certpass"].as(); + if (pt.get_optional("ssl.certpass")) { + oSP["passphrase"] = pt.get("ssl.certpass"); } #ifdef _WIN32 - bool daemon = (pvm->count("foreground")) ? false : g_service_background; + bool daemon = (pt.get_child_optional("foreground")) ? false : g_service_background; #else bool daemon = false; - if (pvm->count("global.daemon") && (0 == pvm->count("foreground"))) { + if (pt.get_child_optional("global.daemon") && !pt.get_child_optional("foreground")) { daemon = srv.GetDaemon(); if (daemon) { pid_t pid = fork(); @@ -1668,13 +1656,13 @@ int main (int argc, char **argv) { int nfd = open("/dev/null", O_RDWR); dup2(nfd, 0); - dup2(nfd, 1); + dup2(nfd, 1); dup2(nfd, 2); close(nfd); (void)chdir("/"); setsid(); - if (pvm->count("global.pidfile")) { - const string pidfn((*pvm)["global.pidfile"].as()); + if (pt.get_child_optional("global.pidfile")) { + const string pidfn(pt.get("global.pidfile")); if (!pidfn.empty()) { ofstream pidfile(pidfn.c_str()); pidfile << getpid() << endl; @@ -1724,9 +1712,9 @@ int main (int argc, char **argv) psrv->SetConfigFile(srv.GetConfigFile()); psrv->ReadConfig(); oSP["https"] = 0; - oSP["port"] = (*pvm)["global.port"].as(); - if (pvm->count("global.bindaddr")) { - oSP["bindaddress"] = (*pvm)["global.bindaddr"].as(); + oSP["port"] = pt.get("global.port"); + if (pt.get_child_optional("global.bindaddr")) { + oSP["bindaddress"] = pt.get("global.bindaddr"); } psrv->SetSourceEHS(srv); wsgate::MyRawSocketHandler *psh = new wsgate::MyRawSocketHandler(psrv); From 1469dfedf0bd36abd4cc1341599df847b44a1cb9 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 4 Sep 2015 22:48:18 +0300 Subject: [PATCH 043/130] Removed duplicate code --- wsgate/webroot/index-debug.html | 69 ++++++++------------------------- 1 file changed, 16 insertions(+), 53 deletions(-) diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index e352faf8..6eda4f38 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -125,10 +125,17 @@ popUpMessage('critical', "This instance seems to be not working. Try to enter the console again.", 0, noInstancePopUp, true); } - function RDPGet(uri, title) { - var wsUri = wsBase + uri; - - rdp = new wsgate.RDP(wsUri, $('screen'), !RIMtablet, RIMtablet, vkbd); + function RDPStart(uri, title){ + if(uri === undefined){ + uri = wsBase; + } + if(title === undefined){ + title = "FreeRDP WebConnect: connected to " + $('rdphost').value.trim(); + } + if(!embedded){ + $('dvLoading').setStyles({'visibility':'visible'}); + } + rdp = new wsgate.RDP(uri, $('screen'), !RIMtablet, RIMtablet, vkbd); rdp.addEvent('alert', function(msg) { popUpMessage('error', msg, 5); @@ -141,61 +148,18 @@ window.removeEvent('resize', OnDesktopSize); button.value = 'Disconnect'; button.addEvent('click', rdp.Disconnect.bind(rdp)); - }); - rdp.addEvent('disconnected', function() { - showDialog(true); - if(embedded){ - $('maindialog').addClass('invisible'); - noInstancePopUp() - } - button = $("rdpconnect"); - button.removeEvents(); - button.value = 'Connect'; - button.addEvent('click', RDPrun); - OnDesktopSize(); - window.addEvent('resize', OnDesktopSize); - }); - rdp.addEvent('mouserelease', ResetRdpMouseFlags); - rdp.addEvent('touch2', function() { - ShowMouseHelper($('mousehelper').hasClass('invisible')); - }); - - rdp.addEvent('touch3', function() { - vkbd.toggle(); - }); - - showDialog(false); - rdp.Run(); - } - - function RDPrun() { - $('dvLoading').setStyles({'visibility':'visible'}); - - rdp = new wsgate.RDP(wsBase, $('screen'), !RIMtablet, RIMtablet, vkbd); - - rdp.addEvent('alert', function(msg) { - popUpMessage('error', msg, 5); - }); - rdp.addEvent('connected', function() { - cleanPopUpDeck(); - document.title = "FreeRDP WebConnect: connected to " + - $('rdphost').value.trim(); - button = $("rdpconnect"); - button.removeEvents(); - window.removeEvent('resize', OnDesktopSize); - button.value = 'Disconnect'; - button.addEvent('click', rdp.Disconnect.bind(rdp)); window.addEvent("beforeunload", rdp.Disconnect.bind(rdp)); }); rdp.addEvent('disconnected', function() { showDialog(true); if(embedded){ $('maindialog').addClass('invisible'); + noInstancePopUp() } button = $("rdpconnect"); button.removeEvents(); button.value = 'Connect'; - button.addEvent('click', RDPrun); + button.addEvent('click', function(){RDPStart();}); OnDesktopSize(); window.addEvent('resize', OnDesktopSize); }); @@ -211,7 +175,6 @@ rdp.Disconnect(); } }); - showDialog(false); rdp.Run(); } @@ -463,7 +426,7 @@ (Browser.ie && (Browser.version >= 10.0)); if(externalConnection == true) { - RDPrun(); + RDPStart(); vkbd = new wsgate.vkbd({ version:false, sizeswitch:false, @@ -490,11 +453,11 @@ while (match = search.exec(query)) urlParams[decode(match[1])] = decode(match[2]); })(); - RDPGet(querystring, urlParams["title"]); + RDPStart(wsBase + querystring, urlParams["title"]); } else { - $('rdpconnect').addEvent('click', RDPrun); + $('rdpconnect').addEvent('click', function(){RDPStart();}); showDialog(true); } vkbd = new wsgate.vkbd({ From 02c979dfedc00e29e26b3c0f558cb73588e8c24a Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 4 Sep 2015 23:56:09 +0300 Subject: [PATCH 044/130] Moved EHS implementation from main to it's own file --- wsgate/wsgateEHS.cpp | 1073 +++++++++++++++++++++++++++++++++++++ wsgate/wsgateEHS.hpp | 185 +++++++ wsgate/wsgate_main.cpp | 1141 ---------------------------------------- 3 files changed, 1258 insertions(+), 1141 deletions(-) create mode 100644 wsgate/wsgateEHS.cpp create mode 100644 wsgate/wsgateEHS.hpp diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp new file mode 100644 index 00000000..e60da46e --- /dev/null +++ b/wsgate/wsgateEHS.cpp @@ -0,0 +1,1073 @@ +#include "wsgateEHS.hpp" + +namespace wsgate{ + WsGate::MimeType WsGate::simpleMime(const string & filename) + { + if (ends_with(filename, ".txt")) + return TEXT; + if (ends_with(filename, ".html")) + return HTML; + if (ends_with(filename, ".png")) + return PNG; + if (ends_with(filename, ".ico")) + return ICO; + if (ends_with(filename, ".js")) + return JAVASCRIPT; + if (ends_with(filename, ".json")) + return JSON; + if (ends_with(filename, ".css")) + return CSS; + if (ends_with(filename, ".cur")) + return CUR; + if (ends_with(filename, ".ogg")) + return OGG; + return BINARY; + } + + WsGate::WsGate(EHS *parent = NULL, std::string registerpath = "") + : EHS(parent, registerpath) + , m_sHostname() + , m_sDocumentRoot() + , m_sPidFile() + , m_bDebug(false) + , m_bEnableCore(false) + , m_SessionMap() + , m_allowedHosts() + , m_deniedHosts() + , m_bOrderDenyAllow(true) + , m_bOverrideRdpHost(false) + , m_bOverrideRdpPort(false) + , m_bOverrideRdpUser(false) + , m_bOverrideRdpPass(false) + , m_bOverrideRdpPerf(false) + , m_bOverrideRdpNowallp(false) + , m_bOverrideRdpNowdrag(false) + , m_bOverrideRdpNomani(false) + , m_bOverrideRdpNotheme(false) + , m_bOverrideRdpNotls(false) + , m_bOverrideRdpNonla(false) + , m_bOverrideRdpFntlm(false) + , m_sRdpOverrideHost() + , m_sRdpOverrideUser() + , m_sRdpOverridePass() + , m_RdpOverrideParams() + , m_sConfigFile() + , m_ptIniConfig() + , m_bDaemon(false) + , m_bRedirect(false) + , m_StaticCache() + { + } + + WsGate::~WsGate() + { + if (!m_sPidFile.empty()) { + unlink(m_sPidFile.c_str()); + } + } + + HttpResponse* WsGate::HandleThreadException(ehs_threadid_t, HttpRequest *request, exception &ex) + { + HttpResponse *ret = NULL; + string msg(ex.what()); + log::err << "##################### Catched " << msg << endl; + log::err << "request: " << hex << request << dec << endl; + tracing::exception *btx = + dynamic_cast(&ex); + if (NULL != btx) { + string tmsg = btx->where(); + log::err << "Backtrace:" << endl << tmsg; + if (0 != msg.compare("fatal")) { + ret = HttpResponse::Error(HTTPRESPONSECODE_500_INTERNALSERVERERROR, request); + string body(ret->GetBody()); + tmsg.insert(0, "
\n
").append(msg).append("

Back to main page"); + body.insert(body.find(""), tmsg); + ret->SetBody(body.c_str(), body.length()); + } + } else { + ret = HttpResponse::Error(HTTPRESPONSECODE_500_INTERNALSERVERERROR, request); + } + return ret; + } + + void WsGate::CheckForPredefined(string& rdpHost, string& rdpUser, string& rdpPass) + { + if (m_bOverrideRdpHost) + rdpHost.assign(m_sRdpOverrideHost); + + if (m_bOverrideRdpUser) + rdpUser.assign(m_sRdpOverrideUser); + + if (m_bOverrideRdpPass) + rdpPass.assign(m_sRdpOverridePass); + } + + bool WsGate::ConnectionIsAllowed(string rdphost) + { + bool denied = true; + vector::iterator ri; + if (m_bOrderDenyAllow) { + denied = false; + for (ri = m_deniedHosts.begin(); ri != m_deniedHosts.end(); ++ri) { + if (regex_match(rdphost, *ri)) { + denied = true; + break; + } + } + for (ri = m_allowedHosts.begin(); ri != m_allowedHosts.end(); ++ri) { + if (regex_match(rdphost, *ri)) { + denied = false; + break; + } + } + } else { + for (ri = m_allowedHosts.begin(); ri != m_allowedHosts.end(); ++ri) { + if (regex_match(rdphost, *ri)) { + denied = false; + break; + } + } + for (ri = m_deniedHosts.begin(); ri != m_deniedHosts.end(); ++ri) { + if (regex_match(rdphost, *ri)) { + denied = true; + break; + } + } + } + return true; + } + + void WsGate::LogInfo(std::basic_string remoteAdress, string uri, const char response[]) + { + log::info << "Request FROM: " << remoteAdress << " replied with " << response << endl; + } + + ResponseCode WsGate::HandleRobotsRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) + { + response->SetHeader("Content-Type", "text/plain"); + response->SetBody("User-agent: *\nDisallow: /\n", 26); + return HTTPRESPONSECODE_200_OK; + } + + /* =================================== CURSOR HANDLING =================================== */ + ResponseCode WsGate::HandleCursorRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) + { + string idpart(uri.substr(5)); + vector parts; + boost::split(parts, idpart, is_any_of("/")); + SessionMap::iterator it = m_SessionMap.find(parts[0]); + if (it != m_SessionMap.end()) { + uint32_t cid = 0; + try { + cid = boost::lexical_cast(parts[1]); + } catch (const boost::bad_lexical_cast & e) { cid = 0; } + if (cid) { + RDP::cursor c = it->second->GetCursor(cid); + time_t ct = c.get<0>(); + if (0 != ct) { + if (notModified(request, response, ct)) { + return HTTPRESPONSECODE_304_NOT_MODIFIED; + } + string png = c.get<1>(); + if (!png.empty()) { + response->SetHeader("Content-Type", "image/cur"); + response->SetLastModified(ct); + response->SetBody(png.data(), png.length()); + LogInfo(request->RemoteAddress(), uri, "200 OK"); + return HTTPRESPONSECODE_200_OK; + } + } + } + } + LogInfo(request->RemoteAddress(), uri, "404 Not Found"); + return HTTPRESPONSECODE_404_NOTFOUND; + } + + /* =================================== REDIRECT REQUEST =================================== */ + ResponseCode WsGate::HandleRedirectRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) + { + string dest(boost::starts_with(uri, "/wsgate?") ? "wss" : "https"); + //adding the sslPort to the dest Location + if (this->m_ptIniConfig.get_optional("ssl.port")) + { + stringstream sslPort; + sslPort << this->m_ptIniConfig.get("ssl.port"); + + //Replace the http port with the ssl one + string thisSslHost = thisHost.substr(0, thisHost.find(":")) + ":" + sslPort.str(); + + //append the rest of the uri + dest.append("://").append(thisSslHost).append(uri); + response->SetHeader("Location", dest); + LogInfo(request->RemoteAddress(), uri, "301 Moved permanently"); + return HTTPRESPONSECODE_301_MOVEDPERMANENTLY; + } + else + { + LogInfo(request->RemoteAddress(), uri, "404 Not found"); + return HTTPRESPONSECODE_404_NOTFOUND; + } + + } + + /* =================================== HANDLE WSGATE REQUEST =================================== */ + int WsGate::CheckIfWSocketRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) + { + if (0 != request->HttpVersion().compare("1.1")) + { + LogInfo(request->RemoteAddress(), uri, "400 (Not HTTP 1.1)"); + return 400; + } + + string wshost(to_lower_copy(request->Headers("Host"))); + string wsconn(to_lower_copy(request->Headers("Connection"))); + string wsupg(to_lower_copy(request->Headers("Upgrade"))); + string wsver(request->Headers("Sec-WebSocket-Version")); + string wskey(request->Headers("Sec-WebSocket-Key")); + + string wsproto(request->Headers("Sec-WebSocket-Protocol")); + string wsext(request->Headers("Sec-WebSocket-Extension")); + + if (!MultivalHeaderContains(wsconn, "upgrade")) + { + LogInfo(request->RemoteAddress(), uri, "400 (No upgrade header)"); + + return 400; + } + if (!MultivalHeaderContains(wsupg, "websocket")) + { + LogInfo(request->RemoteAddress(), uri, "400 (Upgrade header does not contain websocket tag)"); + return 400; + } + if (0 != wshost.compare(thisHost)) + { + LogInfo(request->RemoteAddress(), uri, "400 (Host header does not match)"); + return 400; + } + string wskey_decoded(base64_decode(wskey)); + + if (16 != wskey_decoded.length()) + { + LogInfo(request->RemoteAddress(), uri, "400 (Invalid WebSocket key)"); + return 400; + } + + if (!MultivalHeaderContains(wsver, "13")) + { + response->SetHeader("Sec-WebSocket-Version", "13"); + LogInfo(request->RemoteAddress(), uri, "426 (Protocol version not 13)"); + return 426; + } + + return 0; + } + + ResponseCode WsGate::HandleWsgateRequest(HttpRequest *request, HttpResponse *response, std::string uri, std::string thisHost) + { + //FreeRDP Params + string dtsize; + string rdphost; + string rdppcb; + string rdpuser; + int rdpport = 0; + string rdppass; + WsRdpParams params; + bool setCookie = true; + EmbeddedContext embeddedContext = CONTEXT_PLAIN; + + if(boost::starts_with(uri, "/wsgate?token=")) + { + // OpenStack console authentication + setCookie = false; + try + { + log::info << "Starting OpenStack token authentication" << endl; + + string tokenId = request->FormValues("token").m_sBody; + + nova_console_token_auth* token_auth = nova_console_token_auth_factory::get_instance(); + + nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, + m_sOpenStackPassword, m_sOpenStackTenantName, + tokenId); + + log::info << "Host: " << info.host << " Port: " << info.port + << " Internal access path: " << info.internal_access_path + << endl; + + rdphost = info.host; + rdpport = info.port; + rdppcb = info.internal_access_path; + + rdpuser = m_sHyperVHostUsername; + rdppass = m_sHyperVHostPassword; + + embeddedContext = CONTEXT_EMBEDDED; + } + catch(exception& ex) + { + log::err << "OpenStack token authentication failed: " << ex.what() << endl; + return HTTPRESPONSECODE_400_BADREQUEST; + } + } + + params = + { + rdpport, + 1024, + 768, + m_bOverrideRdpPerf ? m_RdpOverrideParams.perf : nFormValue(request, "perf", 0), + m_bOverrideRdpFntlm ? m_RdpOverrideParams.fntlm : nFormValue(request, "fntlm", 0), + m_bOverrideRdpNotls ? m_RdpOverrideParams.notls : nFormValue(request, "notls", 0), + m_bOverrideRdpNonla ? m_RdpOverrideParams.nonla : nFormValue(request, "nonla", 0), + m_bOverrideRdpNowallp ? m_RdpOverrideParams.nowallp : nFormValue(request, "nowallp", 0), + m_bOverrideRdpNowdrag ? m_RdpOverrideParams.nowdrag : nFormValue(request, "nowdrag", 0), + m_bOverrideRdpNomani ? m_RdpOverrideParams.nomani : nFormValue(request, "nomani", 0), + m_bOverrideRdpNotheme ? m_RdpOverrideParams.notheme : nFormValue(request, "notheme", 0), + }; + + CheckForPredefined(rdphost, rdpuser, rdppass); + + if( !ConnectionIsAllowed(rdphost) ){ + LogInfo(request->RemoteAddress(), rdphost, "403 Denied by access rules"); + return HTTPRESPONSECODE_403_FORBIDDEN; + } + + if (!dtsize.empty()) { + try { + vector wh; + boost::split(wh, dtsize, is_any_of("x")); + if (wh.size() == 2) { + params.width = boost::lexical_cast(wh[0]); + params.height = boost::lexical_cast(wh[1]); + } + } catch (const exception &e) { + params.width = 1024; + params.height = 768; + } + } + response->SetBody("", 0); + + int wsocketCheck = CheckIfWSocketRequest(request, response, uri, thisHost); + if(wsocketCheck != 0) + { + //using a switch in case of new errors being thrown from the wsocket check + switch(wsocketCheck) + { + case 400: + { + return HTTPRESPONSECODE_400_BADREQUEST; + }; + case 426: + { + return HTTPRESPONSECODE_426_UPGRADE_REQUIRED; + }; + } + } + + string wskey(request->Headers("Sec-WebSocket-Key")); + SHA1 sha1; + uint32_t digest[5]; + sha1 << wskey.c_str() << ws_magic; + if (!sha1.Result(digest)) + { + LogInfo(request->RemoteAddress(), uri, "500 (Digest calculation failed)"); + return HTTPRESPONSECODE_500_INTERNALSERVERERROR; + } + // Handle endianess + for (int i = 0; i < 5; ++i) + { + digest[i] = htonl(digest[i]); + } + MyRawSocketHandler *sh = dynamic_cast(GetRawSocketHandler()); + if (!sh) + { + throw tracing::runtime_error("No raw socket handler available"); + } + response->EnableIdleTimeout(false); + response->EnableKeepAlive(true); + try + { + if (!sh->Prepare(request->Connection(), rdphost, rdppcb, rdpuser, rdppass, params, embeddedContext)) + { + LogInfo(request->RemoteAddress(), uri, "503 (RDP backend not available)"); + response->EnableIdleTimeout(true); + return HTTPRESPONSECODE_503_SERVICEUNAVAILABLE; + } + } + catch(...) + { + log::info << "caught exception!" << endl; + } + + response->RemoveHeader("Content-Type"); + response->RemoveHeader("Content-Length"); + response->RemoveHeader("Last-Modified"); + response->RemoveHeader("Cache-Control"); + + string wsproto(request->Headers("Sec-WebSocket-Protocol")); + if (0 < wsproto.length()) + { + response->SetHeader("Sec-WebSocket-Protocol", wsproto); + } + response->SetHeader("Upgrade", "websocket"); + response->SetHeader("Connection", "Upgrade"); + response->SetHeader("Sec-WebSocket-Accept", base64_encode(reinterpret_cast(digest), 20)); + + LogInfo(request->RemoteAddress(), uri, "101"); + return HTTPRESPONSECODE_101_SWITCHING_PROTOCOLS; + } + + // generates a page for each http request + ResponseCode WsGate::HandleRequest(HttpRequest *request, HttpResponse *response) + { + //Connection Params + string uri = request->Uri(); + string thisHost = m_sHostname.empty() ? request->Headers("Host") : m_sHostname; + + //add new behaviour note: + //those requests that have the same beggining have to be placed with an if else condition + + if(request->Method() != REQUESTMETHOD_GET) + return HTTPRESPONSECODE_400_BADREQUEST; + + if (m_bRedirect && (!request->Secure())) + { + return HandleRedirectRequest(request, response, uri, thisHost); + } + + if(boost::starts_with(uri, "/robots.txt")) + { + return HandleRobotsRequest(request, response, uri, thisHost); + } + if(boost::starts_with(uri, "/cur/")) + { + return HandleCursorRequest(request, response, uri, thisHost); + } + + if(boost::starts_with(uri, "/wsgate")) + { + return HandleWsgateRequest(request, response, uri, thisHost); + } + + if(boost::starts_with(uri, "/connect?")) + { + //handle a direct connection via queryString here + return HTTPRESPONSECODE_200_OK; + } + return HandleHTTPRequest(request, response); + } + + ResponseCode WsGate::HandleHTTPRequest(HttpRequest *request, HttpResponse *response, bool tokenAuth = false) + { + string uri(request->Uri()); + string thisHost(m_sHostname.empty() ? request->Headers("Host") : m_sHostname); + + // Regular (non WebSockets) request + bool bDynDebug = m_bDebug; + if (!bDynDebug) { + // Enable debugging by using a custom UserAgent header + if (iequals(request->Headers("X-WSGate-Debug"), "true")) { + bDynDebug = true; + } + } + if (0 != thisHost.compare(request->Headers("Host"))) { + LogInfo(request->RemoteAddress(), uri, "404 Not found"); + return HTTPRESPONSECODE_404_NOTFOUND; + } + + path p(m_sDocumentRoot); + p /= uri; + if (ends_with(uri, "/")) { + p /= (bDynDebug ? "/index-debug.html" : "/index.html"); + } + p.normalize(); + bool externalRequest = false; + + if (!exists(p)) { + p = m_sDocumentRoot; + p /= "index.html"; + } + + if (!is_regular_file(p)) { + LogInfo(request->RemoteAddress(), uri, "403 Forbidden"); + log::warn << "Request from " << request->RemoteAddress() + << ": " << uri << " => 403 Forbidden" << endl; + + p = m_sDocumentRoot; + p /= "index.html"; + } + + // Handle If-modified-sice request header + time_t mtime = last_write_time(p); + if (notModified(request, response, mtime)) { + return HTTPRESPONSECODE_304_NOT_MODIFIED; + } + response->SetLastModified(mtime); + + string body; + StaticCache::iterator ci = m_StaticCache.find(p); + if ((m_StaticCache.end() != ci) && (ci->second.get<0>() == mtime)) { + body.assign(ci->second.get<1>()); + } else { + fs::ifstream f(p, ios::binary); + if (f.fail()) { + log::warn << "Request from " << request->RemoteAddress() + << ": " << uri << " => 404 (file '" << p << "' unreadable)" << endl; + return HTTPRESPONSECODE_404_NOTFOUND; + } + body.assign((istreambuf_iterator(f)), istreambuf_iterator()); + f.close(); + m_StaticCache[p] = cache_entry(mtime, body); + } + +#ifdef BOOST_FILESYSTEM_VERSION +#if (BOOST_FILESYSTEM_VERSION >= 3) + string basename(p.filename().generic_string()); +#else + string basename(p.filename()); +#endif +#else + // Not defined at all: old API + string basename(p.filename()); +#endif + + MimeType mt = simpleMime(to_lower_copy(basename)); + if (HTML == mt) { + ostringstream oss; + + oss << (request->Secure() ? "wss://" : "ws://") << thisHost << "/wsgate"; + + replace_all(body, "%WSURI%", oss.str()); + replace_all(body, "%JSDEBUG%", (bDynDebug ? "-debug" : "")); + string tmp; + if(externalRequest) + { + string dtsize(request->FormValues("dtsize").m_sBody); + string port(request->FormValues("port").m_sBody); + + replace_all(body, "%COOKIE_LASTUSER%", request->FormValues("user").m_sBody); + replace_all(body, "%COOKIE_LASTPASS%", base64_decode(request->FormValues("pass").m_sBody)); // Passw0rd + replace_all(body, "%COOKIE_LASTHOST%", request->FormValues("host").m_sBody); + replace_all(body, "%COOKIE_LASTPCB%", request->FormValues("pcb").m_sBody); + replace_all(body, "var externalConnection = false;", "var externalConnection = true;"); + } + else + { + tmp.assign(m_bOverrideRdpUser ? "" : request->Cookies("lastuser")); + replace_all(body, "%COOKIE_LASTUSER%", tmp); + tmp.assign(m_bOverrideRdpUser ? "disabled=\"disabled\"" : ""); + replace_all(body, "%DISABLED_USER%", tmp); + tmp.assign(m_bOverrideRdpPass ? "SomthingUseless" : base64_decode(request->Cookies("lastpass"))); + replace_all(body, "%COOKIE_LASTPASS%", tmp); + tmp.assign(m_bOverrideRdpPass ? "disabled=\"disabled\"" : ""); + replace_all(body, "%DISABLED_PASS%", tmp); + + tmp.assign(m_bOverrideRdpHost ? "" : request->Cookies("lasthost")); + replace_all(body, "%COOKIE_LASTHOST%", tmp); + tmp.assign(m_bOverrideRdpHost ? "disabled=\"disabled\"" : ""); + replace_all(body, "%DISABLED_HOST%", tmp); + + tmp.assign(request->Cookies("lastpcb")); + replace_all(body, "%COOKIE_LASTPCB%", tmp); + tmp.assign(""); + replace_all(body, "%DISABLED_PCB%", tmp); + } + + tmp.assign(VERSION).append(".").append(GITREV); + replace_all(body, "%VERSION%", tmp); + + //The new Port Selector + if(m_bOverrideRdpPort) { + replace_all(body, "%DISABLED_PORT%", "disabled=\"disabled\""); + } else { + replace_all(body, "%DISABLED_PORT%", ""); + } + + tmp.assign(m_bOverrideRdpPort ? boost::lexical_cast(m_RdpOverrideParams.port) : "3389"); + replace_all(body, "%DEFAULT_PORT%", tmp); + + //The Desktop Resolution + if (m_bOverrideRdpPerf) { + replace_all(body, "%DISABLED_PERF%", "disabled=\"disabled\""); + replace_all(body, "%SELECTED_PERF0%", (0 == m_RdpOverrideParams.perf) ? "selected" : ""); + replace_all(body, "%SELECTED_PERF1%", (1 == m_RdpOverrideParams.perf) ? "selected" : ""); + replace_all(body, "%SELECTED_PERF2%", (2 == m_RdpOverrideParams.perf) ? "selected" : ""); + } else { + replace_all(body, "%DISABLED_PERF%", ""); + replace_all(body, "%SELECTED_PERF0%", ""); + replace_all(body, "%SELECTED_PERF1%", ""); + replace_all(body, "%SELECTED_PERF2%", ""); + } + + + if (m_bOverrideRdpFntlm) { + replace_all(body, "%DISABLED_FNTLM%", "disabled=\"disabled\""); + replace_all(body, "%SELECTED_FNTLM0%", (0 == m_RdpOverrideParams.fntlm) ? "selected" : ""); + replace_all(body, "%SELECTED_FNTLM1%", (1 == m_RdpOverrideParams.fntlm) ? "selected" : ""); + replace_all(body, "%SELECTED_FNTLM2%", (2 == m_RdpOverrideParams.fntlm) ? "selected" : ""); + } else { + replace_all(body, "%DISABLED_FNTLM%", ""); + replace_all(body, "%SELECTED_FNTLM0%", ""); + replace_all(body, "%SELECTED_FNTLM1%", ""); + replace_all(body, "%SELECTED_FNTLM2%", ""); + } + if (m_bOverrideRdpNowallp) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowallp) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NOWALLP%", tmp); + if (m_bOverrideRdpNowdrag) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowdrag) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NOWDRAG%", tmp); + if (m_bOverrideRdpNomani) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nomani) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NOMANI%", tmp); + if (m_bOverrideRdpNotheme) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notheme) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NOTHEME%", tmp); + if (m_bOverrideRdpNotls) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notls) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NOTLS%", tmp); + if (m_bOverrideRdpNonla) { + tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nonla) ? " checked=\"checked\"" : ""); + } else { + tmp.assign(""); + } + replace_all(body, "%CHECKED_NONLA%", tmp); + } + switch (mt) { + case TEXT: + response->SetHeader("Content-Type", "text/plain"); + response->SetHeader("Cache-Control", "no-cache, private"); + break; + case HTML: + response->SetHeader("Content-Type", "text/html"); + response->SetHeader("Cache-Control", "no-cache, private"); + break; + case PNG: + response->SetHeader("Content-Type", "image/png"); + break; + case ICO: + response->SetHeader("Content-Type", "image/x-icon"); + break; + case JAVASCRIPT: + response->SetHeader("Content-Type", "text/javascript"); + break; + case JSON: + response->SetHeader("Content-Type", "application/json"); + break; + case CSS: + response->SetHeader("Content-Type", "text/css"); + break; + case OGG: + response->SetHeader("Content-Type", "audio/ogg"); + break; + case CUR: + response->SetHeader("Content-Type", "image/cur"); + break; + case BINARY: + response->SetHeader("Content-Type", "application/octet-stream"); + break; + } + response->SetBody(body.data(), body.length()); + + LogInfo(request->RemoteAddress(), uri, "200 OK"); + return HTTPRESPONSECODE_200_OK; + } + + boost::property_tree::ptree WsGate::GetConfig() { + return this->m_ptIniConfig; + } + + const string & WsGate::GetConfigFile() { + return m_sConfigFile; + } + + bool WsGate::GetEnableCore() { + return m_bEnableCore; + } + + bool WsGate::SetConfigFile(const string &name) { + if (name.empty()) { +#ifdef _WIN32 + wsgate::log::err << "Config filename is empty." << endl; +#endif + cerr << "Config filename is empty." << endl; + return false; + } + m_sConfigFile = name; + return true; + } + + bool WsGate::ReadConfig(wsgate::log *logger = NULL) { + // config file options + po::options_description cfg(""); + cfg.add_options() + ("global.daemon", po::value(), "enable/disable daemon mode") + ("global.pidfile", po::value(), "path of PID file in daemon mode") + ("global.debug", po::value(), "enable/disable debugging") + ("global.enablecore", po::value(), "enable/disable coredumps") + ("global.hostname", po::value(), "specify host name") + ("global.port", po::value(), "specify listening port") + ("global.bindaddr", po::value(), "specify bind address") + ("global.redirect", po::value(), "Flag: Always redirect non-SSL to SSL") + ("global.logmask", po::value(), "specify syslog mask") + ("global.logfacility", po::value(), "specify syslog facility") + ("ssl.port", po::value(), "specify listening port for SSL") + ("ssl.bindaddr", po::value(), "specify bind address for SSL") + ("ssl.certfile", po::value(), "specify certificate file") + ("ssl.certpass", po::value(), "specify certificate passphrase") + ("threading.mode", po::value(), "specify threading mode") + ("threading.poolsize", po::value(), "specify threading pool size") + ("http.maxrequestsize", po::value(), "specify maximum http request size") + ("http.documentroot", po::value(), "specify http document root") + ("acl.allow", po::value>()->multitoken(), "Allowed destination hosts or nets") + ("acl.deny", po::value>()->multitoken(), "Denied destination hosts or nets") + ("acl.order", po::value(), "Order (deny,allow or allow,deny)") + ("rdpoverride.host", po::value(), "Predefined RDP destination host") + ("rdpoverride.port", po::value(), "Predefined RDP port") + ("rdpoverride.user", po::value(), "Predefined RDP user") + ("rdpoverride.pass", po::value(), "Predefined RDP password") + ("rdpoverride.performance", po::value(), "Predefined RDP performance") + ("rdpoverride.nowallpaper", po::value(), "Predefined RDP flag: No wallpaper") + ("rdpoverride.nofullwindowdrag", po::value(), "Predefined RDP flag: No full window drag") + ("rdpoverride.nomenuanimation", po::value(), "Predefined RDP flag: No full menu animation") + ("rdpoverride.notheming", po::value(), "Predefined RDP flag: No theming") + ("rdpoverride.notls", po::value(), "Predefined RDP flag: Disable TLS") + ("rdpoverride.nonla", po::value(), "Predefined RDP flag: Disable NLA") + ("rdpoverride.forcentlm", po::value(), "Predefined RDP flag: Force NTLM") + ("rdpoverride.size", po::value(), "Predefined RDP desktop size") + ("openstack.authurl", po::value(), "OpenStack authentication URL") + ("openstack.username", po::value(), "OpenStack username") + ("openstack.password", po::value(), "OpenStack password") + ("openstack.tenantname", po::value(), "OpenStack tenant name") + ("hyperv.hostusername", po::value(), "Hyper-V username") + ("hyperv.hostpassword", po::value(), "Hyper-V user's password") + ; + + try { + boost::property_tree::ini_parser::read_ini(m_sConfigFile, this->m_ptIniConfig); + boost::property_tree::ptree pt = this->m_ptIniConfig; + + try { + // Examine values from config file + m_bDaemon = str2bool(pt.get("global.daemon","false")); + m_bDebug = str2bool(pt.get("global.debug","false")); + m_bEnableCore = str2bool(pt.get("global.enablecore","false")); + if (pt.get_optional("global.logmask")) { + if (NULL != logger) { + logger->setmaskByName(to_upper_copy(pt.get("global.logmask"))); + } + } + if (pt.get_optional("global.logfacility")) { + if (NULL != logger) { + logger->setfacilityByName(to_upper_copy(pt.get("global.logfacility"))); + } + } + if (!pt.get_optional("global.port") && !pt.get_optional("ssl.port")) { + throw tracing::invalid_argument("No listening ports defined."); + } + + if (!pt.get_optional("http.documentroot")) { + throw tracing::invalid_argument("No documentroot defined."); + } + m_sDocumentRoot.assign(pt.get("http.documentroot")); + if (m_sDocumentRoot.empty()) { + throw tracing::invalid_argument("documentroot is empty."); + } + + m_bRedirect = str2bool(pt.get("global.redirect","false")); + + if (pt.get_optional("acl.order")) { + setAclOrder(pt.get("acl.order")); + } + if (pt.get_child_optional("acl.allow")) { + setHostList(as_vector(pt, "acl.allow"), m_allowedHosts); + } + if (pt.get_child_optional("acl.deny")) { + setHostList(as_vector(pt, "acl.deny"), m_deniedHosts); + } + + if (pt.get_optional("rdpoverride.host")) { + m_sRdpOverrideHost.assign(pt.get("rdpoverride.host")); + m_bOverrideRdpHost = true; + } else { + m_bOverrideRdpHost = false; + } + if (pt.get_optional("rdpoverride.user")) { + m_sRdpOverrideUser.assign(pt.get("rdpoverride.user")); + m_bOverrideRdpUser = true; + } else { + m_bOverrideRdpUser = false; + } + if (pt.get_optional("rdpoverride.pass")) { + m_sRdpOverridePass.assign(pt.get("rdpoverride.pass")); + m_bOverrideRdpPass = true; + } else { + m_bOverrideRdpPass = false; + } + + if (pt.get_optional("rdpoverride.port")) { + int n = pt.get("rdpoverride.port"); + if ((0 > n) || (2 < n)) { + throw tracing::invalid_argument("Invalid port value."); + } + m_RdpOverrideParams.port = n; + m_bOverrideRdpPort = true; + } else { + m_bOverrideRdpPort = false; + } + + if (pt.get_optional("rdpoverride.performance")) { + int n = pt.get("rdpoverride.performance"); + if ((0 > n) || (2 < n)) { + throw tracing::invalid_argument("Invalid performance value."); + } + m_RdpOverrideParams.perf = n; + m_bOverrideRdpPerf = true; + } else { + m_bOverrideRdpPerf = false; + } + if (pt.get_optional("rdpoverride.forcentlm")) { + int n = pt.get("rdpoverride.forcentlm"); + if ((0 > n) || (2 < n)) { + throw tracing::invalid_argument("Invalid forcentlm value."); + } + m_RdpOverrideParams.fntlm = n; + m_bOverrideRdpFntlm = true; + } else { + m_bOverrideRdpFntlm = false; + } + if (pt.get_optional("rdpoverride.nowallpaper")) { + m_RdpOverrideParams.nowallp = str2bint(pt.get("rdpoverride.nowallpaper")); + m_bOverrideRdpNowallp = true; + } else { + m_bOverrideRdpNowallp = false; + } + if (pt.get_optional("rdpoverride.nofullwindowdrag")) { + m_RdpOverrideParams.nowdrag = str2bint(pt.get("rdpoverride.nofullwindowdrag")); + m_bOverrideRdpNowdrag = true; + } else { + m_bOverrideRdpNowdrag = false; + } + if (pt.get_optional("rdpoverride.nomenuanimation")) { + m_RdpOverrideParams.nomani = str2bint(pt.get("rdpoverride.nomenuanimation")); + m_bOverrideRdpNomani = true; + } else { + m_bOverrideRdpNomani = false; + } + if (pt.get_optional("rdpoverride.notheming")) { + m_RdpOverrideParams.notheme = str2bint(pt.get("rdpoverride.notheming")); + m_bOverrideRdpNotheme = true; + } else { + m_bOverrideRdpNotheme = false; + } + if (pt.get_optional("rdpoverride.notls")) { + m_RdpOverrideParams.notls = str2bint(pt.get("rdpoverride.notls")); + m_bOverrideRdpNotls = true; + } else { + m_bOverrideRdpNotls = false; + } + if (pt.get_optional("rdpoverride.nonla")) { + m_RdpOverrideParams.nonla = str2bint(pt.get("rdpoverride.nonla")); + m_bOverrideRdpNonla = true; + } else { + m_bOverrideRdpNonla = false; + } + if (pt.get_optional("global.hostname")) { + m_sHostname.assign(pt.get("global.hostname")); + } else { + m_sHostname.clear(); + } + if (pt.get_optional("openstack.authurl")) { + m_sOpenStackAuthUrl.assign(pt.get("openstack.authurl")); + } else { + m_sOpenStackAuthUrl.clear(); + } + if (pt.get_optional("openstack.username")) { + m_sOpenStackUsername.assign(pt.get("openstack.username")); + } else { + m_sOpenStackUsername.clear(); + } + if (pt.get_optional("openstack.password")) { + m_sOpenStackPassword.assign(pt.get("openstack.password")); + } else { + m_sOpenStackPassword.clear(); + } + if (pt.get_optional("openstack.tenantname")) { + m_sOpenStackTenantName.assign(pt.get("openstack.tenantname")); + } else { + m_sOpenStackTenantName.clear(); + } + if (pt.get_optional("hyperv.hostusername")) { + m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); + } else { + m_sHyperVHostUsername.clear(); + } + if (pt.get_optional("hyperv.hostpassword")) { + m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); + } else { + m_sHyperVHostPassword.clear(); + } + } catch (const tracing::invalid_argument & e) { + cerr << e.what() << endl; + wsgate::log::err << e.what() << endl; + wsgate::log::err << e.where() << endl; + return false; + } + + } catch (const boost::property_tree::ini_parser_error &e) { + cerr << e.what() << endl; + return false; + } + return true; + } + + template std::vector WsGate::as_vector(boost::property_tree::ptree const& pt, boost::property_tree::ptree::key_type const& key){ + std::vector r; + for (auto& item : pt.get_child(key)) + r.push_back(item.second.get_value()); + return r; + } + + bool WsGate::notModified(HttpRequest *request, HttpResponse *response, time_t mtime) + { + string ifms(request->Headers("if-modified-since")); + if (!ifms.empty()) { + pt::ptime file_time(pt::from_time_t(mtime)); + pt::ptime req_time; + istringstream iss(ifms); + iss.imbue(locale(locale::classic(), + new pt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"))); + iss >> req_time; + if (file_time <= req_time) { + response->RemoveHeader("Content-Type"); + response->RemoveHeader("Content-Length"); + response->RemoveHeader("Last-Modified"); + response->RemoveHeader("Cache-Control"); + log::info << "Request from " << request->RemoteAddress() + << ": " << request->Uri() << " => 304 Not modified" << endl; + return true; + } + } + return false; + } + + int WsGate::str2bint(const string &s) { + string v(s); + trim(v); + if (!v.empty()) { + if (iequals(v, "true")) { + return 1; + } + if (iequals(v, "yes")) { + return 1; + } + if (iequals(v, "on")) { + return 1; + } + if (iequals(v, "1")) { + return 1; + } + if (iequals(v, "false")) { + return 0; + } + if (iequals(v, "no")) { + return 0; + } + if (iequals(v, "off")) { + return 0; + } + if (iequals(v, "0")) { + return 0; + } + } + throw tracing::invalid_argument("Invalid boolean value"); + } + + bool WsGate::str2bool(const string &s) { + return (1 == str2bint(s)); + } + + void WsGate::wc2pat(string &wildcards) { + boost::replace_all(wildcards, "\\", "\\\\"); + boost::replace_all(wildcards, "^", "\\^"); + boost::replace_all(wildcards, ".", "\\."); + boost::replace_all(wildcards, "$", "\\$"); + boost::replace_all(wildcards, "|", "\\|"); + boost::replace_all(wildcards, "(", "\\("); + boost::replace_all(wildcards, ")", "\\)"); + boost::replace_all(wildcards, "[", "\\["); + boost::replace_all(wildcards, "]", "\\]"); + boost::replace_all(wildcards, "*", "\\*"); + boost::replace_all(wildcards, "+", "\\+"); + boost::replace_all(wildcards, "?", "\\?"); + boost::replace_all(wildcards, "/", "\\/"); + boost::replace_all(wildcards, "\\?", "."); + boost::replace_all(wildcards, "\\*", ".*"); + wildcards.insert(0, "^").append("$"); + } + + void WsGate::setHostList(const vector &hosts, vector &hostlist) { + vector tmp(hosts); + vector::iterator i; + hostlist.clear(); + for (i = tmp.begin(); i != tmp.end(); ++i) { + wc2pat(*i); + boost::regex re(*i, boost::regex::icase); + hostlist.push_back(re); + } + } + + void WsGate::setAclOrder(const string &order) { + vector parts; + boost::split(parts, order, is_any_of(",")); + if (2 == parts.size()) { + trim(parts[0]); + trim(parts[1]); + if (iequals(parts[0],"deny") && iequals(parts[1],"allow")) { + m_bOrderDenyAllow = true; + return; + } + if (iequals(parts[0],"allow") && iequals(parts[1],"deny")) { + m_bOrderDenyAllow = false; + return; + } + } + throw tracing::invalid_argument("Invalid acl order value."); + } + + bool WsGate::GetDaemon() { + return m_bDaemon; + } + + void WsGate::SetPidFile(const string &name) { + m_sPidFile = name; + } + + void WsGate::RegisterRdpSession(rdp_ptr rdp) { + ostringstream oss; + oss << hex << rdp.get(); + m_SessionMap[oss.str()] = rdp; + } + + void WsGate::UnregisterRdpSession(rdp_ptr rdp) { + ostringstream oss; + oss << hex << rdp.get(); + m_SessionMap.erase(oss.str()); + } +} diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp new file mode 100644 index 00000000..f45c26ab --- /dev/null +++ b/wsgate/wsgateEHS.hpp @@ -0,0 +1,185 @@ +#ifndef _WSGATE_EHS_ +#define _WSGATE_EHS_ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SIGNAL_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_UNISTD_H + #include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_WAIT_H +# include +#endif +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "common.hpp" +#include "btexception.hpp" +#include "base64.hpp" +#include "sha1.hpp" +#include "logging.hpp" +#include "wsendpoint.hpp" +#include "wsgate.hpp" +#include "myrawsocket.hpp" +#include "nova_token_auth.hpp" + +using namespace std; +using boost::algorithm::iequals; +using boost::algorithm::to_lower_copy; +using boost::algorithm::ends_with; +using boost::algorithm::replace_all; +using boost::algorithm::to_upper_copy; +using boost::algorithm::trim_right_copy_if; +using boost::algorithm::trim; +using boost::algorithm::is_any_of; +using boost::algorithm::split; +namespace po = boost::program_options; +namespace fs = boost::filesystem; +namespace pt = boost::posix_time; +using boost::filesystem::path; +using namespace utility::conversions; + +namespace wsgate{ + // subclass of EHS that defines a custom HTTP response. + class WsGate : public EHS + { + public: + WsGate(EHS *parent = NULL, std::string registerpath = ""); + virtual ~WsGate(); + HttpResponse *HandleThreadException(ehs_threadid_t, HttpRequest *request, exception &ex); + void CheckForPredefined(string& rdpHost, string& rdpUser, string& rdpPass); + bool ConnectionIsAllowed(string rdphost); + void LogInfo(std::basic_string remoteAdress, string uri, const char response[]); + ResponseCode HandleRobotsRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost); + ResponseCode HandleCursorRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost); + ResponseCode HandleRedirectRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost); + int CheckIfWSocketRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost); + ResponseCode HandleWsgateRequest(HttpRequest *request, HttpResponse *response, std::string uri, std::string thisHost); + ResponseCode HandleRequest(HttpRequest *request, HttpResponse *response); + ResponseCode HandleHTTPRequest(HttpRequest *request, HttpResponse *response, bool tokenAuth = false); + boost::property_tree::ptree GetConfig(); + const string & GetConfigFile(); + bool GetEnableCore(); + bool SetConfigFile(const string &name); + bool ReadConfig(wsgate::log *logger = NULL); + bool GetDaemon(); + void SetPidFile(const string &name); + void RegisterRdpSession(rdp_ptr rdp); + void UnregisterRdpSession(rdp_ptr rdp); + private: + typedef enum { + TEXT, + HTML, + PNG, + ICO, + JAVASCRIPT, + JSON, + CSS, + OGG, + CUR, + BINARY + } MimeType; + typedef map SessionMap; + typedef boost::tuple cache_entry; + typedef map StaticCache; + + string m_sHostname; + string m_sDocumentRoot; + string m_sPidFile; + bool m_bDebug; + bool m_bEnableCore; + SessionMap m_SessionMap; + vector m_allowedHosts; + vector m_deniedHosts; + bool m_bOrderDenyAllow; + bool m_bOverrideRdpHost; + bool m_bOverrideRdpPort; + bool m_bOverrideRdpUser; + bool m_bOverrideRdpPass; + bool m_bOverrideRdpPerf; + bool m_bOverrideRdpNowallp; + bool m_bOverrideRdpNowdrag; + bool m_bOverrideRdpNomani; + bool m_bOverrideRdpNotheme; + bool m_bOverrideRdpNotls; + bool m_bOverrideRdpNonla; + bool m_bOverrideRdpFntlm; + string m_sRdpOverrideHost; + string m_sRdpOverrideUser; + string m_sRdpOverridePass; + WsRdpParams m_RdpOverrideParams; + string m_sConfigFile; + boost::property_tree::ptree m_ptIniConfig; + bool m_bDaemon; + bool m_bRedirect; + StaticCache m_StaticCache; + string m_sOpenStackAuthUrl; + string m_sOpenStackUsername; + string m_sOpenStackPassword; + string m_sOpenStackTenantName; + string m_sHyperVHostUsername; + string m_sHyperVHostPassword; + + // Non-copyable + WsGate(const WsGate&); + WsGate & operator=(const WsGate&); + + MimeType simpleMime(const string & filename); + template std::vector as_vector(boost::property_tree::ptree const& pt, boost::property_tree::ptree::key_type const& key); + bool notModified(HttpRequest *request, HttpResponse *response, time_t mtime); + int str2bint(const string &s); + bool str2bool(const string &s); + void wc2pat(string &wildcards); + void setHostList(const vector &hosts, vector &hostlist); + void setAclOrder(const string &order); + }; +} + +#endif \ No newline at end of file diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 8419b748..1903d241 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -157,1147 +157,6 @@ namespace wsgate { } } - // subclass of EHS that defines a custom HTTP response. - class WsGate : public EHS - { - private: - typedef enum { - TEXT, - HTML, - PNG, - ICO, - JAVASCRIPT, - JSON, - CSS, - OGG, - CUR, - BINARY - } MimeType; - - typedef map SessionMap; - typedef boost::tuple cache_entry; - typedef map StaticCache; - - MimeType simpleMime(const string & filename) - { - if (ends_with(filename, ".txt")) - return TEXT; - if (ends_with(filename, ".html")) - return HTML; - if (ends_with(filename, ".png")) - return PNG; - if (ends_with(filename, ".ico")) - return ICO; - if (ends_with(filename, ".js")) - return JAVASCRIPT; - if (ends_with(filename, ".json")) - return JSON; - if (ends_with(filename, ".css")) - return CSS; - if (ends_with(filename, ".cur")) - return CUR; - if (ends_with(filename, ".ogg")) - return OGG; - return BINARY; - } - - // Non-copyable - WsGate(const wsgate::WsGate&); - WsGate & operator=(const wsgate::WsGate&); - - public: - - WsGate(EHS *parent = NULL, std::string registerpath = "") - : EHS(parent, registerpath) - , m_sHostname() - , m_sDocumentRoot() - , m_sPidFile() - , m_bDebug(false) - , m_bEnableCore(false) - , m_SessionMap() - , m_allowedHosts() - , m_deniedHosts() - , m_bOrderDenyAllow(true) - , m_bOverrideRdpHost(false) - , m_bOverrideRdpPort(false) - , m_bOverrideRdpUser(false) - , m_bOverrideRdpPass(false) - , m_bOverrideRdpPerf(false) - , m_bOverrideRdpNowallp(false) - , m_bOverrideRdpNowdrag(false) - , m_bOverrideRdpNomani(false) - , m_bOverrideRdpNotheme(false) - , m_bOverrideRdpNotls(false) - , m_bOverrideRdpNonla(false) - , m_bOverrideRdpFntlm(false) - , m_sRdpOverrideHost() - , m_sRdpOverrideUser() - , m_sRdpOverridePass() - , m_RdpOverrideParams() - , m_sConfigFile() - , m_ptIniConfig() - , m_bDaemon(false) - , m_bRedirect(false) - , m_StaticCache() - { - } - - virtual ~WsGate() - { - if (!m_sPidFile.empty()) { - unlink(m_sPidFile.c_str()); - } - } - - HttpResponse *HandleThreadException(ehs_threadid_t, HttpRequest *request, exception &ex) - { - HttpResponse *ret = NULL; - string msg(ex.what()); - log::err << "##################### Catched " << msg << endl; - log::err << "request: " << hex << request << dec << endl; - tracing::exception *btx = - dynamic_cast(&ex); - if (NULL != btx) { - string tmsg = btx->where(); - log::err << "Backtrace:" << endl << tmsg; - if (0 != msg.compare("fatal")) { - ret = HttpResponse::Error(HTTPRESPONSECODE_500_INTERNALSERVERERROR, request); - string body(ret->GetBody()); - tmsg.insert(0, "
\n

").append(msg).append("

Back to main page"); - body.insert(body.find(""), tmsg); - ret->SetBody(body.c_str(), body.length()); - } - } else { - ret = HttpResponse::Error(HTTPRESPONSECODE_500_INTERNALSERVERERROR, request); - } - return ret; - } - - void CheckForPredefined(string& rdpHost, string& rdpUser, string& rdpPass) - { - if (m_bOverrideRdpHost) - rdpHost.assign(m_sRdpOverrideHost); - - if (m_bOverrideRdpUser) - rdpUser.assign(m_sRdpOverrideUser); - - if (m_bOverrideRdpPass) - rdpPass.assign(m_sRdpOverridePass); - } - - bool ConnectionIsAllowed(string rdphost) - { - bool denied = true; - vector::iterator ri; - if (m_bOrderDenyAllow) { - denied = false; - for (ri = m_deniedHosts.begin(); ri != m_deniedHosts.end(); ++ri) { - if (regex_match(rdphost, *ri)) { - denied = true; - break; - } - } - for (ri = m_allowedHosts.begin(); ri != m_allowedHosts.end(); ++ri) { - if (regex_match(rdphost, *ri)) { - denied = false; - break; - } - } - } else { - for (ri = m_allowedHosts.begin(); ri != m_allowedHosts.end(); ++ri) { - if (regex_match(rdphost, *ri)) { - denied = false; - break; - } - } - for (ri = m_deniedHosts.begin(); ri != m_deniedHosts.end(); ++ri) { - if (regex_match(rdphost, *ri)) { - denied = true; - break; - } - } - } - return true; - } - - void LogInfo(std::basic_string remoteAdress, string uri, const char response[]) - { - log::info << "Request FROM: " << remoteAdress << " replied with " << response << endl; - } - - ResponseCode HandleRobotsRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) - { - response->SetHeader("Content-Type", "text/plain"); - response->SetBody("User-agent: *\nDisallow: /\n", 26); - return HTTPRESPONSECODE_200_OK; - } - - /* =================================== CURSOR HANDLING =================================== */ - ResponseCode HandleCursorRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) - { - string idpart(uri.substr(5)); - vector parts; - boost::split(parts, idpart, is_any_of("/")); - SessionMap::iterator it = m_SessionMap.find(parts[0]); - if (it != m_SessionMap.end()) { - uint32_t cid = 0; - try { - cid = boost::lexical_cast(parts[1]); - } catch (const boost::bad_lexical_cast & e) { cid = 0; } - if (cid) { - RDP::cursor c = it->second->GetCursor(cid); - time_t ct = c.get<0>(); - if (0 != ct) { - if (notModified(request, response, ct)) { - return HTTPRESPONSECODE_304_NOT_MODIFIED; - } - string png = c.get<1>(); - if (!png.empty()) { - response->SetHeader("Content-Type", "image/cur"); - response->SetLastModified(ct); - response->SetBody(png.data(), png.length()); - LogInfo(request->RemoteAddress(), uri, "200 OK"); - return HTTPRESPONSECODE_200_OK; - } - } - } - } - LogInfo(request->RemoteAddress(), uri, "404 Not Found"); - return HTTPRESPONSECODE_404_NOTFOUND; - } - - /* =================================== REDIRECT REQUEST =================================== */ - ResponseCode HandleRedirectRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) - { - string dest(boost::starts_with(uri, "/wsgate?") ? "wss" : "https"); - //adding the sslPort to the dest Location - if (this->m_ptIniConfig.get_optional("ssl.port")) - { - stringstream sslPort; - sslPort << this->m_ptIniConfig.get("ssl.port"); - - //Replace the http port with the ssl one - string thisSslHost = thisHost.substr(0, thisHost.find(":")) + ":" + sslPort.str(); - - //append the rest of the uri - dest.append("://").append(thisSslHost).append(uri); - response->SetHeader("Location", dest); - LogInfo(request->RemoteAddress(), uri, "301 Moved permanently"); - return HTTPRESPONSECODE_301_MOVEDPERMANENTLY; - } - else - { - LogInfo(request->RemoteAddress(), uri, "404 Not found"); - return HTTPRESPONSECODE_404_NOTFOUND; - } - - } - - /* =================================== HANDLE WSGATE REQUEST =================================== */ - int CheckIfWSocketRequest(HttpRequest *request, HttpResponse *response, string uri, string thisHost) - { - if (0 != request->HttpVersion().compare("1.1")) - { - LogInfo(request->RemoteAddress(), uri, "400 (Not HTTP 1.1)"); - return 400; - } - - string wshost(to_lower_copy(request->Headers("Host"))); - string wsconn(to_lower_copy(request->Headers("Connection"))); - string wsupg(to_lower_copy(request->Headers("Upgrade"))); - string wsver(request->Headers("Sec-WebSocket-Version")); - string wskey(request->Headers("Sec-WebSocket-Key")); - - string wsproto(request->Headers("Sec-WebSocket-Protocol")); - string wsext(request->Headers("Sec-WebSocket-Extension")); - - if (!MultivalHeaderContains(wsconn, "upgrade")) - { - LogInfo(request->RemoteAddress(), uri, "400 (No upgrade header)"); - - return 400; - } - if (!MultivalHeaderContains(wsupg, "websocket")) - { - LogInfo(request->RemoteAddress(), uri, "400 (Upgrade header does not contain websocket tag)"); - return 400; - } - if (0 != wshost.compare(thisHost)) - { - LogInfo(request->RemoteAddress(), uri, "400 (Host header does not match)"); - return 400; - } - string wskey_decoded(base64_decode(wskey)); - - if (16 != wskey_decoded.length()) - { - LogInfo(request->RemoteAddress(), uri, "400 (Invalid WebSocket key)"); - return 400; - } - - if (!MultivalHeaderContains(wsver, "13")) - { - response->SetHeader("Sec-WebSocket-Version", "13"); - LogInfo(request->RemoteAddress(), uri, "426 (Protocol version not 13)"); - return 426; - } - - return 0; - } - - ResponseCode HandleWsgateRequest(HttpRequest *request, HttpResponse *response, std::string uri, std::string thisHost) - { - //FreeRDP Params - string dtsize; - string rdphost; - string rdppcb; - string rdpuser; - int rdpport = 0; - string rdppass; - WsRdpParams params; - bool setCookie = true; - EmbeddedContext embeddedContext = CONTEXT_PLAIN; - - if(boost::starts_with(uri, "/wsgate?token=")) - { - // OpenStack console authentication - setCookie = false; - try - { - log::info << "Starting OpenStack token authentication" << endl; - - string tokenId = request->FormValues("token").m_sBody; - - nova_console_token_auth* token_auth = nova_console_token_auth_factory::get_instance(); - - nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, - m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId); - - log::info << "Host: " << info.host << " Port: " << info.port - << " Internal access path: " << info.internal_access_path - << endl; - - rdphost = info.host; - rdpport = info.port; - rdppcb = info.internal_access_path; - - rdpuser = m_sHyperVHostUsername; - rdppass = m_sHyperVHostPassword; - - embeddedContext = CONTEXT_EMBEDDED; - } - catch(exception& ex) - { - log::err << "OpenStack token authentication failed: " << ex.what() << endl; - return HTTPRESPONSECODE_400_BADREQUEST; - } - } - - params = - { - rdpport, - 1024, - 768, - m_bOverrideRdpPerf ? m_RdpOverrideParams.perf : nFormValue(request, "perf", 0), - m_bOverrideRdpFntlm ? m_RdpOverrideParams.fntlm : nFormValue(request, "fntlm", 0), - m_bOverrideRdpNotls ? m_RdpOverrideParams.notls : nFormValue(request, "notls", 0), - m_bOverrideRdpNonla ? m_RdpOverrideParams.nonla : nFormValue(request, "nonla", 0), - m_bOverrideRdpNowallp ? m_RdpOverrideParams.nowallp : nFormValue(request, "nowallp", 0), - m_bOverrideRdpNowdrag ? m_RdpOverrideParams.nowdrag : nFormValue(request, "nowdrag", 0), - m_bOverrideRdpNomani ? m_RdpOverrideParams.nomani : nFormValue(request, "nomani", 0), - m_bOverrideRdpNotheme ? m_RdpOverrideParams.notheme : nFormValue(request, "notheme", 0), - }; - - CheckForPredefined(rdphost, rdpuser, rdppass); - - if( !ConnectionIsAllowed(rdphost) ){ - LogInfo(request->RemoteAddress(), rdphost, "403 Denied by access rules"); - return HTTPRESPONSECODE_403_FORBIDDEN; - } - - if (!dtsize.empty()) { - try { - vector wh; - boost::split(wh, dtsize, is_any_of("x")); - if (wh.size() == 2) { - params.width = boost::lexical_cast(wh[0]); - params.height = boost::lexical_cast(wh[1]); - } - } catch (const exception &e) { - params.width = 1024; - params.height = 768; - } - } - response->SetBody("", 0); - - int wsocketCheck = CheckIfWSocketRequest(request, response, uri, thisHost); - if(wsocketCheck != 0) - { - //using a switch in case of new errors being thrown from the wsocket check - switch(wsocketCheck) - { - case 400: - { - return HTTPRESPONSECODE_400_BADREQUEST; - }; - case 426: - { - return HTTPRESPONSECODE_426_UPGRADE_REQUIRED; - }; - } - } - - string wskey(request->Headers("Sec-WebSocket-Key")); - SHA1 sha1; - uint32_t digest[5]; - sha1 << wskey.c_str() << ws_magic; - if (!sha1.Result(digest)) - { - LogInfo(request->RemoteAddress(), uri, "500 (Digest calculation failed)"); - return HTTPRESPONSECODE_500_INTERNALSERVERERROR; - } - // Handle endianess - for (int i = 0; i < 5; ++i) - { - digest[i] = htonl(digest[i]); - } - MyRawSocketHandler *sh = dynamic_cast(GetRawSocketHandler()); - if (!sh) - { - throw tracing::runtime_error("No raw socket handler available"); - } - response->EnableIdleTimeout(false); - response->EnableKeepAlive(true); - try - { - if (!sh->Prepare(request->Connection(), rdphost, rdppcb, rdpuser, rdppass, params, embeddedContext)) - { - LogInfo(request->RemoteAddress(), uri, "503 (RDP backend not available)"); - response->EnableIdleTimeout(true); - return HTTPRESPONSECODE_503_SERVICEUNAVAILABLE; - } - } - catch(...) - { - log::info << "caught exception!" << endl; - } - - response->RemoveHeader("Content-Type"); - response->RemoveHeader("Content-Length"); - response->RemoveHeader("Last-Modified"); - response->RemoveHeader("Cache-Control"); - - string wsproto(request->Headers("Sec-WebSocket-Protocol")); - if (0 < wsproto.length()) - { - response->SetHeader("Sec-WebSocket-Protocol", wsproto); - } - response->SetHeader("Upgrade", "websocket"); - response->SetHeader("Connection", "Upgrade"); - response->SetHeader("Sec-WebSocket-Accept", base64_encode(reinterpret_cast(digest), 20)); - - LogInfo(request->RemoteAddress(), uri, "101"); - return HTTPRESPONSECODE_101_SWITCHING_PROTOCOLS; - } - - // generates a page for each http request - ResponseCode HandleRequest(HttpRequest *request, HttpResponse *response) - { - //Connection Params - string uri = request->Uri(); - string thisHost = m_sHostname.empty() ? request->Headers("Host") : m_sHostname; - - //add new behaviour note: - //those requests that have the same beggining have to be placed with an if else condition - - if(request->Method() != REQUESTMETHOD_GET) - return HTTPRESPONSECODE_400_BADREQUEST; - - if (m_bRedirect && (!request->Secure())) - { - return HandleRedirectRequest(request, response, uri, thisHost); - } - - if(boost::starts_with(uri, "/robots.txt")) - { - return HandleRobotsRequest(request, response, uri, thisHost); - } - if(boost::starts_with(uri, "/cur/")) - { - return HandleCursorRequest(request, response, uri, thisHost); - } - - if(boost::starts_with(uri, "/wsgate")) - { - return HandleWsgateRequest(request, response, uri, thisHost); - } - - if(boost::starts_with(uri, "/connect?")) - { - //handle a direct connection via queryString here - return HTTPRESPONSECODE_200_OK; - } - return HandleHTTPRequest(request, response); - } - - ResponseCode HandleHTTPRequest(HttpRequest *request, HttpResponse *response, bool tokenAuth = false) - { - string uri(request->Uri()); - string thisHost(m_sHostname.empty() ? request->Headers("Host") : m_sHostname); - - // Regular (non WebSockets) request - bool bDynDebug = m_bDebug; - if (!bDynDebug) { - // Enable debugging by using a custom UserAgent header - if (iequals(request->Headers("X-WSGate-Debug"), "true")) { - bDynDebug = true; - } - } - if (0 != thisHost.compare(request->Headers("Host"))) { - LogInfo(request->RemoteAddress(), uri, "404 Not found"); - return HTTPRESPONSECODE_404_NOTFOUND; - } - - - path p(m_sDocumentRoot); - p /= uri; - if (ends_with(uri, "/")) { - p /= (bDynDebug ? "/index-debug.html" : "/index.html"); - } - p.normalize(); - bool externalRequest = false; - - if (!exists(p)) { - p = m_sDocumentRoot; - p /= "index.html"; - } - - if (!is_regular_file(p)) { - LogInfo(request->RemoteAddress(), uri, "403 Forbidden"); - log::warn << "Request from " << request->RemoteAddress() - << ": " << uri << " => 403 Forbidden" << endl; - - p = m_sDocumentRoot; - p /= "index.html"; - } - - // Handle If-modified-sice request header - time_t mtime = last_write_time(p); - if (notModified(request, response, mtime)) { - return HTTPRESPONSECODE_304_NOT_MODIFIED; - } - response->SetLastModified(mtime); - - string body; - StaticCache::iterator ci = m_StaticCache.find(p); - if ((m_StaticCache.end() != ci) && (ci->second.get<0>() == mtime)) { - body.assign(ci->second.get<1>()); - } else { - fs::ifstream f(p, ios::binary); - if (f.fail()) { - log::warn << "Request from " << request->RemoteAddress() - << ": " << uri << " => 404 (file '" << p << "' unreadable)" << endl; - return HTTPRESPONSECODE_404_NOTFOUND; - } - body.assign((istreambuf_iterator(f)), istreambuf_iterator()); - f.close(); - m_StaticCache[p] = cache_entry(mtime, body); - } - -#ifdef BOOST_FILESYSTEM_VERSION -# if (BOOST_FILESYSTEM_VERSION >= 3) - string basename(p.filename().generic_string()); -# else - string basename(p.filename()); -# endif -#else - // Not defined at all: old API - string basename(p.filename()); -#endif - - MimeType mt = simpleMime(to_lower_copy(basename)); - if (HTML == mt) { - ostringstream oss; - - oss << (request->Secure() ? "wss://" : "ws://") << thisHost << "/wsgate"; - - replace_all(body, "%WSURI%", oss.str()); - replace_all(body, "%JSDEBUG%", (bDynDebug ? "-debug" : "")); - string tmp; - if(externalRequest) - { - string dtsize(request->FormValues("dtsize").m_sBody); - string port(request->FormValues("port").m_sBody); - - replace_all(body, "%COOKIE_LASTUSER%", request->FormValues("user").m_sBody); - replace_all(body, "%COOKIE_LASTPASS%", base64_decode(request->FormValues("pass").m_sBody)); // Passw0rd - replace_all(body, "%COOKIE_LASTHOST%", request->FormValues("host").m_sBody); - replace_all(body, "%COOKIE_LASTPCB%", request->FormValues("pcb").m_sBody); - replace_all(body, "var externalConnection = false;", "var externalConnection = true;"); - } - else - { - tmp.assign(m_bOverrideRdpUser ? "" : request->Cookies("lastuser")); - replace_all(body, "%COOKIE_LASTUSER%", tmp); - tmp.assign(m_bOverrideRdpUser ? "disabled=\"disabled\"" : ""); - replace_all(body, "%DISABLED_USER%", tmp); - tmp.assign(m_bOverrideRdpPass ? "SomthingUseless" : base64_decode(request->Cookies("lastpass"))); - replace_all(body, "%COOKIE_LASTPASS%", tmp); - tmp.assign(m_bOverrideRdpPass ? "disabled=\"disabled\"" : ""); - replace_all(body, "%DISABLED_PASS%", tmp); - - tmp.assign(m_bOverrideRdpHost ? "" : request->Cookies("lasthost")); - replace_all(body, "%COOKIE_LASTHOST%", tmp); - tmp.assign(m_bOverrideRdpHost ? "disabled=\"disabled\"" : ""); - replace_all(body, "%DISABLED_HOST%", tmp); - - tmp.assign(request->Cookies("lastpcb")); - replace_all(body, "%COOKIE_LASTPCB%", tmp); - tmp.assign(""); - replace_all(body, "%DISABLED_PCB%", tmp); - } - - tmp.assign(VERSION).append(".").append(GITREV); - replace_all(body, "%VERSION%", tmp); - - //The new Port Selector - if(m_bOverrideRdpPort) { - replace_all(body, "%DISABLED_PORT%", "disabled=\"disabled\""); - } else { - replace_all(body, "%DISABLED_PORT%", ""); - } - - tmp.assign(m_bOverrideRdpPort ? boost::lexical_cast(m_RdpOverrideParams.port) : "3389"); - replace_all(body, "%DEFAULT_PORT%", tmp); - - //The Desktop Resolution - if (m_bOverrideRdpPerf) { - replace_all(body, "%DISABLED_PERF%", "disabled=\"disabled\""); - replace_all(body, "%SELECTED_PERF0%", (0 == m_RdpOverrideParams.perf) ? "selected" : ""); - replace_all(body, "%SELECTED_PERF1%", (1 == m_RdpOverrideParams.perf) ? "selected" : ""); - replace_all(body, "%SELECTED_PERF2%", (2 == m_RdpOverrideParams.perf) ? "selected" : ""); - } else { - replace_all(body, "%DISABLED_PERF%", ""); - replace_all(body, "%SELECTED_PERF0%", ""); - replace_all(body, "%SELECTED_PERF1%", ""); - replace_all(body, "%SELECTED_PERF2%", ""); - } - - - if (m_bOverrideRdpFntlm) { - replace_all(body, "%DISABLED_FNTLM%", "disabled=\"disabled\""); - replace_all(body, "%SELECTED_FNTLM0%", (0 == m_RdpOverrideParams.fntlm) ? "selected" : ""); - replace_all(body, "%SELECTED_FNTLM1%", (1 == m_RdpOverrideParams.fntlm) ? "selected" : ""); - replace_all(body, "%SELECTED_FNTLM2%", (2 == m_RdpOverrideParams.fntlm) ? "selected" : ""); - } else { - replace_all(body, "%DISABLED_FNTLM%", ""); - replace_all(body, "%SELECTED_FNTLM0%", ""); - replace_all(body, "%SELECTED_FNTLM1%", ""); - replace_all(body, "%SELECTED_FNTLM2%", ""); - } - if (m_bOverrideRdpNowallp) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowallp) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NOWALLP%", tmp); - if (m_bOverrideRdpNowdrag) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowdrag) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NOWDRAG%", tmp); - if (m_bOverrideRdpNomani) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nomani) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NOMANI%", tmp); - if (m_bOverrideRdpNotheme) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notheme) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NOTHEME%", tmp); - if (m_bOverrideRdpNotls) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notls) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NOTLS%", tmp); - if (m_bOverrideRdpNonla) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nonla) ? " checked=\"checked\"" : ""); - } else { - tmp.assign(""); - } - replace_all(body, "%CHECKED_NONLA%", tmp); - } - switch (mt) { - case TEXT: - response->SetHeader("Content-Type", "text/plain"); - response->SetHeader("Cache-Control", "no-cache, private"); - break; - case HTML: - response->SetHeader("Content-Type", "text/html"); - response->SetHeader("Cache-Control", "no-cache, private"); - break; - case PNG: - response->SetHeader("Content-Type", "image/png"); - break; - case ICO: - response->SetHeader("Content-Type", "image/x-icon"); - break; - case JAVASCRIPT: - response->SetHeader("Content-Type", "text/javascript"); - break; - case JSON: - response->SetHeader("Content-Type", "application/json"); - break; - case CSS: - response->SetHeader("Content-Type", "text/css"); - break; - case OGG: - response->SetHeader("Content-Type", "audio/ogg"); - break; - case CUR: - response->SetHeader("Content-Type", "image/cur"); - break; - case BINARY: - response->SetHeader("Content-Type", "application/octet-stream"); - break; - } - response->SetBody(body.data(), body.length()); - - LogInfo(request->RemoteAddress(), uri, "200 OK"); - return HTTPRESPONSECODE_200_OK; - } - - boost::property_tree::ptree GetConfig() { - return this->m_ptIniConfig; - } - - const string & GetConfigFile() { - return m_sConfigFile; - } - - bool GetEnableCore() { - return m_bEnableCore; - } - - bool SetConfigFile(const string &name) { - if (name.empty()) { -#ifdef _WIN32 - wsgate::log::err << "Config filename is empty." << endl; -#endif - cerr << "Config filename is empty." << endl; - return false; - } - m_sConfigFile = name; - return true; - } - - bool ReadConfig(wsgate::log *logger = NULL) { - // config file options - po::options_description cfg(""); - cfg.add_options() - ("global.daemon", po::value(), "enable/disable daemon mode") - ("global.pidfile", po::value(), "path of PID file in daemon mode") - ("global.debug", po::value(), "enable/disable debugging") - ("global.enablecore", po::value(), "enable/disable coredumps") - ("global.hostname", po::value(), "specify host name") - ("global.port", po::value(), "specify listening port") - ("global.bindaddr", po::value(), "specify bind address") - ("global.redirect", po::value(), "Flag: Always redirect non-SSL to SSL") - ("global.logmask", po::value(), "specify syslog mask") - ("global.logfacility", po::value(), "specify syslog facility") - ("ssl.port", po::value(), "specify listening port for SSL") - ("ssl.bindaddr", po::value(), "specify bind address for SSL") - ("ssl.certfile", po::value(), "specify certificate file") - ("ssl.certpass", po::value(), "specify certificate passphrase") - ("threading.mode", po::value(), "specify threading mode") - ("threading.poolsize", po::value(), "specify threading pool size") - ("http.maxrequestsize", po::value(), "specify maximum http request size") - ("http.documentroot", po::value(), "specify http document root") - ("acl.allow", po::value>()->multitoken(), "Allowed destination hosts or nets") - ("acl.deny", po::value>()->multitoken(), "Denied destination hosts or nets") - ("acl.order", po::value(), "Order (deny,allow or allow,deny)") - ("rdpoverride.host", po::value(), "Predefined RDP destination host") - ("rdpoverride.port", po::value(), "Predefined RDP port") - ("rdpoverride.user", po::value(), "Predefined RDP user") - ("rdpoverride.pass", po::value(), "Predefined RDP password") - ("rdpoverride.performance", po::value(), "Predefined RDP performance") - ("rdpoverride.nowallpaper", po::value(), "Predefined RDP flag: No wallpaper") - ("rdpoverride.nofullwindowdrag", po::value(), "Predefined RDP flag: No full window drag") - ("rdpoverride.nomenuanimation", po::value(), "Predefined RDP flag: No full menu animation") - ("rdpoverride.notheming", po::value(), "Predefined RDP flag: No theming") - ("rdpoverride.notls", po::value(), "Predefined RDP flag: Disable TLS") - ("rdpoverride.nonla", po::value(), "Predefined RDP flag: Disable NLA") - ("rdpoverride.forcentlm", po::value(), "Predefined RDP flag: Force NTLM") - ("rdpoverride.size", po::value(), "Predefined RDP desktop size") - ("openstack.authurl", po::value(), "OpenStack authentication URL") - ("openstack.username", po::value(), "OpenStack username") - ("openstack.password", po::value(), "OpenStack password") - ("openstack.tenantname", po::value(), "OpenStack tenant name") - ("hyperv.hostusername", po::value(), "Hyper-V username") - ("hyperv.hostpassword", po::value(), "Hyper-V user's password") - ; - - try { - boost::property_tree::ini_parser::read_ini(m_sConfigFile, this->m_ptIniConfig); - boost::property_tree::ptree pt = this->m_ptIniConfig; - - try { - // Examine values from config file - m_bDaemon = str2bool(pt.get("global.daemon","false")); - m_bDebug = str2bool(pt.get("global.debug","false")); - m_bEnableCore = str2bool(pt.get("global.enablecore","false")); - if (pt.get_optional("global.logmask")) { - if (NULL != logger) { - logger->setmaskByName(to_upper_copy(pt.get("global.logmask"))); - } - } - if (pt.get_optional("global.logfacility")) { - if (NULL != logger) { - logger->setfacilityByName(to_upper_copy(pt.get("global.logfacility"))); - } - } - if (!pt.get_optional("global.port") && !pt.get_optional("ssl.port")) { - throw tracing::invalid_argument("No listening ports defined."); - } - - if (!pt.get_optional("http.documentroot")) { - throw tracing::invalid_argument("No documentroot defined."); - } - m_sDocumentRoot.assign(pt.get("http.documentroot")); - if (m_sDocumentRoot.empty()) { - throw tracing::invalid_argument("documentroot is empty."); - } - - m_bRedirect = str2bool(pt.get("global.redirect","false")); - - if (pt.get_optional("acl.order")) { - setAclOrder(pt.get("acl.order")); - } - if (pt.get_child_optional("acl.allow")) { - setHostList(as_vector(pt, "acl.allow"), m_allowedHosts); - } - if (pt.get_child_optional("acl.deny")) { - setHostList(as_vector(pt, "acl.deny"), m_deniedHosts); - } - - if (pt.get_optional("rdpoverride.host")) { - m_sRdpOverrideHost.assign(pt.get("rdpoverride.host")); - m_bOverrideRdpHost = true; - } else { - m_bOverrideRdpHost = false; - } - if (pt.get_optional("rdpoverride.user")) { - m_sRdpOverrideUser.assign(pt.get("rdpoverride.user")); - m_bOverrideRdpUser = true; - } else { - m_bOverrideRdpUser = false; - } - if (pt.get_optional("rdpoverride.pass")) { - m_sRdpOverridePass.assign(pt.get("rdpoverride.pass")); - m_bOverrideRdpPass = true; - } else { - m_bOverrideRdpPass = false; - } - - if (pt.get_optional("rdpoverride.port")) { - int n = pt.get("rdpoverride.port"); - if ((0 > n) || (2 < n)) { - throw tracing::invalid_argument("Invalid port value."); - } - m_RdpOverrideParams.port = n; - m_bOverrideRdpPort = true; - } else { - m_bOverrideRdpPort = false; - } - - if (pt.get_optional("rdpoverride.performance")) { - int n = pt.get("rdpoverride.performance"); - if ((0 > n) || (2 < n)) { - throw tracing::invalid_argument("Invalid performance value."); - } - m_RdpOverrideParams.perf = n; - m_bOverrideRdpPerf = true; - } else { - m_bOverrideRdpPerf = false; - } - if (pt.get_optional("rdpoverride.forcentlm")) { - int n = pt.get("rdpoverride.forcentlm"); - if ((0 > n) || (2 < n)) { - throw tracing::invalid_argument("Invalid forcentlm value."); - } - m_RdpOverrideParams.fntlm = n; - m_bOverrideRdpFntlm = true; - } else { - m_bOverrideRdpFntlm = false; - } - if (pt.get_optional("rdpoverride.nowallpaper")) { - m_RdpOverrideParams.nowallp = str2bint(pt.get("rdpoverride.nowallpaper")); - m_bOverrideRdpNowallp = true; - } else { - m_bOverrideRdpNowallp = false; - } - if (pt.get_optional("rdpoverride.nofullwindowdrag")) { - m_RdpOverrideParams.nowdrag = str2bint(pt.get("rdpoverride.nofullwindowdrag")); - m_bOverrideRdpNowdrag = true; - } else { - m_bOverrideRdpNowdrag = false; - } - if (pt.get_optional("rdpoverride.nomenuanimation")) { - m_RdpOverrideParams.nomani = str2bint(pt.get("rdpoverride.nomenuanimation")); - m_bOverrideRdpNomani = true; - } else { - m_bOverrideRdpNomani = false; - } - if (pt.get_optional("rdpoverride.notheming")) { - m_RdpOverrideParams.notheme = str2bint(pt.get("rdpoverride.notheming")); - m_bOverrideRdpNotheme = true; - } else { - m_bOverrideRdpNotheme = false; - } - if (pt.get_optional("rdpoverride.notls")) { - m_RdpOverrideParams.notls = str2bint(pt.get("rdpoverride.notls")); - m_bOverrideRdpNotls = true; - } else { - m_bOverrideRdpNotls = false; - } - if (pt.get_optional("rdpoverride.nonla")) { - m_RdpOverrideParams.nonla = str2bint(pt.get("rdpoverride.nonla")); - m_bOverrideRdpNonla = true; - } else { - m_bOverrideRdpNonla = false; - } - if (pt.get_optional("global.hostname")) { - m_sHostname.assign(pt.get("global.hostname")); - } else { - m_sHostname.clear(); - } - if (pt.get_optional("openstack.authurl")) { - m_sOpenStackAuthUrl.assign(pt.get("openstack.authurl")); - } else { - m_sOpenStackAuthUrl.clear(); - } - if (pt.get_optional("openstack.username")) { - m_sOpenStackUsername.assign(pt.get("openstack.username")); - } else { - m_sOpenStackUsername.clear(); - } - if (pt.get_optional("openstack.password")) { - m_sOpenStackPassword.assign(pt.get("openstack.password")); - } else { - m_sOpenStackPassword.clear(); - } - if (pt.get_optional("openstack.tenantname")) { - m_sOpenStackTenantName.assign(pt.get("openstack.tenantname")); - } else { - m_sOpenStackTenantName.clear(); - } - if (pt.get_optional("hyperv.hostusername")) { - m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); - } else { - m_sHyperVHostUsername.clear(); - } - if (pt.get_optional("hyperv.hostpassword")) { - m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); - } else { - m_sHyperVHostPassword.clear(); - } - } catch (const tracing::invalid_argument & e) { - cerr << e.what() << endl; - wsgate::log::err << e.what() << endl; - wsgate::log::err << e.where() << endl; - return false; - } - - } catch (const boost::property_tree::ini_parser_error &e) { - cerr << e.what() << endl; - return false; - } - return true; - } - - private: - - template - std::vector as_vector(boost::property_tree::ptree const& pt, boost::property_tree::ptree::key_type const& key){ - std::vector r; - for (auto& item : pt.get_child(key)) - r.push_back(item.second.get_value()); - return r; - } - - bool notModified(HttpRequest *request, HttpResponse *response, time_t mtime) - { - string ifms(request->Headers("if-modified-since")); - if (!ifms.empty()) { - pt::ptime file_time(pt::from_time_t(mtime)); - pt::ptime req_time; - istringstream iss(ifms); - iss.imbue(locale(locale::classic(), - new pt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"))); - iss >> req_time; - if (file_time <= req_time) { - response->RemoveHeader("Content-Type"); - response->RemoveHeader("Content-Length"); - response->RemoveHeader("Last-Modified"); - response->RemoveHeader("Cache-Control"); - log::info << "Request from " << request->RemoteAddress() - << ": " << request->Uri() << " => 304 Not modified" << endl; - return true; - } - } - return false; - } - - int str2bint(const string &s) { - string v(s); - trim(v); - if (!v.empty()) { - if (iequals(v, "true")) { - return 1; - } - if (iequals(v, "yes")) { - return 1; - } - if (iequals(v, "on")) { - return 1; - } - if (iequals(v, "1")) { - return 1; - } - if (iequals(v, "false")) { - return 0; - } - if (iequals(v, "no")) { - return 0; - } - if (iequals(v, "off")) { - return 0; - } - if (iequals(v, "0")) { - return 0; - } - } - throw tracing::invalid_argument("Invalid boolean value"); - } - - bool str2bool(const string &s) { - return (1 == str2bint(s)); - } - - void wc2pat(string &wildcards) { - boost::replace_all(wildcards, "\\", "\\\\"); - boost::replace_all(wildcards, "^", "\\^"); - boost::replace_all(wildcards, ".", "\\."); - boost::replace_all(wildcards, "$", "\\$"); - boost::replace_all(wildcards, "|", "\\|"); - boost::replace_all(wildcards, "(", "\\("); - boost::replace_all(wildcards, ")", "\\)"); - boost::replace_all(wildcards, "[", "\\["); - boost::replace_all(wildcards, "]", "\\]"); - boost::replace_all(wildcards, "*", "\\*"); - boost::replace_all(wildcards, "+", "\\+"); - boost::replace_all(wildcards, "?", "\\?"); - boost::replace_all(wildcards, "/", "\\/"); - boost::replace_all(wildcards, "\\?", "."); - boost::replace_all(wildcards, "\\*", ".*"); - wildcards.insert(0, "^").append("$"); - } - - void setHostList(const vector &hosts, vector &hostlist) { - vector tmp(hosts); - vector::iterator i; - hostlist.clear(); - for (i = tmp.begin(); i != tmp.end(); ++i) { - wc2pat(*i); - boost::regex re(*i, boost::regex::icase); - hostlist.push_back(re); - } - } - - void setAclOrder(const string &order) { - vector parts; - boost::split(parts, order, is_any_of(",")); - if (2 == parts.size()) { - trim(parts[0]); - trim(parts[1]); - if (iequals(parts[0],"deny") && iequals(parts[1],"allow")) { - m_bOrderDenyAllow = true; - return; - } - if (iequals(parts[0],"allow") && iequals(parts[1],"deny")) { - m_bOrderDenyAllow = false; - return; - } - } - throw tracing::invalid_argument("Invalid acl order value."); - } - - public: - bool GetDaemon() { - return m_bDaemon; - } - - void SetPidFile(const string &name) { - m_sPidFile = name; - } - - void RegisterRdpSession(rdp_ptr rdp) { - ostringstream oss; - oss << hex << rdp.get(); - m_SessionMap[oss.str()] = rdp; - } - - void UnregisterRdpSession(rdp_ptr rdp) { - ostringstream oss; - oss << hex << rdp.get(); - m_SessionMap.erase(oss.str()); - } - - private: - string m_sHostname; - string m_sDocumentRoot; - string m_sPidFile; - bool m_bDebug; - bool m_bEnableCore; - SessionMap m_SessionMap; - vector m_allowedHosts; - vector m_deniedHosts; - bool m_bOrderDenyAllow; - bool m_bOverrideRdpHost; - bool m_bOverrideRdpPort; - bool m_bOverrideRdpUser; - bool m_bOverrideRdpPass; - bool m_bOverrideRdpPerf; - bool m_bOverrideRdpNowallp; - bool m_bOverrideRdpNowdrag; - bool m_bOverrideRdpNomani; - bool m_bOverrideRdpNotheme; - bool m_bOverrideRdpNotls; - bool m_bOverrideRdpNonla; - bool m_bOverrideRdpFntlm; - string m_sRdpOverrideHost; - string m_sRdpOverrideUser; - string m_sRdpOverridePass; - WsRdpParams m_RdpOverrideParams; - string m_sConfigFile; - boost::property_tree::ptree m_ptIniConfig; - bool m_bDaemon; - bool m_bRedirect; - StaticCache m_StaticCache; - string m_sOpenStackAuthUrl; - string m_sOpenStackUsername; - string m_sOpenStackPassword; - string m_sOpenStackTenantName; - string m_sHyperVHostUsername; - string m_sHyperVHostPassword; - }; - #ifndef _WIN32 // Bind helper is not needed on win32, because win32 does not // have a concept of privileged ports. From 3f0c9fc29c20569088ee8d40786f8b3abb24bea1 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Sat, 5 Sep 2015 00:11:36 +0300 Subject: [PATCH 045/130] Moved globally used functions inside wsgate.hpp --- wsgate/wsgate.hpp | 43 +++++++++++++ wsgate/wsgate_main.cpp | 138 +---------------------------------------- 2 files changed, 45 insertions(+), 136 deletions(-) diff --git a/wsgate/wsgate.hpp b/wsgate/wsgate.hpp index 4a1c8386..77cb8c61 100644 --- a/wsgate/wsgate.hpp +++ b/wsgate/wsgate.hpp @@ -21,12 +21,55 @@ #define _WSGATE_H_ #include "logging.hpp" +#include +using namespace std; namespace wsgate { /// Our global logging instance typedef wsgate::logger log; + static const char * const ws_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + //disable two connections to the same host + std::map activeConnections; + + int nFormValue(HttpRequest *request, const string & name, int defval) { + string tmp(request->FormValues(name).m_sBody); + int ret = defval; + if (!tmp.empty()) { + try { + ret = boost::lexical_cast(tmp); + } catch (const boost::bad_lexical_cast & e) { ret = defval; } + } + return ret; + } + + void SplitUserDomain(const string& fullUsername, string& username, string& domain) + { + std::vector strs; + boost::split(strs, fullUsername, boost::is_any_of("\\")); + if (strs.size() > 1) + { + username = strs[1]; + domain = strs[0]; + } + else + { + strs.clear(); + boost::split(strs, fullUsername, boost::is_any_of("@")); + if (strs.size() > 1) + { + username = strs[0]; + domain = strs[1]; + } + else + { + username = fullUsername; + domain = ""; + } + } + } } #endif diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 1903d241..8fe27131 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -17,145 +17,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_WINSOCK2_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SIGNAL_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_FCNTL_H -# include -#endif -#ifdef HAVE_UNISTD_H - #include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_WAIT_H -# include -#endif -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#include "common.hpp" -#include "btexception.hpp" -#include "base64.hpp" -#include "sha1.hpp" -#include "logging.hpp" -#include "wsendpoint.hpp" +#include "wsgateEHS.hpp" #include "wsgate.hpp" -#include "myrawsocket.hpp" -#include "nova_token_auth.hpp" - -#ifdef _WIN32 -#include -# define WIN32_LEAN_AND_MEAN -# include -# include -# include "NTService.hpp" -#endif - -using namespace std; -using boost::algorithm::iequals; -using boost::algorithm::to_lower_copy; -using boost::algorithm::ends_with; -using boost::algorithm::replace_all; -using boost::algorithm::to_upper_copy; -using boost::algorithm::trim_right_copy_if; -using boost::algorithm::trim; -using boost::algorithm::is_any_of; -using boost::algorithm::split; -namespace po = boost::program_options; -namespace fs = boost::filesystem; -namespace pt = boost::posix_time; -using boost::filesystem::path; -using namespace utility::conversions; namespace wsgate { - static const char * const ws_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - //disable two connections to the same host - std::map activeConnections; - - int nFormValue(HttpRequest *request, const string & name, int defval) { - string tmp(request->FormValues(name).m_sBody); - int ret = defval; - if (!tmp.empty()) { - try { - ret = boost::lexical_cast(tmp); - } catch (const boost::bad_lexical_cast & e) { ret = defval; } - } - return ret; - } - - void SplitUserDomain(const string& fullUsername, string& username, string& domain) - { - std::vector strs; - boost::split(strs, fullUsername, boost::is_any_of("\\")); - if (strs.size() > 1) - { - username = strs[1]; - domain = strs[0]; - } - else - { - strs.clear(); - boost::split(strs, fullUsername, boost::is_any_of("@")); - if (strs.size() > 1) - { - username = strs[0]; - domain = strs[1]; - } - else - { - username = fullUsername; - domain = ""; - } - } - } + #ifndef _WIN32 // Bind helper is not needed on win32, because win32 does not From 13e65185e7eaaea20324c77217b8108c36d89b13 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 20:39:33 +0300 Subject: [PATCH 046/130] Separated MyWsHandler from the main --- wsgate/myWsHandler.cpp | 55 +++++++++++++++++++++++++++++++++++++ wsgate/myWsHandler.hpp | 29 ++++++++++++++++++++ wsgate/wsgate_main.cpp | 61 ------------------------------------------ 3 files changed, 84 insertions(+), 61 deletions(-) create mode 100644 wsgate/myWsHandler.cpp create mode 100644 wsgate/myWsHandler.hpp diff --git a/wsgate/myWsHandler.cpp b/wsgate/myWsHandler.cpp new file mode 100644 index 00000000..d46d39d6 --- /dev/null +++ b/wsgate/myWsHandler.cpp @@ -0,0 +1,55 @@ +#include "myWsHandler.hpp" + +namespace wsgate{ + MyWsHandler::MyWsHandler(EHSConnection *econn, EHS *ehs, MyRawSocketHandler *rsh) + : m_econn(econn) + , m_ehs(ehs) + , m_rsh(rsh){ + } + + void MyWsHandler::on_message(std::string hdr, std::string data){ + if (1 == (hdr[0] & 0x0F)) { + // A text message + if (':' == data[1]) { + switch (data[0]) { + case 'D': + log::debug << "JS: " << data.substr(2) << endl; + break; + case 'I': + log::info << "JS: " << data.substr(2) << endl; + break; + case 'W': + log::warn << "JS: " << data.substr(2) << endl; + break; + case 'E': + log::err << "JS: " << data.substr(2) << endl; + break; + } + } + return; + } + // binary message; + m_rsh->OnMessage(m_econn, data); + } + + void MyWsHandler::on_close(){ + log::debug << "GOT Close" << endl; + ehs_autoptr r(new GenericResponse(0, m_econn)); + m_ehs->AddResponse(ehs_move(r)); + } + + bool MyWsHandler::on_ping(const std::string & data){ + log::debug << "GOT Ping: '" << data << "'" << endl; + return true; + } + + void MyWsHandler::on_pong(const std::string & data){ + log::debug << "GOT Pong: '" << data << "'" << endl; + } + + void MyWsHandler::do_response(const std::string & data){ + ehs_autoptr r(new GenericResponse(0, m_econn)); + r->SetBody(data.data(), data.length()); + m_ehs->AddResponse(ehs_move(r)); + } +} \ No newline at end of file diff --git a/wsgate/myWsHandler.hpp b/wsgate/myWsHandler.hpp new file mode 100644 index 00000000..44aa108d --- /dev/null +++ b/wsgate/myWsHandler.hpp @@ -0,0 +1,29 @@ +#ifndef _MY_WS_HANDLER_ +#define _MY_WS_HANDLER_ + +#include "wshandler.hpp" +#include "myrawsocket.hpp" +#include + +namespace wsgate{ + class MyWsHandler : public wspp::wshandler + { + public: + MyWsHandler(EHSConnection *econn, EHS *ehs, MyRawSocketHandler *rsh); + virtual void on_message(std::string hdr, std::string data); + virtual void on_close(); + virtual bool on_ping(const std::string & data); + virtual void on_pong(const std::string & data); + virtual void do_response(const std::string & data); + private: + // Non-copyable + MyWsHandler(const MyWsHandler&); + MyWsHandler& operator=(const MyWsHandler&); + + EHSConnection *m_econn; + EHS *m_ehs; + MyRawSocketHandler *m_rsh; + }; +} + +#endif //_MY_WS_HANDLER_ \ No newline at end of file diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 8fe27131..4f12b478 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -66,67 +66,6 @@ namespace wsgate { }; #endif - class MyWsHandler : public wspp::wshandler - { - public: - MyWsHandler(EHSConnection *econn, EHS *ehs, MyRawSocketHandler *rsh) - : m_econn(econn) - , m_ehs(ehs) - , m_rsh(rsh) - {} - - virtual void on_message(std::string hdr, std::string data) { - if (1 == (hdr[0] & 0x0F)) { - // A text message - if (':' == data[1]) { - switch (data[0]) { - case 'D': - log::debug << "JS: " << data.substr(2) << endl; - break; - case 'I': - log::info << "JS: " << data.substr(2) << endl; - break; - case 'W': - log::warn << "JS: " << data.substr(2) << endl; - break; - case 'E': - log::err << "JS: " << data.substr(2) << endl; - break; - } - } - return; - } - // binary message; - m_rsh->OnMessage(m_econn, data); - } - virtual void on_close() { - log::debug << "GOT Close" << endl; - ehs_autoptr r(new GenericResponse(0, m_econn)); - m_ehs->AddResponse(ehs_move(r)); - } - virtual bool on_ping(const std::string & data) { - log::debug << "GOT Ping: '" << data << "'" << endl; - return true; - } - virtual void on_pong(const std::string & data) { - log::debug << "GOT Pong: '" << data << "'" << endl; - } - virtual void do_response(const std::string & data) { - ehs_autoptr r(new GenericResponse(0, m_econn)); - r->SetBody(data.data(), data.length()); - m_ehs->AddResponse(ehs_move(r)); - } - - private: - // Non-copyable - MyWsHandler(const MyWsHandler&); - MyWsHandler& operator=(const MyWsHandler&); - - EHSConnection *m_econn; - EHS *m_ehs; - MyRawSocketHandler *m_rsh; - }; - MyRawSocketHandler::MyRawSocketHandler(WsGate *parent) : m_parent(parent) , m_cmap(conn_map()) From 1ec6193b97221589a4d49c0d053a2c4239e6f36c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 20:57:30 +0300 Subject: [PATCH 047/130] Fixed compilation errors --- wsgate/myWsHandler.hpp | 2 +- wsgate/wsgate.hpp | 8 +++++++- wsgate/wsgateEHS.cpp | 6 +++--- wsgate/wsgate_main.cpp | 4 +++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/wsgate/myWsHandler.hpp b/wsgate/myWsHandler.hpp index 44aa108d..4df8a6a2 100644 --- a/wsgate/myWsHandler.hpp +++ b/wsgate/myWsHandler.hpp @@ -3,7 +3,7 @@ #include "wshandler.hpp" #include "myrawsocket.hpp" -#include +#include namespace wsgate{ class MyWsHandler : public wspp::wshandler diff --git a/wsgate/wsgate.hpp b/wsgate/wsgate.hpp index 77cb8c61..e140350f 100644 --- a/wsgate/wsgate.hpp +++ b/wsgate/wsgate.hpp @@ -20,8 +20,14 @@ #ifndef _WSGATE_H_ #define _WSGATE_H_ -#include "logging.hpp" #include +#include +#include +#include +#include +#include +#include "logging.hpp" + using namespace std; namespace wsgate { diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index e60da46e..4df12b86 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -24,7 +24,7 @@ namespace wsgate{ return BINARY; } - WsGate::WsGate(EHS *parent = NULL, std::string registerpath = "") + WsGate::WsGate(EHS *parent, std::string registerpath) : EHS(parent, registerpath) , m_sHostname() , m_sDocumentRoot() @@ -458,7 +458,7 @@ namespace wsgate{ return HandleHTTPRequest(request, response); } - ResponseCode WsGate::HandleHTTPRequest(HttpRequest *request, HttpResponse *response, bool tokenAuth = false) + ResponseCode WsGate::HandleHTTPRequest(HttpRequest *request, HttpResponse *response, bool tokenAuth) { string uri(request->Uri()); string thisHost(m_sHostname.empty() ? request->Headers("Host") : m_sHostname); @@ -713,7 +713,7 @@ namespace wsgate{ return true; } - bool WsGate::ReadConfig(wsgate::log *logger = NULL) { + bool WsGate::ReadConfig(wsgate::log *logger) { // config file options po::options_description cfg(""); cfg.add_options() diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 4f12b478..b7e7476c 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -17,8 +17,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "wsgateEHS.hpp" + #include "wsgate.hpp" +#include "wsgateEHS.hpp" +#include "myWsHandler.hpp" namespace wsgate { From 9232f8f01412964c64863aa69fc8cb954a688051 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 21:13:43 +0300 Subject: [PATCH 048/130] Separated WsGateService from main --- wsgate/wsGateService.cpp | 137 +++++++++++++++++++++++++++++++++++++++ wsgate/wsGateService.hpp | 21 ++++++ wsgate/wsgate_main.cpp | 124 +---------------------------------- 3 files changed, 159 insertions(+), 123 deletions(-) create mode 100644 wsgate/wsGateService.cpp create mode 100644 wsgate/wsGateService.hpp diff --git a/wsgate/wsGateService.cpp b/wsgate/wsGateService.cpp new file mode 100644 index 00000000..cc89a001 --- /dev/null +++ b/wsgate/wsGateService.cpp @@ -0,0 +1,137 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include "wsGateService.hpp" +#include "btexception.hpp" +#include +#ifdef _WIN32 +#include +#endif + +using namespace std; +using boost::filesystem::path; + +extern bool g_signaled = false; +#ifdef _WIN32 +extern bool g_service_background = true; +extern int _service_main (int argc, char **argv); +#endif + +namespace wsgate{ + + WsGateService::WsGateService() + :NTService("FreeRDP-WebConnect", "FreeRDP WebConnect") + { + m_dwServiceStartupType = SERVICE_AUTO_START; + m_sDescription.assign("RDP Web access gateway"); + AddDependency("Eventlog"); + } + + bool WsGateService::OnServiceStop(){ + g_signaled = true; + return true; + } + + bool WsGateService::OnServiceShutdown(){ + g_signaled = true; + return true; + } + + void WsGateService::RunService(){ + g_signaled = false; + // On Windows, always set out working dir to ../ relatively seen from + // the binary's path. + path p(m_sModulePath); + string wdir(p.branch_path().branch_path().string()); + chdir(wdir.c_str()); + g_signaled = false; + char *argv[] = { + strdup("wsgate"), + strdup("-c"), + strdup("etc/wsgate.ini"), + NULL + }; + int r = _service_main(3, argv); + if (0 != r) { + m_ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + m_ServiceStatus.dwServiceSpecificExitCode = r; + } + free(argv[0]); + free(argv[1]); + free(argv[2]); + } + + bool WsGateService::ParseSpecialArgs(int argc, char **argv){ + if (argc < 2) { + return false; + } + bool installed = false; + try { + installed = IsServiceInstalled(); + } catch (const tracing::runtime_error &e) { + cerr << e.what() << endl; + return true; + } + if (0 == strcmp(argv[1], "--query")) { + // Report version of installed service + cout << "The service is " << (installed ? "currently" : "not") + << " installed." << endl; + return true; + } + if (0 == strcmp(argv[1], "--start")) { + // Start the service + try { + Start(); + } catch (const tracing::runtime_error &e) { + cerr << "Failed to start " << m_sServiceName << endl; + cerr << e.what() << endl; + } + return true; + } + if (0 == strcmp(argv[1], "--stop")) { + // Start the service + try { + Stop(); + } catch (const tracing::runtime_error &e) { + cerr << "Failed to stop " << m_sServiceName << endl; + cerr << e.what() << endl; + } + return true; + } + if (0 == strcmp(argv[1], "--install")) { + // Install the service + if (installed) { + cout << m_sServiceName << " is already installed." << endl; + } else { + try { + InstallService(); + cout << m_sServiceName << " installed." << endl; + } catch (const tracing::runtime_error &e) { + cerr << "Failed to install " << m_sServiceName << endl; + cerr << e.what() << endl; + } + } + return true; + } + if (0 == strcmp(argv[1], "--remove")) { + // Remove the service + if (!installed) { + cout << m_sServiceName << " is not installed." << endl; + } else { + try { + UninstallService(); + cout << m_sServiceName << " removed." << endl; + } catch (const tracing::runtime_error &e) { + cerr << "Failed to remove " << m_sServiceName << endl; + cerr << e.what() << endl; + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/wsgate/wsGateService.hpp b/wsgate/wsGateService.hpp new file mode 100644 index 00000000..be2d24c1 --- /dev/null +++ b/wsgate/wsGateService.hpp @@ -0,0 +1,21 @@ +#ifndef _WS_GATE_SERVICE_ +#define _WS_GATE_SERVICE_ + +#include "NTService.hpp" + +namespace wsgate{ + + class WsGateService : public NTService { + + public: + WsGateService(); + bool ParseSpecialArgs(int argc, char **argv); + + protected: + bool OnServiceStop(); + bool OnServiceShutdown(); + void RunService(); + }; +} + +#endif //_WS_GATE_SERVICE_ \ No newline at end of file diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index b7e7476c..414a2044 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -21,6 +21,7 @@ #include "wsgate.hpp" #include "wsgateEHS.hpp" #include "myWsHandler.hpp" +#include "wsGateService.hpp" namespace wsgate { @@ -441,130 +442,7 @@ int main (int argc, char **argv) namespace wsgate { - class WsGateService : public NTService { - public: - - WsGateService() : NTService("FreeRDP-WebConnect", "FreeRDP WebConnect") - { - m_dwServiceStartupType = SERVICE_AUTO_START; - m_sDescription.assign("RDP Web access gateway"); - AddDependency("Eventlog"); - } - - protected: - - bool OnServiceStop() - { - g_signaled = true; - return true; - } - - bool OnServiceShutdown() - { - g_signaled = true; - return true; - } - - void RunService() - { - g_signaled = false; - // On Windows, always set out working dir to ../ relatively seen from - // the binary's path. - path p(m_sModulePath); - string wdir(p.branch_path().branch_path().string()); - chdir(wdir.c_str()); - g_signaled = false; - char *argv[] = { - strdup("wsgate"), - strdup("-c"), - strdup("etc/wsgate.ini"), - NULL - }; - int r = _service_main(3, argv); - if (0 != r) { - m_ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - m_ServiceStatus.dwServiceSpecificExitCode = r; - } - free(argv[0]); - free(argv[1]); - free(argv[2]); - } - - public: - - bool ParseSpecialArgs(int argc, char **argv) - { - if (argc < 2) { - return false; - } - bool installed = false; - try { - installed = IsServiceInstalled(); - } catch (const tracing::runtime_error &e) { - cerr << e.what() << endl; - return true; - } - if (0 == strcmp(argv[1], "--query")) { - // Report version of installed service - cout << "The service is " << (installed ? "currently" : "not") - << " installed." << endl; - return true; - } - if (0 == strcmp(argv[1], "--start")) { - // Start the service - try { - Start(); - } catch (const tracing::runtime_error &e) { - cerr << "Failed to start " << m_sServiceName << endl; - cerr << e.what() << endl; - } - return true; - } - if (0 == strcmp(argv[1], "--stop")) { - // Start the service - try { - Stop(); - } catch (const tracing::runtime_error &e) { - cerr << "Failed to stop " << m_sServiceName << endl; - cerr << e.what() << endl; - } - return true; - } - if (0 == strcmp(argv[1], "--install")) { - // Install the service - if (installed) { - cout << m_sServiceName << " is already installed." << endl; - } else { - try { - InstallService(); - cout << m_sServiceName << " installed." << endl; - } catch (const tracing::runtime_error &e) { - cerr << "Failed to install " << m_sServiceName << endl; - cerr << e.what() << endl; - } - } - return true; - } - if (0 == strcmp(argv[1], "--remove")) { - // Remove the service - if (!installed) { - cout << m_sServiceName << " is not installed." << endl; - } else { - try { - UninstallService(); - cout << m_sServiceName << " removed." << endl; - } catch (const tracing::runtime_error &e) { - cerr << "Failed to remove " << m_sServiceName << endl; - cerr << e.what() << endl; - } - } - return true; - } - return false; - } - - }; } int main (int argc, char **argv) From b7e70677706ec71a72d913127c7e3857e87296fa Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 21:52:47 +0300 Subject: [PATCH 049/130] Separated MyRawSocketHandler from main --- wsgate/myrawsocket.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++ wsgate/wsgate_main.cpp | 80 -------------------------------------- 2 files changed, 87 insertions(+), 80 deletions(-) create mode 100644 wsgate/myrawsocket.cpp diff --git a/wsgate/myrawsocket.cpp b/wsgate/myrawsocket.cpp new file mode 100644 index 00000000..8405b9f3 --- /dev/null +++ b/wsgate/myrawsocket.cpp @@ -0,0 +1,87 @@ +#include "myrawsocket.hpp" +#include "wsgateEHS.hpp" +#include "myWsHandler.hpp" + +namespace wsgate{ + MyRawSocketHandler::MyRawSocketHandler(WsGate *parent) + : m_parent(parent) + , m_cmap(conn_map()) + { } + + bool MyRawSocketHandler::OnData(EHSConnection *conn, std::string data) + { + if (m_cmap.end() != m_cmap.find(conn)) { + m_cmap[conn].get<0>()->AddRxData(data); + return true; + } + return false; + } + + void MyRawSocketHandler::OnConnect(EHSConnection * /* conn */) + { + log::debug << "GOT WS CONNECT" << endl; + } + + void MyRawSocketHandler:: OnDisconnect(EHSConnection *conn) + { + log::debug << "GOT WS DISCONNECT" << endl; + m_parent->UnregisterRdpSession(m_cmap[conn].get<2>()); + m_cmap.erase(conn); + } + + void MyRawSocketHandler::OnMessage(EHSConnection *conn, const std::string & data) + { + if (m_cmap.end() != m_cmap.find(conn)) { + m_cmap[conn].get<2>()->OnWsMessage(data); + } + } + + bool MyRawSocketHandler::Prepare(EHSConnection *conn, const string host, const string pcb, + const string user, const string pass, const WsRdpParams ¶ms, EmbeddedContext embeddedContext) + { + try + { + handler_ptr h(new MyWsHandler(conn, m_parent, this)); + conn_ptr c(new wspp::wsendpoint(h.get())); + rdp_ptr r(new RDP(h.get(), this)); + m_cmap[conn] = conn_tuple(c, h, r); + + r->setEmbeddedContext(embeddedContext); + + this->conn = conn; + if (embeddedContext == CONTEXT_EMBEDDED){ + PrepareRDP(host, pcb, user, pass, params); + } + } + catch(...) + { + log::info << "Attemtped double connection to the same machine" << endl; + return false; + } + return true; + } + + void MyRawSocketHandler::PrepareRDP(const std::string host, const std::string pcb, const std::string user, const std::string pass, const WsRdpParams ¶ms){ + string username; + string domain; + SplitUserDomain(user, username, domain); + + rdp_ptr r = this->m_cmap[this->conn].get<2>(); + r->Connect(host, pcb, username, domain, pass, params); + m_parent->RegisterRdpSession(r); + + log::debug << "RDP Host: '" << host << "'" << endl; + log::debug << "RDP Pcb: '" << pcb << "'" << endl; + log::debug << "RDP User: '" << user << "'" << endl; + log::info << "RDP Port: '" << params.port << "'" << endl; + log::debug << "RDP Desktop size: " << params.width << "x" << params.height << endl; + log::debug << "RDP Performance: " << params.perf << endl; + log::debug << "RDP No wallpaper: " << params.nowallp << endl; + log::debug << "RDP No full windowdrag: " << params.nowdrag << endl; + log::debug << "RDP No menu animation: " << params.nomani << endl; + log::debug << "RDP No theming: " << params.nomani << endl; + log::debug << "RDP Disable TLS: " << params.notls << endl; + log::debug << "RDP Disable NLA: " << params.nonla << endl; + log::debug << "RDP NTLM auth: " << params.fntlm << endl; + } +} \ No newline at end of file diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 414a2044..6aefffb8 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -69,87 +69,7 @@ namespace wsgate { }; #endif - MyRawSocketHandler::MyRawSocketHandler(WsGate *parent) - : m_parent(parent) - , m_cmap(conn_map()) - { } - - bool MyRawSocketHandler::OnData(EHSConnection *conn, std::string data) - { - if (m_cmap.end() != m_cmap.find(conn)) { - m_cmap[conn].get<0>()->AddRxData(data); - return true; - } - return false; - } - - void MyRawSocketHandler::OnConnect(EHSConnection * /* conn */) - { - log::debug << "GOT WS CONNECT" << endl; - } - void MyRawSocketHandler:: OnDisconnect(EHSConnection *conn) - { - log::debug << "GOT WS DISCONNECT" << endl; - m_parent->UnregisterRdpSession(m_cmap[conn].get<2>()); - m_cmap.erase(conn); - } - - void MyRawSocketHandler::OnMessage(EHSConnection *conn, const std::string & data) - { - if (m_cmap.end() != m_cmap.find(conn)) { - m_cmap[conn].get<2>()->OnWsMessage(data); - } - } - - bool MyRawSocketHandler::Prepare(EHSConnection *conn, const string host, const string pcb, - const string user, const string pass, const WsRdpParams ¶ms, EmbeddedContext embeddedContext) - { - try - { - handler_ptr h(new MyWsHandler(conn, m_parent, this)); - conn_ptr c(new wspp::wsendpoint(h.get())); - rdp_ptr r(new RDP(h.get(), this)); - m_cmap[conn] = conn_tuple(c, h, r); - - r->setEmbeddedContext(embeddedContext); - - this->conn = conn; - if (embeddedContext == CONTEXT_EMBEDDED){ - PrepareRDP(host, pcb, user, pass, params); - } - } - catch(...) - { - log::info << "Attemtped double connection to the same machine" << endl; - return false; - } - return true; - } - - void MyRawSocketHandler::PrepareRDP(const std::string host, const std::string pcb, const std::string user, const std::string pass, const WsRdpParams ¶ms){ - string username; - string domain; - SplitUserDomain(user, username, domain); - - rdp_ptr r = this->m_cmap[this->conn].get<2>(); - r->Connect(host, pcb, username, domain, pass, params); - m_parent->RegisterRdpSession(r); - - log::debug << "RDP Host: '" << host << "'" << endl; - log::debug << "RDP Pcb: '" << pcb << "'" << endl; - log::debug << "RDP User: '" << user << "'" << endl; - log::info << "RDP Port: '" << params.port << "'" << endl; - log::debug << "RDP Desktop size: " << params.width << "x" << params.height << endl; - log::debug << "RDP Performance: " << params.perf << endl; - log::debug << "RDP No wallpaper: " << params.nowallp << endl; - log::debug << "RDP No full windowdrag: " << params.nowdrag << endl; - log::debug << "RDP No menu animation: " << params.nomani << endl; - log::debug << "RDP No theming: " << params.nomani << endl; - log::debug << "RDP Disable TLS: " << params.notls << endl; - log::debug << "RDP Disable NLA: " << params.nonla << endl; - log::debug << "RDP NTLM auth: " << params.fntlm << endl; - } } From f1a0bb2c8f460e1bfbb7e2b2faa0d574dcd8cfc6 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 22:30:16 +0300 Subject: [PATCH 050/130] Separated myBindHelper from main --- wsgate/myBindHelper.cpp | 40 ++++++++++++++++++++++++++++ wsgate/myBindHelper.hpp | 58 +++++++++++++++++++++++++++++++++++++++++ wsgate/wsgateEHS.hpp | 31 ---------------------- wsgate/wsgate_main.cpp | 51 +----------------------------------- 4 files changed, 99 insertions(+), 81 deletions(-) create mode 100644 wsgate/myBindHelper.cpp create mode 100644 wsgate/myBindHelper.hpp diff --git a/wsgate/myBindHelper.cpp b/wsgate/myBindHelper.cpp new file mode 100644 index 00000000..bc31f611 --- /dev/null +++ b/wsgate/myBindHelper.cpp @@ -0,0 +1,40 @@ +#ifndef _WIN32 + +#include "myBindHelper.hpp" + +namespace wsgate { + MyBindHelper::MyBindHelper() + :mutex(pthread_mutex_t()){ + pthread_mutex_init(&mutex, NULL); + } + + bool MyBindHelper::BindPrivilegedPort(int socket, const char *addr, const unsigned short port){ + bool ret = false; + pid_t pid; + int status; + char buf[32]; + pthread_mutex_lock(&mutex); + switch (pid = fork()) { + case 0: + sprintf(buf, "%08x%08x%04x", socket, inet_addr(addr), port); + execl(BINDHELPER_PATH, buf, ((void *)NULL)); + exit(errno); + break; + case -1: + break; + default: + if (waitpid(pid, &status, 0) != -1) { + ret = (0 == status); + if (0 != status) { + log::err << BINDHELPER_PATH << " reports: " << strerror(WEXITSTATUS(status)) << endl; + errno = WEXITSTATUS(status); + } + } + break; + } + pthread_mutex_unlock(&mutex); + return ret; + } +} + +#endif // _WIN32 \ No newline at end of file diff --git a/wsgate/myBindHelper.hpp b/wsgate/myBindHelper.hpp new file mode 100644 index 00000000..09dce8de --- /dev/null +++ b/wsgate/myBindHelper.hpp @@ -0,0 +1,58 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SIGNAL_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_UNISTD_H + #include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_WAIT_H +# include +#endif +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifndef _WIN32 + +#ifndef _MY_BIND_HELPER_ +#define _MY_BIND_HELPER_ + +#include + +namespace wsgate { + + // Bind helper is not needed on win32, because win32 does not + // have a concept of privileged ports. + class MyBindHelper : public PrivilegedBindHelper { + public: + MyBindHelper(); + bool BindPrivilegedPort(int socket, const char *addr, const unsigned short port); + private: + pthread_mutex_t mutex; + }; +} + +#endif // _MY_BIND_HELPER_ + +#endif // _WIN32 \ No newline at end of file diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index f45c26ab..65ae37fe 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -29,37 +29,6 @@ #include #include -#ifdef HAVE_SIGNAL_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_FCNTL_H -# include -#endif -#ifdef HAVE_UNISTD_H - #include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_WAIT_H -# include -#endif -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif - #include "common.hpp" #include "btexception.hpp" #include "base64.hpp" diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 6aefffb8..05677c80 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -22,56 +22,7 @@ #include "wsgateEHS.hpp" #include "myWsHandler.hpp" #include "wsGateService.hpp" - -namespace wsgate { - - -#ifndef _WIN32 - // Bind helper is not needed on win32, because win32 does not - // have a concept of privileged ports. - class MyBindHelper : public PrivilegedBindHelper { - - public: - MyBindHelper() : mutex(pthread_mutex_t()) { - pthread_mutex_init(&mutex, NULL); - } - - bool BindPrivilegedPort(int socket, const char *addr, const unsigned short port) { - bool ret = false; - pid_t pid; - int status; - char buf[32]; - pthread_mutex_lock(&mutex); - switch (pid = fork()) { - case 0: - sprintf(buf, "%08x%08x%04x", socket, inet_addr(addr), port); - execl(BINDHELPER_PATH, buf, ((void *)NULL)); - exit(errno); - break; - case -1: - break; - default: - if (waitpid(pid, &status, 0) != -1) { - ret = (0 == status); - if (0 != status) { - log::err << BINDHELPER_PATH << " reports: " << strerror(WEXITSTATUS(status)) << endl; - errno = WEXITSTATUS(status); - } - } - break; - } - pthread_mutex_unlock(&mutex); - return ret; - } - - private: - pthread_mutex_t mutex; - }; -#endif - - - -} +#include "myBindHelper.hpp" static bool g_signaled = false; #ifdef _WIN32 From e3da698d82fe7316f4b26eac5394e1d80afa950c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 22:35:24 +0300 Subject: [PATCH 051/130] Removed useless namespace declaration --- wsgate/wsgate_main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 05677c80..1af7308a 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -309,12 +309,6 @@ int main (int argc, char **argv) } #ifdef _WIN32 -// Windows Service implementation - -namespace wsgate { - - -} int main (int argc, char **argv) { From 71941890d2267ee1f0cc490115edf2db536eb262 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 22:38:00 +0300 Subject: [PATCH 052/130] Removed unused code --- wsgate/common.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wsgate/common.hpp b/wsgate/common.hpp index 30ef8fdc..41b4ea38 100644 --- a/wsgate/common.hpp +++ b/wsgate/common.hpp @@ -35,10 +35,6 @@ #endif #include -#ifdef _WIN32 -inline void sleep(int seconds) { Sleep(seconds * 1000); } -#endif - /** * The namespace of the main proxy application. */ From 9fe11a7cdc98cd54826134a17adb2d2eb90d4946 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 22:57:47 +0300 Subject: [PATCH 053/130] Stripped implementation from .hpp file --- wsgate/wsgate.hpp | 38 ++------------------------------------ wsgate/wsgateEHS.cpp | 1 + wsgate/wsgateEHS.hpp | 1 - wsgate/wsgate_main.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 44 insertions(+), 38 deletions(-) diff --git a/wsgate/wsgate.hpp b/wsgate/wsgate.hpp index e140350f..a1166d93 100644 --- a/wsgate/wsgate.hpp +++ b/wsgate/wsgate.hpp @@ -40,42 +40,8 @@ namespace wsgate { //disable two connections to the same host std::map activeConnections; - int nFormValue(HttpRequest *request, const string & name, int defval) { - string tmp(request->FormValues(name).m_sBody); - int ret = defval; - if (!tmp.empty()) { - try { - ret = boost::lexical_cast(tmp); - } catch (const boost::bad_lexical_cast & e) { ret = defval; } - } - return ret; - } - - void SplitUserDomain(const string& fullUsername, string& username, string& domain) - { - std::vector strs; - boost::split(strs, fullUsername, boost::is_any_of("\\")); - if (strs.size() > 1) - { - username = strs[1]; - domain = strs[0]; - } - else - { - strs.clear(); - boost::split(strs, fullUsername, boost::is_any_of("@")); - if (strs.size() > 1) - { - username = strs[0]; - domain = strs[1]; - } - else - { - username = fullUsername; - domain = ""; - } - } - } + int nFormValue(HttpRequest *request, const string & name, int defval); + void SplitUserDomain(const string& fullUsername, string& username, string& domain); } #endif diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index 4df12b86..f1139454 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -1,4 +1,5 @@ #include "wsgateEHS.hpp" +#include "wsgate.hpp" namespace wsgate{ WsGate::MimeType WsGate::simpleMime(const string & filename) diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index 65ae37fe..8aca448f 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -35,7 +35,6 @@ #include "sha1.hpp" #include "logging.hpp" #include "wsendpoint.hpp" -#include "wsgate.hpp" #include "myrawsocket.hpp" #include "nova_token_auth.hpp" diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 1af7308a..f2cc8a9b 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -24,6 +24,46 @@ #include "wsGateService.hpp" #include "myBindHelper.hpp" +namespace wsgate{ + + int nFormValue(HttpRequest *request, const string & name, int defval) { + string tmp(request->FormValues(name).m_sBody); + int ret = defval; + if (!tmp.empty()) { + try { + ret = boost::lexical_cast(tmp); + } catch (const boost::bad_lexical_cast & e) { ret = defval; } + } + return ret; + } + + void SplitUserDomain(const string& fullUsername, string& username, string& domain) + { + std::vector strs; + boost::split(strs, fullUsername, boost::is_any_of("\\")); + if (strs.size() > 1) + { + username = strs[1]; + domain = strs[0]; + } + else + { + strs.clear(); + boost::split(strs, fullUsername, boost::is_any_of("@")); + if (strs.size() > 1) + { + username = strs[0]; + domain = strs[1]; + } + else + { + username = fullUsername; + domain = ""; + } + } + } +} + static bool g_signaled = false; #ifdef _WIN32 static bool g_service_background = true; @@ -53,7 +93,7 @@ static void reload(int) #endif #ifdef _WIN32 -static int _service_main (int argc, char **argv) +int _service_main (int argc, char **argv) #else int main (int argc, char **argv) #endif From 1d8d28f11e252786f5dcf97a392bf119f707149c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 23:10:39 +0300 Subject: [PATCH 054/130] Stripped implementation from wsendpoint.hpp --- wsgate/wsendpoint.cpp | 307 ++++++++++++++++++++++++++++++++++++++++++ wsgate/wsendpoint.hpp | 287 +++------------------------------------ wsgate/wshandler.cpp | 15 +++ 3 files changed, 337 insertions(+), 272 deletions(-) create mode 100644 wsgate/wsendpoint.cpp create mode 100644 wsgate/wshandler.cpp diff --git a/wsgate/wsendpoint.cpp b/wsgate/wsendpoint.cpp new file mode 100644 index 00000000..edd41d29 --- /dev/null +++ b/wsgate/wsendpoint.cpp @@ -0,0 +1,307 @@ +/* vim: set et ts=4 sw=4 cindent: + * + * FreeRDP-WebConnect, + * A gateway for seamless access to your RDP-Sessions in any HTML5-compliant browser. + * + * Copyright 2012 Fritz Elfert + * This file has been partially derived from the WebSockets++ project at + * https://github.com/zaphoyd/websocketpp which is licensed under a BSD-license. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wsendpoint.hpp" + +#ifndef HAVE_BOOST_LOCK_GUARD + MutexHelper::MutexHelper(pthread_mutex_t *mutex, bool locknow = true) : + m_pMutex(mutex), m_bLocked(false) + { + if (locknow) + Lock(); + } + + MutexHelper::~MutexHelper() + { + if (m_bLocked) + pthread_mutex_unlock(m_pMutex); + } + void MutexHelper::Lock() + { + pthread_mutex_lock(m_pMutex); + m_bLocked = true; + } + + void MutexHelper::Unlock() + { + m_bLocked = false; + pthread_mutex_unlock(m_pMutex); + } +#endif + +namespace wspp { + using wsgate::log; + wsendpoint::wsendpoint(wshandler *h) + : m_rng(simple_rng()) + , m_parser(frame::parser(m_rng)) + , m_state(session::state::OPEN) + , m_lock() + , m_handler(h) + { +#ifndef HAVE_BOOST_LOCK_GUARD + pthread_mutexattr_t mattr; + pthread_mutexattr_init(&mattr); + pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_lock, &mattr); + pthread_mutexattr_destroy(&mattr); +#endif + m_handler->m_endpoint = this; + } + +#ifndef HAVE_BOOST_LOCK_GUARD + wsendpoint::~wsendpoint() { pthread_mutex_destroy(&m_lock); } +#endif + + void wsendpoint::AddRxData(std::string data) + { + std::istringstream s(data); + while (m_state != session::state::CLOSED && s.rdbuf()->in_avail()) { + try { + m_parser.consume(s); + if (m_parser.ready()) { + if (m_parser.is_control()) { + process_control(); + } else { + process_data(); + } + m_parser.reset(); + } + } catch (const tracing::wserror & e) { + if (m_parser.ready()) { + m_parser.reset(); + } + switch(e.code()) { + case tracing::wserror::PROTOCOL_VIOLATION: + send_close(close::status::PROTOCOL_ERROR,e.what()); + break; + case tracing::wserror::PAYLOAD_VIOLATION: + send_close(close::status::INVALID_PAYLOAD,e.what()); + break; + case tracing::wserror::INTERNAL_ENDPOINT_ERROR: + send_close(close::status::INTERNAL_ENDPOINT_ERROR,e.what()); + break; + case tracing::wserror::SOFT_ERROR: + continue; + case tracing::wserror::MESSAGE_TOO_BIG: + send_close(close::status::MESSAGE_TOO_BIG,e.what()); + break; + case tracing::wserror::OUT_OF_MESSAGES: + // we need to wait for a message to be returned by the + // client. We exit the read loop. handle_read_frame + // will be restarted by recycle() + //m_read_state = WAITING; + //m_endpoint.wait(type::shared_from_this()); + return; + default: + // Fatal error, forcibly end connection immediately. + log::warn + << "Dropping TCP due to unrecoverable exception: " << e.code() + << " (" << e.what() << ")" << std::endl; + shutdown(); + } + break; + } + } + } + + void wsendpoint::send(const std::string& payload, frame::opcode::value op) { +#ifdef HAVE_BOOST_LOCK_GUARD + boost::lock_guard lock(m_lock); +#else + MutexHelper((pthread_mutex_t *)&m_lock); +#endif + + if (m_state != session::state::OPEN) { + log::err << "send: enpoint-state not OPEN"; + return; + } + frame::parser control(m_rng); + control.set_opcode(op); + control.set_fin(true); + control.set_masked(false); + control.set_payload(payload); + + std::string tmp(control.get_header_str()); + tmp.append(control.get_payload_str()); + m_handler->do_response(tmp); + } + + void wsendpoint::process_data() { + m_handler->on_message(m_parser.get_header_str(), m_parser.get_payload_str()); + } + + + void wsendpoint::shutdown() { +#ifdef HAVE_BOOST_LOCK_GUARD + boost::lock_guard lock(m_lock); +#else + MutexHelper((pthread_mutex_t *)&m_lock); +#endif + + if (m_state == session::state::CLOSED) {return;} + + m_state = session::state::CLOSED; + m_handler->on_close(); + } + + void wsendpoint::pong(const std::vector & payload) { +#ifdef HAVE_BOOST_LOCK_GUARD + boost::lock_guard lock(m_lock); +#else + MutexHelper((pthread_mutex_t *)&m_lock); +#endif + + if (m_state != session::state::OPEN) {return;} + + // TODO: optimize control messages and handle case where + // endpoint is out of messages + frame::parser control(m_rng); + control.set_opcode(frame::opcode::PONG); + control.set_fin(true); + control.set_masked(false); + control.set_payload(payload); + + std::string tmp(control.get_header_str()); + tmp.append(control.get_payload_str()); + m_handler->do_response(tmp); + } + + void wsendpoint::send_close(close::status::value code, const std::string& reason) { +#ifdef HAVE_BOOST_LOCK_GUARD + boost::lock_guard lock(m_lock); +#else + MutexHelper((pthread_mutex_t *)&m_lock); +#endif + + if (m_state != session::state::OPEN) { + log::err << "Tried to disconnect a session that wasn't open" << std::endl; + return; + } + + if (close::status::invalid(code)) { + log::err << "Tried to close a connection with invalid close code: " + << code << std::endl; + return; + } else if (close::status::reserved(code)) { + log::err << "Tried to close a connection with reserved close code: " + << code << std::endl; + return; + } + + m_state = session::state::CLOSING; + + frame::parser control(m_rng); + control.set_opcode(frame::opcode::CLOSE); + control.set_fin(true); + control.set_masked(false); + if (code != close::status::NO_STATUS) { + const uint16_t payload = htons(code); + std::string pl(reinterpret_cast(&payload), 2); + pl.append(reason); + control.set_payload(pl); + } + + std::string tmp(control.get_header_str()); + tmp.append(control.get_payload_str()); + m_handler->do_response(tmp); + } + + void wsendpoint::send_close_ack(close::status::value remote_close_code, std::string remote_close_reason) { + close::status::value local_close_code; + std::string local_close_reason; + // echo close value unless there is a good reason not to. + if (remote_close_code == close::status::NO_STATUS) { + local_close_code = close::status::NORMAL; + local_close_reason = ""; + } else if (remote_close_code == close::status::ABNORMAL_CLOSE) { + // TODO: can we possibly get here? This means send_close_ack was + // called after a connection ended without getting a close + // frame + throw "shouldn't be here"; + } else if (close::status::invalid(remote_close_code)) { + // TODO: shouldn't be able to get here now either + local_close_code = close::status::PROTOCOL_ERROR; + local_close_reason = "Status code is invalid"; + } else if (close::status::reserved(remote_close_code)) { + // TODO: shouldn't be able to get here now either + local_close_code = close::status::PROTOCOL_ERROR; + local_close_reason = "Status code is reserved"; + } else { + local_close_code = remote_close_code; + local_close_reason = remote_close_reason; + } + + // TODO: check whether we should cancel the current in flight write. + // if not canceled the close message will be sent as soon as the + // current write completes. + + + frame::parser control(m_rng); + control.set_opcode(frame::opcode::CLOSE); + control.set_fin(true); + control.set_masked(false); + if (local_close_code != close::status::NO_STATUS) { + const uint16_t payload = htons(local_close_code); + std::string pl(reinterpret_cast(&payload), 2); + pl.append(local_close_reason); + control.set_payload(pl); + } + + std::string tmp(control.get_header_str()); + tmp.append(control.get_payload_str()); + m_handler->do_response(tmp); + shutdown(); + } + + void wsendpoint::process_control() { + switch (m_parser.get_opcode()) { + case frame::opcode::PING: + if (m_handler->on_ping(m_parser.get_payload_str())) { + pong(m_parser.get_payload()); + } + break; + case frame::opcode::PONG: + m_handler->on_pong(m_parser.get_payload_str()); + break; + case frame::opcode::CLOSE: + // check that the codes we got over the wire are valid + if (m_state == session::state::OPEN) { + // other end is initiating + log::debug << "sending close ack" << std::endl; + + // TODO: + send_close_ack(m_parser.get_close_code(), m_parser.get_close_reason()); + } else if (m_state == session::state::CLOSING) { + // ack of our close + log::debug << "got close ack" << std::endl; + shutdown(); + } + break; + default: + throw tracing::wserror("Invalid Opcode", + tracing::wserror::PROTOCOL_VIOLATION); + break; + } + } +} + +#endif diff --git a/wsgate/wsendpoint.hpp b/wsgate/wsendpoint.hpp index 89978eed..d3eb50f6 100644 --- a/wsgate/wsendpoint.hpp +++ b/wsgate/wsendpoint.hpp @@ -46,39 +46,22 @@ class MutexHelper { * @param mutex The mutex to use. * @param locknow false, if the mutex should not be locked initially */ - MutexHelper(pthread_mutex_t *mutex, bool locknow = true) : - m_pMutex(mutex), m_bLocked(false) - { - if (locknow) - Lock(); - } + MutexHelper(pthread_mutex_t *mutex, bool locknow = true); /** * Unlocks the associated mutex. */ - ~MutexHelper() - { - if (m_bLocked) - pthread_mutex_unlock(m_pMutex); - } + ~MutexHelper(); /** * Locks the associated mutex. */ - void Lock() - { - pthread_mutex_lock(m_pMutex); - m_bLocked = true; - } + void Lock(); /** * Unlocks the associated mutex. */ - void Unlock() - { - m_bLocked = false; - pthread_mutex_unlock(m_pMutex); - } + void Unlock(); private: pthread_mutex_t *m_pMutex; bool m_bLocked; @@ -106,25 +89,10 @@ namespace wspp { * Constructor * @param h The corresponding wshandler instance. */ - wsendpoint(wshandler *h) - : m_rng(simple_rng()) - , m_parser(frame::parser(m_rng)) - , m_state(session::state::OPEN) - , m_lock() - , m_handler(h) - { -#ifndef HAVE_BOOST_LOCK_GUARD - pthread_mutexattr_t mattr; - pthread_mutexattr_init(&mattr); - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_lock, &mattr); - pthread_mutexattr_destroy(&mattr); -#endif - m_handler->m_endpoint = this; - } + wsendpoint(wshandler *h); #ifndef HAVE_BOOST_LOCK_GUARD - ~wsendpoint() { pthread_mutex_destroy(&m_lock); } + ~wsendpoint(); #endif /** @@ -138,57 +106,7 @@ namespace wspp { * * @param data the raw data, received from the client. */ - void AddRxData(std::string data) - { - std::istringstream s(data); - while (m_state != session::state::CLOSED && s.rdbuf()->in_avail()) { - try { - m_parser.consume(s); - if (m_parser.ready()) { - if (m_parser.is_control()) { - process_control(); - } else { - process_data(); - } - m_parser.reset(); - } - } catch (const tracing::wserror & e) { - if (m_parser.ready()) { - m_parser.reset(); - } - switch(e.code()) { - case tracing::wserror::PROTOCOL_VIOLATION: - send_close(close::status::PROTOCOL_ERROR,e.what()); - break; - case tracing::wserror::PAYLOAD_VIOLATION: - send_close(close::status::INVALID_PAYLOAD,e.what()); - break; - case tracing::wserror::INTERNAL_ENDPOINT_ERROR: - send_close(close::status::INTERNAL_ENDPOINT_ERROR,e.what()); - break; - case tracing::wserror::SOFT_ERROR: - continue; - case tracing::wserror::MESSAGE_TOO_BIG: - send_close(close::status::MESSAGE_TOO_BIG,e.what()); - break; - case tracing::wserror::OUT_OF_MESSAGES: - // we need to wait for a message to be returned by the - // client. We exit the read loop. handle_read_frame - // will be restarted by recycle() - //m_read_state = WAITING; - //m_endpoint.wait(type::shared_from_this()); - return; - default: - // Fatal error, forcibly end connection immediately. - log::warn - << "Dropping TCP due to unrecoverable exception: " << e.code() - << " (" << e.what() << ")" << std::endl; - shutdown(); - } - break; - } - } - } + void AddRxData(std::string data); /** * Send a data message. @@ -197,32 +115,10 @@ namespace wspp { * @param payload The payload data. * @param op The opcode according to RFC6455 */ - void send(const std::string& payload, frame::opcode::value op) { -#ifdef HAVE_BOOST_LOCK_GUARD - boost::lock_guard lock(m_lock); -#else - MutexHelper((pthread_mutex_t *)&m_lock); -#endif - - if (m_state != session::state::OPEN) { - log::err << "send: enpoint-state not OPEN"; - return; - } - frame::parser control(m_rng); - control.set_opcode(op); - control.set_fin(true); - control.set_masked(false); - control.set_payload(payload); - - std::string tmp(control.get_header_str()); - tmp.append(control.get_payload_str()); - m_handler->do_response(tmp); - } + void send(const std::string& payload, frame::opcode::value op); private: - void process_data() { - m_handler->on_message(m_parser.get_header_str(), m_parser.get_payload_str()); - } + void process_data(); /// Ends the connection by cleaning up based on current state /** Terminate will review the outstanding resources and close each @@ -235,18 +131,7 @@ namespace wspp { * Concurrency: Must be called from within m_strand * */ - void shutdown() { -#ifdef HAVE_BOOST_LOCK_GUARD - boost::lock_guard lock(m_lock); -#else - MutexHelper((pthread_mutex_t *)&m_lock); -#endif - - if (m_state == session::state::CLOSED) {return;} - - m_state = session::state::CLOSED; - m_handler->on_close(); - } + void shutdown(); /** * Send Pong @@ -260,27 +145,7 @@ namespace wspp { * * @param payload Payload to be used for the pong */ - void pong(const std::vector & payload) { -#ifdef HAVE_BOOST_LOCK_GUARD - boost::lock_guard lock(m_lock); -#else - MutexHelper((pthread_mutex_t *)&m_lock); -#endif - - if (m_state != session::state::OPEN) {return;} - - // TODO: optimize control messages and handle case where - // endpoint is out of messages - frame::parser control(m_rng); - control.set_opcode(frame::opcode::PONG); - control.set_fin(true); - control.set_masked(false); - control.set_payload(payload); - - std::string tmp(control.get_header_str()); - tmp.append(control.get_payload_str()); - m_handler->do_response(tmp); - } + void pong(const std::vector & payload); /// Send a close frame /** @@ -294,45 +159,7 @@ namespace wspp { * @param code The code to send * @param reason The reason to send */ - void send_close(close::status::value code, const std::string& reason) { -#ifdef HAVE_BOOST_LOCK_GUARD - boost::lock_guard lock(m_lock); -#else - MutexHelper((pthread_mutex_t *)&m_lock); -#endif - - if (m_state != session::state::OPEN) { - log::err << "Tried to disconnect a session that wasn't open" << std::endl; - return; - } - - if (close::status::invalid(code)) { - log::err << "Tried to close a connection with invalid close code: " - << code << std::endl; - return; - } else if (close::status::reserved(code)) { - log::err << "Tried to close a connection with reserved close code: " - << code << std::endl; - return; - } - - m_state = session::state::CLOSING; - - frame::parser control(m_rng); - control.set_opcode(frame::opcode::CLOSE); - control.set_fin(true); - control.set_masked(false); - if (code != close::status::NO_STATUS) { - const uint16_t payload = htons(code); - std::string pl(reinterpret_cast(&payload), 2); - pl.append(reason); - control.set_payload(pl); - } - - std::string tmp(control.get_header_str()); - tmp.append(control.get_payload_str()); - m_handler->do_response(tmp); - } + void send_close(close::status::value code, const std::string& reason); /// send an acknowledgement close frame /** @@ -340,84 +167,9 @@ namespace wspp { * State: no state checking, should only be called within process_control * Concurrency: Must be called within m_stranded method */ - void send_close_ack(close::status::value remote_close_code, std::string remote_close_reason) { - close::status::value local_close_code; - std::string local_close_reason; - // echo close value unless there is a good reason not to. - if (remote_close_code == close::status::NO_STATUS) { - local_close_code = close::status::NORMAL; - local_close_reason = ""; - } else if (remote_close_code == close::status::ABNORMAL_CLOSE) { - // TODO: can we possibly get here? This means send_close_ack was - // called after a connection ended without getting a close - // frame - throw "shouldn't be here"; - } else if (close::status::invalid(remote_close_code)) { - // TODO: shouldn't be able to get here now either - local_close_code = close::status::PROTOCOL_ERROR; - local_close_reason = "Status code is invalid"; - } else if (close::status::reserved(remote_close_code)) { - // TODO: shouldn't be able to get here now either - local_close_code = close::status::PROTOCOL_ERROR; - local_close_reason = "Status code is reserved"; - } else { - local_close_code = remote_close_code; - local_close_reason = remote_close_reason; - } - - // TODO: check whether we should cancel the current in flight write. - // if not canceled the close message will be sent as soon as the - // current write completes. - - - frame::parser control(m_rng); - control.set_opcode(frame::opcode::CLOSE); - control.set_fin(true); - control.set_masked(false); - if (local_close_code != close::status::NO_STATUS) { - const uint16_t payload = htons(local_close_code); - std::string pl(reinterpret_cast(&payload), 2); - pl.append(local_close_reason); - control.set_payload(pl); - } - - std::string tmp(control.get_header_str()); - tmp.append(control.get_payload_str()); - m_handler->do_response(tmp); - shutdown(); - } - - void process_control() { - switch (m_parser.get_opcode()) { - case frame::opcode::PING: - if (m_handler->on_ping(m_parser.get_payload_str())) { - pong(m_parser.get_payload()); - } - break; - case frame::opcode::PONG: - m_handler->on_pong(m_parser.get_payload_str()); - break; - case frame::opcode::CLOSE: - // check that the codes we got over the wire are valid - if (m_state == session::state::OPEN) { - // other end is initiating - log::debug << "sending close ack" << std::endl; - - // TODO: - send_close_ack(m_parser.get_close_code(), m_parser.get_close_reason()); - } else if (m_state == session::state::CLOSING) { - // ack of our close - log::debug << "got close ack" << std::endl; - shutdown(); - } - break; - default: - throw tracing::wserror("Invalid Opcode", - tracing::wserror::PROTOCOL_VIOLATION); - break; - } - } + void send_close_ack(close::status::value remote_close_code, std::string remote_close_reason); + void process_control(); private: simple_rng m_rng; frame::parser m_parser; @@ -430,16 +182,7 @@ namespace wspp { wshandler *m_handler; }; - void wshandler::send_text(const std::string & data) { - if (m_endpoint) { - m_endpoint->send(data, frame::opcode::TEXT); - } - } - void wshandler::send_binary(const std::string & data) { - if (m_endpoint) { - m_endpoint->send(data, frame::opcode::BINARY); - } - } + } diff --git a/wsgate/wshandler.cpp b/wsgate/wshandler.cpp new file mode 100644 index 00000000..5c8d059f --- /dev/null +++ b/wsgate/wshandler.cpp @@ -0,0 +1,15 @@ +#include "wshandler.hpp" +#include "wsendpoint.hpp" + +namespace wspp{ + void wshandler::send_text(const std::string & data) { + if (m_endpoint) { + m_endpoint->send(data, frame::opcode::TEXT); + } + } + void wshandler::send_binary(const std::string & data) { + if (m_endpoint) { + m_endpoint->send(data, frame::opcode::BINARY); + } + } +} \ No newline at end of file From f0bc8688a813b6c79481796e34866f1397177d15 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 23:13:01 +0300 Subject: [PATCH 055/130] Fixed compilation error --- wsgate/wsendpoint.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wsgate/wsendpoint.cpp b/wsgate/wsendpoint.cpp index edd41d29..035d4646 100644 --- a/wsgate/wsendpoint.cpp +++ b/wsgate/wsendpoint.cpp @@ -23,7 +23,7 @@ #include "wsendpoint.hpp" #ifndef HAVE_BOOST_LOCK_GUARD - MutexHelper::MutexHelper(pthread_mutex_t *mutex, bool locknow = true) : + MutexHelper::MutexHelper(pthread_mutex_t *mutex, bool locknow) : m_pMutex(mutex), m_bLocked(false) { if (locknow) @@ -302,6 +302,4 @@ namespace wspp { break; } } -} - -#endif +} \ No newline at end of file From a7ead83398c884bb24119135719c827a935f5bb6 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 23:18:37 +0300 Subject: [PATCH 056/130] Removed unused code --- wsgate/wsgate.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/wsgate/wsgate.hpp b/wsgate/wsgate.hpp index a1166d93..625e8aa7 100644 --- a/wsgate/wsgate.hpp +++ b/wsgate/wsgate.hpp @@ -37,9 +37,6 @@ namespace wsgate { static const char * const ws_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - //disable two connections to the same host - std::map activeConnections; - int nFormValue(HttpRequest *request, const string & name, int defval); void SplitUserDomain(const string& fullUsername, string& username, string& domain); } From 325f4b81fa1c89faec4a6b983602d3e7d1b87925 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 7 Sep 2015 23:28:13 +0300 Subject: [PATCH 057/130] Fixed compilation error --- wsgate/wsendpoint.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wsgate/wsendpoint.hpp b/wsgate/wsendpoint.hpp index d3eb50f6..c97bf747 100644 --- a/wsgate/wsendpoint.hpp +++ b/wsgate/wsendpoint.hpp @@ -23,6 +23,10 @@ #ifndef WSENDPOINT_H #define WSENDPOINT_H +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include From cbb1c3c785185f49acba0ce7ee5e24135423f71d Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 11:10:15 +0300 Subject: [PATCH 058/130] Register added sources to the cmake file --- wsgate/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index ff645073..4fd6d1a8 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -589,15 +589,18 @@ add_definitions(-DBINDHELPER_PATH="${CMAKE_CURRENT_BINARY_DIR}/bindhelper${bindh set(WSGATE_SOURCES base64.cpp btexception.cpp logging.cpp sha1.cpp wsgate_main.cpp RDP.cpp Update.cpp Primary.cpp + myBindHelper.cpp myWsHandler.cpp myrawsocket.cpp + wsendpoint.cpp wsgateEHS.cpp wshandler.cpp Png.cpp nova_token_auth.cpp) if (WIN32) - set(WSGATE_SOURCES "${WSGATE_SOURCES}" NTService.cpp) + set(WSGATE_SOURCES "${WSGATE_SOURCES}" NTService.cpp wsGateService.cpp) # in order for header files to appear in VS solution, add them to the sources list set(WSGATE_SOURCES "${WSGATE_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR}/config.h base64.hpp btexception.hpp common.hpp logging.hpp myrawsocket.hpp nova_token_auth.hpp NTService.hpp Png.hpp Primary.hpp rdpcommon.hpp RDP.hpp sha1.hpp Update.hpp wscommon.hpp wsendpoint.hpp wsframe.hpp wsgate.hpp wshandler.hpp + myBindHelper.hpp myWsHandler.hpp wsGateService.hpp wsgateEHS.hpp wsutf8.hpp) endif() From c96ebfaf1f12e728759b0d14e9fcc43a2afa737a Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 16:42:22 +0300 Subject: [PATCH 059/130] Changed include paths from backslash to forward slash --- wsgate/myrawsocket.hpp | 4 ++-- wsgate/wsgate.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wsgate/myrawsocket.hpp b/wsgate/myrawsocket.hpp index eb159590..5e525ee0 100644 --- a/wsgate/myrawsocket.hpp +++ b/wsgate/myrawsocket.hpp @@ -21,8 +21,8 @@ #define _MYRAWSOCKET_H_ #include "RDP.hpp" -#include -#include +#include +#include namespace wsgate { diff --git a/wsgate/wsgate.hpp b/wsgate/wsgate.hpp index 625e8aa7..bebc9d20 100644 --- a/wsgate/wsgate.hpp +++ b/wsgate/wsgate.hpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "logging.hpp" using namespace std; From e368d72fdbb550021ac2b34829fac97ca01c5149 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 17:48:53 +0300 Subject: [PATCH 060/130] Removed redundant include --- wsgate/myWsHandler.hpp | 1 - wsgate/myrawsocket.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/wsgate/myWsHandler.hpp b/wsgate/myWsHandler.hpp index 4df8a6a2..3eebdbd8 100644 --- a/wsgate/myWsHandler.hpp +++ b/wsgate/myWsHandler.hpp @@ -3,7 +3,6 @@ #include "wshandler.hpp" #include "myrawsocket.hpp" -#include namespace wsgate{ class MyWsHandler : public wspp::wshandler diff --git a/wsgate/myrawsocket.hpp b/wsgate/myrawsocket.hpp index 5e525ee0..55aadd7f 100644 --- a/wsgate/myrawsocket.hpp +++ b/wsgate/myrawsocket.hpp @@ -22,7 +22,6 @@ #include "RDP.hpp" #include -#include namespace wsgate { From d57c37615bbe1428e52b7ef3b35b6e6f72860674 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 19:50:30 +0300 Subject: [PATCH 061/130] wsGateService is exclusive to _WIN32 --- wsgate/wsGateService.cpp | 8 +++++--- wsgate/wsGateService.hpp | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/wsgate/wsGateService.cpp b/wsgate/wsGateService.cpp index cc89a001..f842c363 100644 --- a/wsgate/wsGateService.cpp +++ b/wsgate/wsGateService.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -8,9 +10,7 @@ #include "wsGateService.hpp" #include "btexception.hpp" #include -#ifdef _WIN32 #include -#endif using namespace std; using boost::filesystem::path; @@ -134,4 +134,6 @@ namespace wsgate{ } return false; } -} \ No newline at end of file +} + +#endif //_WIN32 diff --git a/wsgate/wsGateService.hpp b/wsgate/wsGateService.hpp index be2d24c1..5c706598 100644 --- a/wsgate/wsGateService.hpp +++ b/wsgate/wsGateService.hpp @@ -1,6 +1,8 @@ #ifndef _WS_GATE_SERVICE_ #define _WS_GATE_SERVICE_ +#ifdef _WIN32 + #include "NTService.hpp" namespace wsgate{ @@ -18,4 +20,6 @@ namespace wsgate{ }; } -#endif //_WS_GATE_SERVICE_ \ No newline at end of file +#endif //_WIN32 + +#endif //_WS_GATE_SERVICE_ From daf1fb2cfc9ec32fbf9c94d634360069a54828ef Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 20:30:53 +0300 Subject: [PATCH 062/130] Use propper cross-platform cpprest strings --- wsgate/RDP.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 3c3ad172..1471c042 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -624,19 +624,19 @@ namespace wsgate { const uint32_t *op = reinterpret_cast(data.data()); switch (*op) { case WSOP_CS_CREDENTIAL_JSON: - std::wstring infoJSON = L""; + std::string infoJSON = ""; for (int i = 1; i < data.length() / 4; i++){ - infoJSON += (wchar_t)op[i]; + infoJSON += (char)op[i]; } try{ - web::json::value jsonValue = web::json::value::parse(infoJSON); - std::wstring w_host = jsonValue[L"host"].as_string(); - std::wstring w_pcb = jsonValue[L"pcb"].as_string(); - std::wstring w_user = jsonValue[L"user"].as_string(); - std::wstring w_pass = jsonValue[L"pass"].as_string(); - std::wstring w_dtsize = jsonValue[L"dtsize"].as_string(); - - std::string size(w_dtsize.begin(), w_dtsize.end()); + web::json::value jsonValue = web::json::value::parse(utility::conversions::to_string_t(infoJSON)); + utility::string_t w_host = jsonValue[L"host"].as_string(); + utility::string_t w_pcb = jsonValue[L"pcb"].as_string(); + utility::string_t w_user = jsonValue[L"user"].as_string(); + utility::string_t w_pass = jsonValue[L"pass"].as_string(); + utility::string_t w_dtsize = jsonValue[L"dtsize"].as_string(); + + utility::string_t size(w_dtsize.begin(), w_dtsize.end()); WsRdpParams params; params.fntlm = jsonValue[L"fntlm"].as_integer(); From e5eb619cb9d079c39bce1130fab001ccccf31dbe Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 9 Sep 2015 20:36:51 +0300 Subject: [PATCH 063/130] Fixed compiling error --- wsgate/myBindHelper.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wsgate/myBindHelper.cpp b/wsgate/myBindHelper.cpp index bc31f611..37ee3518 100644 --- a/wsgate/myBindHelper.cpp +++ b/wsgate/myBindHelper.cpp @@ -1,6 +1,9 @@ #ifndef _WIN32 #include "myBindHelper.hpp" +#include "wsgate.hpp" + +using namespace std; namespace wsgate { MyBindHelper::MyBindHelper() From dc3d7cf184b4f6ac67149539dd1fc9a4dc607d21 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 10 Sep 2015 15:34:30 +0300 Subject: [PATCH 064/130] Fixed protability issue --- wsgate/RDP.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 1471c042..08e8cfc0 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -624,30 +624,30 @@ namespace wsgate { const uint32_t *op = reinterpret_cast(data.data()); switch (*op) { case WSOP_CS_CREDENTIAL_JSON: - std::string infoJSON = ""; + utility::string_t infoJSON; for (int i = 1; i < data.length() / 4; i++){ infoJSON += (char)op[i]; } try{ - web::json::value jsonValue = web::json::value::parse(utility::conversions::to_string_t(infoJSON)); - utility::string_t w_host = jsonValue[L"host"].as_string(); - utility::string_t w_pcb = jsonValue[L"pcb"].as_string(); - utility::string_t w_user = jsonValue[L"user"].as_string(); - utility::string_t w_pass = jsonValue[L"pass"].as_string(); - utility::string_t w_dtsize = jsonValue[L"dtsize"].as_string(); + web::json::value jsonValue = web::json::value::parse(infoJSON); + utility::string_t w_host = jsonValue[utility::conversions::to_string_t("host")].as_string(); + utility::string_t w_pcb = jsonValue[utility::conversions::to_string_t("pcb")].as_string(); + utility::string_t w_user = jsonValue[utility::conversions::to_string_t("user")].as_string(); + utility::string_t w_pass = jsonValue[utility::conversions::to_string_t("pass")].as_string(); + utility::string_t w_dtsize = jsonValue[utility::conversions::to_string_t("dtsize")].as_string(); utility::string_t size(w_dtsize.begin(), w_dtsize.end()); WsRdpParams params; - params.fntlm = jsonValue[L"fntlm"].as_integer(); - params.nomani = jsonValue[L"nomani"].as_integer(); - params.nonla = jsonValue[L"nonla"].as_integer(); - params.notheme = jsonValue[L"notheme"].as_integer(); - params.notls = jsonValue[L"notls"].as_integer(); - params.nowallp = jsonValue[L"nowallp"].as_integer(); - params.nowdrag = jsonValue[L"nowdrag"].as_integer(); - params.perf = jsonValue[L"perf"].as_integer(); - params.port = jsonValue[L"port"].as_integer(); + params.fntlm = jsonValue[utility::conversions::to_string_t("fntlm")].as_integer(); + params.nomani = jsonValue[utility::conversions::to_string_t("nomani")].as_integer(); + params.nonla = jsonValue[utility::conversions::to_string_t("nonla")].as_integer(); + params.notheme = jsonValue[utility::conversions::to_string_t("notheme")].as_integer(); + params.notls = jsonValue[utility::conversions::to_string_t("notls")].as_integer(); + params.nowallp = jsonValue[utility::conversions::to_string_t("nowallp")].as_integer(); + params.nowdrag = jsonValue[utility::conversions::to_string_t("nowdrag")].as_integer(); + params.perf = jsonValue[utility::conversions::to_string_t("perf")].as_integer(); + params.port = jsonValue[utility::conversions::to_string_t("port")].as_integer(); if (!size.empty()) { try { From 8f6283f7abbe3c8c8aad0ebb0a6dd6faad2d3857 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 15 Sep 2015 19:38:49 +0300 Subject: [PATCH 065/130] Fixed black cursor bug --- wsgate/RDP.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 08e8cfc0..63210bd0 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -901,6 +901,19 @@ namespace wsgate { pointer->width, pointer->height, pointer->xorBpp, hclrconv); } + //check if the cursor is fully transparent + bool transparent = true; + for (int y = 0; y < pointer->height; y++){ + for (int x = 0; x < pointer->width; x++){ + if (pixels[0 + x * 4 + y * 4 * pointer->width] != 0){ + transparent = false; + } + } + } + if (transparent){ + pixels[3] = 1; + } + Png png; std::string png_string = png.GenerateFromARGB(pointer->width, pointer->height, pixels); From c47085a694f5b4b7a9c5ba79cb77b3f74ce24d58 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 15 Sep 2015 20:44:44 +0300 Subject: [PATCH 066/130] Added px to style size update --- wsgate/webroot/js/wsgate-debug.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 7b17428d..5775bac3 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -1101,8 +1101,8 @@ wsgate.RDP = new Class( { $('screen').height=resolution[1]; this.bstore.width=resolution[0]; this.bstore.height=resolution[1]; - $('textareainput').setStyle('width', resolution[0]); - $('textareainput').setStyle('height', resolution[1]); + $('textareainput').setStyle('width', resolution[0]+'px'); + $('textareainput').setStyle('height', resolution[1]+'px'); break; case 'C:': var msg = evt.data.substr(2); From 18b90efa18abead1cbc4391cb8f29151bc8bb2f2 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 15 Sep 2015 21:06:13 +0300 Subject: [PATCH 067/130] Added mouse coordinates to mouse leave event --- wsgate/webroot/js/wsgate-debug.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 5775bac3..19d39479 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -885,14 +885,22 @@ wsgate.RDP = new Class( { onMouseLeave: function(evt){ for(var button in this.mouseDownStatus){ if(this.mouseDownStatus[button]){ + var x = (this.msie > 0 || this.trident > 0) ? evt.event.layerX - evt.event.currentTarget.offsetLeft : evt.event.layerX; + var y = (this.msie > 0 || this.trident > 0) ? evt.event.layerY - evt.event.currentTarget.offsetTop : evt.event.layerY; + var maxX = $('textareainput').getStyle('width').toInt(); + var maxY = $('textareainput').getStyle('height').toInt(); + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x > maxX) x = maxX; + if (y > maxY) y = maxY; var which = button; if (this.sock.readyState == this.sock.OPEN) { buf = new ArrayBuffer(16); a = new Uint32Array(buf); a[0] = 0; // WSOP_CS_MOUSE a[1] = which; - a[2] = 0; - a[3] = 0; + a[2] = x; + a[3] = y; this.sock.send(buf); this.mouseDownStatus[which] = false; } From 817cfee33d2561aa5a9f61e26fc7f1193a1ca02a Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 17 Sep 2015 16:27:23 +0300 Subject: [PATCH 068/130] Fix multilanguage button --- wsgate/webroot/index-debug.html | 5 +++-- wsgate/webroot/js/wsgate-debug.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index 6eda4f38..fcad1c58 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -481,9 +481,10 @@

  • Ctrl+Alt+Delete
  • - +
  • + Multilanguage keyboard : OFF +
  • - diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 19d39479..85683e9e 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -226,11 +226,11 @@ wsgate.RDP = new Class( { */ useIME: false, ToggleLanguageButton: function(){ - this.useIME = $('keyboardlanguage').get('text') == "Multilanguage keyboard"; + this.useIME = $('keyboardlanguage').get('text') == "Multilanguage keyboard : OFF"; if(this.useIME){ - $('keyboardlanguage').set('text','Normal keyboard'); + $('keyboardlanguage').set('text','Multilanguage keyboard : ON'); }else{ - $('keyboardlanguage').set('text','Multilanguage keyboard'); + $('keyboardlanguage').set('text','Multilanguage keyboard : OFF'); } }, /** From 62ea6fb3aa3a6524fe1145a95ba30f091f06479e Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 21 Sep 2015 18:16:34 +0300 Subject: [PATCH 069/130] Fixed IME helper for Firefox --- wsgate/webroot/js/wsgate-debug.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 85683e9e..736c15c3 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -274,11 +274,14 @@ wsgate.RDP = new Class( { document.body.appendChild(this.textAreaInput); + //start the IME helper refresh + refreshIMEhelper(); + //make sure the textarea is always on focus this.textAreaInput.focus(); this.textAreaInput.addEvent('blur', function(){ try{ - setTimeout(function(){$('textareainput').focus();},20); + setTimeout(function(){$('textareainput').focus();},30); } catch(err){ } @@ -958,7 +961,6 @@ wsgate.RDP = new Class( { if(this.FunctionalKey(evt.code)){ if(evt.preventDefault) evt.preventDefault(); if(evt.stopPropagation) evt.stopPropagation(); - this.SendKeyUpDown(evt.code, 1); } } @@ -973,17 +975,9 @@ wsgate.RDP = new Class( { if(this.FunctionalKey(evt.code)){ if(evt.preventDefault) evt.preventDefault(); if(evt.stopPropagation) evt.stopPropagation(); - this.SendKeyUpDown(evt.code, 0); } this.DumpTextArea(evt.code); - //IME helper div - if(this.IMEon){ - $('IMEhelper').setStyle('visibility','visible'); - $('IMEhelper').set('html',$('textareainput').get('value')); - }else{ - $('IMEhelper').setStyle('visibility','hidden'); - } } }, /** @@ -1636,4 +1630,16 @@ wsgate.dRLE16_RGBA = function(inA, inLength, width, outA) { } } } - +/** + * Continuos refresh for the IMEhelper + */ +function refreshIMEhelper(){ + setTimeout(this.refreshIMEhelper,20); + //IME helper div + if(rdp.IMEon){ + $('IMEhelper').setStyle('visibility','visible'); + $('IMEhelper').set('html',$('textareainput').get('value')); + }else{ + $('IMEhelper').setStyle('visibility','hidden'); + } +} From ecaf0bb400921a16a43d91129fb23b1c4d6b0b73 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 21 Sep 2015 18:21:20 +0300 Subject: [PATCH 070/130] Fixed focus on inexistent element --- wsgate/webroot/js/wsgate-debug.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 736c15c3..dba8984d 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -280,11 +280,11 @@ wsgate.RDP = new Class( { //make sure the textarea is always on focus this.textAreaInput.focus(); this.textAreaInput.addEvent('blur', function(){ - try{ - setTimeout(function(){$('textareainput').focus();},30); - } - catch(err){ - } + setTimeout(function(){ + if($('textareainput')){ + $('textareainput').focus(); + } + },20); }); }, /** From 3d1e2feea636f2a94ebed8fd8852415a7aa89c42 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 22 Sep 2015 22:26:24 +0300 Subject: [PATCH 071/130] Change special combination method --- wsgate/RDP.cpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 63210bd0..1ccdfe31 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -478,32 +478,24 @@ namespace wsgate { uint32_t op; uint32_t code; } wsmsg; - + const wsmsg *m = reinterpret_cast(data.data()); log::debug << "Special combination sent: " << m->code << endl; - uint32_t tcode1, tcode2, tcode3 = 0; - //keeping the switch logic for further key combos + std::vector< std::pair< UINT16, UINT16 > > actionList; switch (m->code){ case 42: //ctrl+alt+delete - tcode1 = RDP_SCANCODE_LCONTROL; - tcode2 = RDP_SCANCODE_LMENU; - tcode3 = RDP_SCANCODE_DELETE; + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_LCONTROL)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_DELETE)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_DELETE)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_LCONTROL)); break; } - //send down signal for the keys - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_DOWN, tcode1); - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_DOWN, tcode2); - - //aditional signal send/release for the delete key - if (m->code == 42){ - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_DOWN, tcode3); - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_RELEASE, tcode3); - } - - //send release signal for the keys - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_RELEASE, tcode1); - freerdp_input_send_keyboard_event(m_rdpInput, KBD_FLAGS_RELEASE, tcode2); + for(unsigned int i=0;i Date: Tue, 22 Sep 2015 22:30:14 +0300 Subject: [PATCH 072/130] Changed CtrlAltDelete combination code --- wsgate/RDP.cpp | 2 +- wsgate/webroot/index-debug.html | 4 +--- wsgate/webroot/js/wsgate-debug.js | 15 +++++---------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index 1ccdfe31..a66bfc0e 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -483,7 +483,7 @@ namespace wsgate { log::debug << "Special combination sent: " << m->code << endl; std::vector< std::pair< UINT16, UINT16 > > actionList; switch (m->code){ - case 42: //ctrl+alt+delete + case 0: //ctrl+alt+delete actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_LCONTROL)); actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU)); actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_DELETE)); diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index fcad1c58..ebbfbfde 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -297,8 +297,6 @@ } } - var sendCtrlAltDel = function() { rdp.SendKey(1); } - function showDialog(show) { if (show) { ShowMouseHelper(false); @@ -326,7 +324,7 @@ { 'visibility':'visible' }); - $('ctrlaltdelete').addEvent('click', sendCtrlAltDel); + $('ctrlaltdelete').addEvent('click', function(){ rdp.SendKey(0); }); $('disconnect').addEvent('click', sendDisconnect); } } diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index dba8984d..012efde1 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -194,21 +194,16 @@ wsgate.RDP = new Class( { this._reset(); }, SendKey: function(comb) { - //Add here all the keys from the canvas - switch (comb) { - case 1: - code = 0x2a; //ctrl+alt+delete - break; - }; + //code 0 : ctrl+alt+delete + if (this.sock.readyState == this.sock.OPEN) { - this.log.debug('send special combination', code); + this.log.debug('send special combination', comb); buf = new ArrayBuffer(12); a = new Uint32Array(buf); a[0] = 3; // WSOP_CS_SPECIALCOMB - a[1] = code; + a[1] = comb; this.sock.send(buf); - - }; + }; }, SendCredentials: function() { var infoJSONstring = JSON.stringify(settingsGetJSON()); From da714f60df5b5fcd4db579649f33425505ecd1fd Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 23 Sep 2015 02:05:43 +0300 Subject: [PATCH 073/130] Added Alt+Tab combination --- wsgate/RDP.cpp | 7 +++++++ wsgate/webroot/css/style-debug.css | 5 ++++- wsgate/webroot/index-debug.html | 18 ++++++++++++++++++ wsgate/webroot/js/wsgate-debug.js | 2 ++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/wsgate/RDP.cpp b/wsgate/RDP.cpp index a66bfc0e..57d4a019 100644 --- a/wsgate/RDP.cpp +++ b/wsgate/RDP.cpp @@ -491,6 +491,13 @@ namespace wsgate { actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU)); actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_LCONTROL)); break; + case 1: //alt+tab + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_DOWN, RDP_SCANCODE_TAB)); + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_TAB)); + break; + case 2: //alt+tab release + actionList.push_back(std::pair< UINT16, UINT16 >(KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU)); } for(unsigned int i=0;i Ctrl+Alt+Delete +
  • + Alt+Tab +
  • Multilanguage keyboard : OFF
  • diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 012efde1..850a3f1d 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -195,6 +195,8 @@ wsgate.RDP = new Class( { }, SendKey: function(comb) { //code 0 : ctrl+alt+delete + //code 1 : alt+tab + //code 2 : alt+tab release if (this.sock.readyState == this.sock.OPEN) { this.log.debug('send special combination', comb); From 1ec5be8c075e2e76fe6487721bcd86431bb39d2c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 23 Sep 2015 02:31:15 +0300 Subject: [PATCH 074/130] Changed style of multilanguage button --- wsgate/webroot/index-debug.html | 2 +- wsgate/webroot/js/wsgate-debug.js | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wsgate/webroot/index-debug.html b/wsgate/webroot/index-debug.html index 8a288587..0872fd10 100644 --- a/wsgate/webroot/index-debug.html +++ b/wsgate/webroot/index-debug.html @@ -498,7 +498,7 @@ Alt+Tab
  • - Multilanguage keyboard : OFF + Multilanguage keyboard
  • diff --git a/wsgate/webroot/js/wsgate-debug.js b/wsgate/webroot/js/wsgate-debug.js index 850a3f1d..b09427d5 100644 --- a/wsgate/webroot/js/wsgate-debug.js +++ b/wsgate/webroot/js/wsgate-debug.js @@ -223,11 +223,12 @@ wsgate.RDP = new Class( { */ useIME: false, ToggleLanguageButton: function(){ - this.useIME = $('keyboardlanguage').get('text') == "Multilanguage keyboard : OFF"; if(this.useIME){ - $('keyboardlanguage').set('text','Multilanguage keyboard : ON'); + this.useIME = false; + $('keyboardlanguage').removeClass('extracommandshold'); }else{ - $('keyboardlanguage').set('text','Multilanguage keyboard : OFF'); + this.useIME = true; + $('keyboardlanguage').addClass('extracommandshold'); } }, /** From f53dcad84d216a52dad26415021add7d37e24859 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 15 Feb 2016 23:20:45 +0200 Subject: [PATCH 075/130] Fixes service never stopping --- wsgate/wsGateService.cpp | 10 ++++------ wsgate/wsGateService.hpp | 2 +- wsgate/wsgate_main.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/wsgate/wsGateService.cpp b/wsgate/wsGateService.cpp index f842c363..f2a12efb 100644 --- a/wsgate/wsGateService.cpp +++ b/wsgate/wsGateService.cpp @@ -15,14 +15,13 @@ using namespace std; using boost::filesystem::path; -extern bool g_signaled = false; #ifdef _WIN32 extern bool g_service_background = true; extern int _service_main (int argc, char **argv); #endif namespace wsgate{ - + bool WsGateService::g_signaled = false; WsGateService::WsGateService() :NTService("FreeRDP-WebConnect", "FreeRDP WebConnect") { @@ -32,23 +31,22 @@ namespace wsgate{ } bool WsGateService::OnServiceStop(){ - g_signaled = true; + WsGateService::g_signaled = true; return true; } bool WsGateService::OnServiceShutdown(){ - g_signaled = true; + WsGateService::g_signaled = true; return true; } void WsGateService::RunService(){ - g_signaled = false; + WsGateService::g_signaled = false; // On Windows, always set out working dir to ../ relatively seen from // the binary's path. path p(m_sModulePath); string wdir(p.branch_path().branch_path().string()); chdir(wdir.c_str()); - g_signaled = false; char *argv[] = { strdup("wsgate"), strdup("-c"), diff --git a/wsgate/wsGateService.hpp b/wsgate/wsGateService.hpp index 5c706598..e416dfda 100644 --- a/wsgate/wsGateService.hpp +++ b/wsgate/wsGateService.hpp @@ -8,11 +8,11 @@ namespace wsgate{ class WsGateService : public NTService { - public: WsGateService(); bool ParseSpecialArgs(int argc, char **argv); + static bool g_signaled; protected: bool OnServiceStop(); bool OnServiceShutdown(); diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index f2cc8a9b..40ba9ffe 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -64,14 +64,13 @@ namespace wsgate{ } } -static bool g_signaled = false; #ifdef _WIN32 static bool g_service_background = true; #endif static void terminate(int) { - g_signaled = true; + wsgate::WsGateService::g_signaled = true; signal(SIGINT, terminate); signal(SIGTERM, terminate); } @@ -305,7 +304,7 @@ int main (int argc, char **argv) } if (daemon) { - while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || g_signaled)) { + while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || wsgate::WsGateService::g_signaled)) { if (sleepInLoop) { usleep(50000); } else { @@ -318,7 +317,7 @@ int main (int argc, char **argv) } else { wsgate::kbdio kbd; cout << "Press q to terminate ..." << endl; - while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || g_signaled || kbd.qpressed())) + while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || wsgate::WsGateService::g_signaled || kbd.qpressed())) { if (sleepInLoop) { @@ -355,6 +354,7 @@ int main (int argc, char **argv) wsgate::WsGateService s; if (!s.ParseSpecialArgs(argc, argv)) { try { + if (!s.Execute()) { return _service_main(argc, argv); } From a05c6f9a6ecca386435b41af8189ddc8e8577aef Mon Sep 17 00:00:00 2001 From: c64cosmin Date: Tue, 8 Mar 2016 01:45:54 +0200 Subject: [PATCH 076/130] Fixed WIN32 only service signal issue #133 --- wsgate/wsgate_main.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wsgate/wsgate_main.cpp b/wsgate/wsgate_main.cpp index 40ba9ffe..0602fdaa 100644 --- a/wsgate/wsgate_main.cpp +++ b/wsgate/wsgate_main.cpp @@ -70,7 +70,9 @@ static bool g_service_background = true; static void terminate(int) { +#ifdef _WIN32 wsgate::WsGateService::g_signaled = true; +#endif signal(SIGINT, terminate); signal(SIGTERM, terminate); } @@ -304,7 +306,11 @@ int main (int argc, char **argv) } if (daemon) { +#ifdef _WIN32 while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || wsgate::WsGateService::g_signaled)) { +#else + while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()))) { +#endif if (sleepInLoop) { usleep(50000); } else { @@ -317,7 +323,11 @@ int main (int argc, char **argv) } else { wsgate::kbdio kbd; cout << "Press q to terminate ..." << endl; +#ifdef _WIN32 while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || wsgate::WsGateService::g_signaled || kbd.qpressed())) +#else + while (!(srv.ShouldTerminate() || (psrv && psrv->ShouldTerminate()) || kbd.qpressed())) +#endif { if (sleepInLoop) { From a07da71f1d2fc8cc00f14e182f2443343220ef4f Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 22 Apr 2016 16:17:12 +0300 Subject: [PATCH 077/130] Fixed port range --- wsgate/wsgateEHS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index f1139454..2f724ef5 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -824,7 +824,7 @@ namespace wsgate{ if (pt.get_optional("rdpoverride.port")) { int n = pt.get("rdpoverride.port"); - if ((0 > n) || (2 < n)) { + if ((0 > n) || (65536 < n)) { throw tracing::invalid_argument("Invalid port value."); } m_RdpOverrideParams.port = n; From 93563e819b89325f4b4cc26367f447ee9a977ae6 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 22 Apr 2016 16:29:18 +0300 Subject: [PATCH 078/130] Added PCB override field --- wsgate/wsgateEHS.cpp | 8 ++++++++ wsgate/wsgateEHS.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index 2f724ef5..f31e1550 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -822,6 +822,14 @@ namespace wsgate{ m_bOverrideRdpPass = false; } + if (pt.get_optional("rdpoverride.pcb")) { + m_sRdpOverridePcb.assign(pt.get("rdpoverride.pcb")); + m_bOverrideRdpPcb = true; + } + else { + m_bOverrideRdpPcb = false; + } + if (pt.get_optional("rdpoverride.port")) { int n = pt.get("rdpoverride.port"); if ((0 > n) || (65536 < n)) { diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index 8aca448f..ee36517a 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -111,6 +111,7 @@ namespace wsgate{ bool m_bOverrideRdpPort; bool m_bOverrideRdpUser; bool m_bOverrideRdpPass; + bool m_bOverrideRdpPcb; bool m_bOverrideRdpPerf; bool m_bOverrideRdpNowallp; bool m_bOverrideRdpNowdrag; @@ -122,6 +123,7 @@ namespace wsgate{ string m_sRdpOverrideHost; string m_sRdpOverrideUser; string m_sRdpOverridePass; + string m_sRdpOverridePcb; WsRdpParams m_RdpOverrideParams; string m_sConfigFile; boost::property_tree::ptree m_ptIniConfig; From 06c3f88418710b41408ffa4f24b6ee20f81a9026 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 22 Apr 2016 17:49:23 +0300 Subject: [PATCH 079/130] Getter for override parameters --- wsgate/rdpcommon.hpp | 24 ++++++ wsgate/wsgateEHS.cpp | 199 ++++++++++++++++++++++--------------------- wsgate/wsgateEHS.hpp | 20 +---- 3 files changed, 126 insertions(+), 117 deletions(-) diff --git a/wsgate/rdpcommon.hpp b/wsgate/rdpcommon.hpp index e132d586..fd7aea09 100644 --- a/wsgate/rdpcommon.hpp +++ b/wsgate/rdpcommon.hpp @@ -108,6 +108,30 @@ namespace wsgate { int notheme; } WsRdpParams; + /** + * Set of override parameters + */ + typedef struct{ + bool m_bOverrideRdpHost; + bool m_bOverrideRdpPort; + bool m_bOverrideRdpUser; + bool m_bOverrideRdpPass; + bool m_bOverrideRdpPcb; + bool m_bOverrideRdpPerf; + bool m_bOverrideRdpNowallp; + bool m_bOverrideRdpNowdrag; + bool m_bOverrideRdpNomani; + bool m_bOverrideRdpNotheme; + bool m_bOverrideRdpNotls; + bool m_bOverrideRdpNonla; + bool m_bOverrideRdpFntlm; + string m_sRdpOverrideHost; + string m_sRdpOverrideUser; + string m_sRdpOverridePass; + string m_sRdpOverridePcb; + WsRdpParams m_RdpOverrideParams; + } WsRdpOverrideParams; + /** * Our extension of FreeRDP's context */ diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index f31e1550..fd4998c3 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -36,28 +36,25 @@ namespace wsgate{ , m_allowedHosts() , m_deniedHosts() , m_bOrderDenyAllow(true) - , m_bOverrideRdpHost(false) - , m_bOverrideRdpPort(false) - , m_bOverrideRdpUser(false) - , m_bOverrideRdpPass(false) - , m_bOverrideRdpPerf(false) - , m_bOverrideRdpNowallp(false) - , m_bOverrideRdpNowdrag(false) - , m_bOverrideRdpNomani(false) - , m_bOverrideRdpNotheme(false) - , m_bOverrideRdpNotls(false) - , m_bOverrideRdpNonla(false) - , m_bOverrideRdpFntlm(false) - , m_sRdpOverrideHost() - , m_sRdpOverrideUser() - , m_sRdpOverridePass() - , m_RdpOverrideParams() , m_sConfigFile() , m_ptIniConfig() , m_bDaemon(false) , m_bRedirect(false) , m_StaticCache() { + overrideParams.m_bOverrideRdpHost = false; + overrideParams.m_bOverrideRdpPort = false; + overrideParams.m_bOverrideRdpUser = false; + overrideParams.m_bOverrideRdpPass = false; + overrideParams.m_bOverrideRdpPcb = false; + overrideParams.m_bOverrideRdpPerf = false; + overrideParams.m_bOverrideRdpNowallp = false; + overrideParams.m_bOverrideRdpNowdrag = false; + overrideParams.m_bOverrideRdpNomani = false; + overrideParams.m_bOverrideRdpNotheme = false; + overrideParams.m_bOverrideRdpNotls = false; + overrideParams.m_bOverrideRdpNonla = false; + overrideParams.m_bOverrideRdpFntlm = false; } WsGate::~WsGate() @@ -93,14 +90,14 @@ namespace wsgate{ void WsGate::CheckForPredefined(string& rdpHost, string& rdpUser, string& rdpPass) { - if (m_bOverrideRdpHost) - rdpHost.assign(m_sRdpOverrideHost); + if (this->overrideParams.m_bOverrideRdpHost) + rdpHost.assign(this->overrideParams.m_sRdpOverrideHost); - if (m_bOverrideRdpUser) - rdpUser.assign(m_sRdpOverrideUser); + if (this->overrideParams.m_bOverrideRdpUser) + rdpUser.assign(this->overrideParams.m_sRdpOverrideUser); - if (m_bOverrideRdpPass) - rdpPass.assign(m_sRdpOverridePass); + if (this->overrideParams.m_bOverrideRdpPass) + rdpPass.assign(this->overrideParams.m_sRdpOverridePass); } bool WsGate::ConnectionIsAllowed(string rdphost) @@ -317,14 +314,14 @@ namespace wsgate{ rdpport, 1024, 768, - m_bOverrideRdpPerf ? m_RdpOverrideParams.perf : nFormValue(request, "perf", 0), - m_bOverrideRdpFntlm ? m_RdpOverrideParams.fntlm : nFormValue(request, "fntlm", 0), - m_bOverrideRdpNotls ? m_RdpOverrideParams.notls : nFormValue(request, "notls", 0), - m_bOverrideRdpNonla ? m_RdpOverrideParams.nonla : nFormValue(request, "nonla", 0), - m_bOverrideRdpNowallp ? m_RdpOverrideParams.nowallp : nFormValue(request, "nowallp", 0), - m_bOverrideRdpNowdrag ? m_RdpOverrideParams.nowdrag : nFormValue(request, "nowdrag", 0), - m_bOverrideRdpNomani ? m_RdpOverrideParams.nomani : nFormValue(request, "nomani", 0), - m_bOverrideRdpNotheme ? m_RdpOverrideParams.notheme : nFormValue(request, "notheme", 0), + this->overrideParams.m_bOverrideRdpPerf ? this->overrideParams.m_RdpOverrideParams.perf : nFormValue(request, "perf", 0), + this->overrideParams.m_bOverrideRdpFntlm ? this->overrideParams.m_RdpOverrideParams.fntlm : nFormValue(request, "fntlm", 0), + this->overrideParams.m_bOverrideRdpNotls ? this->overrideParams.m_RdpOverrideParams.notls : nFormValue(request, "notls", 0), + this->overrideParams.m_bOverrideRdpNonla ? this->overrideParams.m_RdpOverrideParams.nonla : nFormValue(request, "nonla", 0), + this->overrideParams.m_bOverrideRdpNowallp ? this->overrideParams.m_RdpOverrideParams.nowallp : nFormValue(request, "nowallp", 0), + this->overrideParams.m_bOverrideRdpNowdrag ? this->overrideParams.m_RdpOverrideParams.nowdrag : nFormValue(request, "nowdrag", 0), + this->overrideParams.m_bOverrideRdpNomani ? this->overrideParams.m_RdpOverrideParams.nomani : nFormValue(request, "nomani", 0), + this->overrideParams.m_bOverrideRdpNotheme ? this->overrideParams.m_RdpOverrideParams.notheme : nFormValue(request, "notheme", 0), }; CheckForPredefined(rdphost, rdpuser, rdppass); @@ -555,23 +552,23 @@ namespace wsgate{ } else { - tmp.assign(m_bOverrideRdpUser ? "" : request->Cookies("lastuser")); + tmp.assign(this->overrideParams.m_bOverrideRdpUser ? "" : request->Cookies("lastuser")); replace_all(body, "%COOKIE_LASTUSER%", tmp); - tmp.assign(m_bOverrideRdpUser ? "disabled=\"disabled\"" : ""); + tmp.assign(this->overrideParams.m_bOverrideRdpUser ? "disabled=\"disabled\"" : ""); replace_all(body, "%DISABLED_USER%", tmp); - tmp.assign(m_bOverrideRdpPass ? "SomthingUseless" : base64_decode(request->Cookies("lastpass"))); + tmp.assign(this->overrideParams.m_bOverrideRdpPass ? "SomthingUseless" : base64_decode(request->Cookies("lastpass"))); replace_all(body, "%COOKIE_LASTPASS%", tmp); - tmp.assign(m_bOverrideRdpPass ? "disabled=\"disabled\"" : ""); + tmp.assign(this->overrideParams.m_bOverrideRdpPass ? "disabled=\"disabled\"" : ""); replace_all(body, "%DISABLED_PASS%", tmp); - tmp.assign(m_bOverrideRdpHost ? "" : request->Cookies("lasthost")); + tmp.assign(this->overrideParams.m_bOverrideRdpHost ? "" : request->Cookies("lasthost")); replace_all(body, "%COOKIE_LASTHOST%", tmp); - tmp.assign(m_bOverrideRdpHost ? "disabled=\"disabled\"" : ""); + tmp.assign(this->overrideParams.m_bOverrideRdpHost ? "disabled=\"disabled\"" : ""); replace_all(body, "%DISABLED_HOST%", tmp); - tmp.assign(request->Cookies("lastpcb")); + tmp.assign(this->overrideParams.m_bOverrideRdpPcb ? "" : request->Cookies("lastpcb")); replace_all(body, "%COOKIE_LASTPCB%", tmp); - tmp.assign(""); + tmp.assign(this->overrideParams.m_bOverrideRdpPcb ? "disabled=\"disabled\"" : ""); replace_all(body, "%DISABLED_PCB%", tmp); } @@ -579,21 +576,21 @@ namespace wsgate{ replace_all(body, "%VERSION%", tmp); //The new Port Selector - if(m_bOverrideRdpPort) { + if (this->overrideParams.m_bOverrideRdpPort) { replace_all(body, "%DISABLED_PORT%", "disabled=\"disabled\""); } else { replace_all(body, "%DISABLED_PORT%", ""); } - tmp.assign(m_bOverrideRdpPort ? boost::lexical_cast(m_RdpOverrideParams.port) : "3389"); + tmp.assign(this->overrideParams.m_bOverrideRdpPort ? boost::lexical_cast(this->overrideParams.m_RdpOverrideParams.port) : "3389"); replace_all(body, "%DEFAULT_PORT%", tmp); //The Desktop Resolution - if (m_bOverrideRdpPerf) { + if (this->overrideParams.m_bOverrideRdpPerf) { replace_all(body, "%DISABLED_PERF%", "disabled=\"disabled\""); - replace_all(body, "%SELECTED_PERF0%", (0 == m_RdpOverrideParams.perf) ? "selected" : ""); - replace_all(body, "%SELECTED_PERF1%", (1 == m_RdpOverrideParams.perf) ? "selected" : ""); - replace_all(body, "%SELECTED_PERF2%", (2 == m_RdpOverrideParams.perf) ? "selected" : ""); + replace_all(body, "%SELECTED_PERF0%", (0 == this->overrideParams.m_RdpOverrideParams.perf) ? "selected" : ""); + replace_all(body, "%SELECTED_PERF1%", (1 == this->overrideParams.m_RdpOverrideParams.perf) ? "selected" : ""); + replace_all(body, "%SELECTED_PERF2%", (2 == this->overrideParams.m_RdpOverrideParams.perf) ? "selected" : ""); } else { replace_all(body, "%DISABLED_PERF%", ""); replace_all(body, "%SELECTED_PERF0%", ""); @@ -602,49 +599,49 @@ namespace wsgate{ } - if (m_bOverrideRdpFntlm) { + if (this->overrideParams.m_bOverrideRdpFntlm) { replace_all(body, "%DISABLED_FNTLM%", "disabled=\"disabled\""); - replace_all(body, "%SELECTED_FNTLM0%", (0 == m_RdpOverrideParams.fntlm) ? "selected" : ""); - replace_all(body, "%SELECTED_FNTLM1%", (1 == m_RdpOverrideParams.fntlm) ? "selected" : ""); - replace_all(body, "%SELECTED_FNTLM2%", (2 == m_RdpOverrideParams.fntlm) ? "selected" : ""); + replace_all(body, "%SELECTED_FNTLM0%", (0 == this->overrideParams.m_RdpOverrideParams.fntlm) ? "selected" : ""); + replace_all(body, "%SELECTED_FNTLM1%", (1 == this->overrideParams.m_RdpOverrideParams.fntlm) ? "selected" : ""); + replace_all(body, "%SELECTED_FNTLM2%", (2 == this->overrideParams.m_RdpOverrideParams.fntlm) ? "selected" : ""); } else { replace_all(body, "%DISABLED_FNTLM%", ""); replace_all(body, "%SELECTED_FNTLM0%", ""); replace_all(body, "%SELECTED_FNTLM1%", ""); replace_all(body, "%SELECTED_FNTLM2%", ""); } - if (m_bOverrideRdpNowallp) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowallp) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNowallp) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.nowallp) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } replace_all(body, "%CHECKED_NOWALLP%", tmp); - if (m_bOverrideRdpNowdrag) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nowdrag) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNowdrag) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.nowdrag) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } replace_all(body, "%CHECKED_NOWDRAG%", tmp); - if (m_bOverrideRdpNomani) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nomani) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNomani) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.nomani) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } replace_all(body, "%CHECKED_NOMANI%", tmp); - if (m_bOverrideRdpNotheme) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notheme) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNotheme) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.notheme) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } replace_all(body, "%CHECKED_NOTHEME%", tmp); - if (m_bOverrideRdpNotls) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.notls) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNotls) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.notls) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } replace_all(body, "%CHECKED_NOTLS%", tmp); - if (m_bOverrideRdpNonla) { - tmp.assign("disabled=\"disabled\"").append((m_RdpOverrideParams.nonla) ? " checked=\"checked\"" : ""); + if (this->overrideParams.m_bOverrideRdpNonla) { + tmp.assign("disabled=\"disabled\"").append((this->overrideParams.m_RdpOverrideParams.nonla) ? " checked=\"checked\"" : ""); } else { tmp.assign(""); } @@ -804,30 +801,30 @@ namespace wsgate{ } if (pt.get_optional("rdpoverride.host")) { - m_sRdpOverrideHost.assign(pt.get("rdpoverride.host")); - m_bOverrideRdpHost = true; + this->overrideParams.m_sRdpOverrideHost.assign(pt.get("rdpoverride.host")); + this->overrideParams.m_bOverrideRdpHost = true; } else { - m_bOverrideRdpHost = false; + this->overrideParams.m_bOverrideRdpHost = false; } if (pt.get_optional("rdpoverride.user")) { - m_sRdpOverrideUser.assign(pt.get("rdpoverride.user")); - m_bOverrideRdpUser = true; + this->overrideParams.m_sRdpOverrideUser.assign(pt.get("rdpoverride.user")); + this->overrideParams.m_bOverrideRdpUser = true; } else { - m_bOverrideRdpUser = false; + this->overrideParams.m_bOverrideRdpUser = false; } if (pt.get_optional("rdpoverride.pass")) { - m_sRdpOverridePass.assign(pt.get("rdpoverride.pass")); - m_bOverrideRdpPass = true; + this->overrideParams.m_sRdpOverridePass.assign(pt.get("rdpoverride.pass")); + this->overrideParams.m_bOverrideRdpPass = true; } else { - m_bOverrideRdpPass = false; + this->overrideParams.m_bOverrideRdpPass = false; } if (pt.get_optional("rdpoverride.pcb")) { - m_sRdpOverridePcb.assign(pt.get("rdpoverride.pcb")); - m_bOverrideRdpPcb = true; + this->overrideParams.m_sRdpOverridePcb.assign(pt.get("rdpoverride.pcb")); + this->overrideParams.m_bOverrideRdpPcb = true; } else { - m_bOverrideRdpPcb = false; + this->overrideParams.m_bOverrideRdpPcb = false; } if (pt.get_optional("rdpoverride.port")) { @@ -835,10 +832,10 @@ namespace wsgate{ if ((0 > n) || (65536 < n)) { throw tracing::invalid_argument("Invalid port value."); } - m_RdpOverrideParams.port = n; - m_bOverrideRdpPort = true; + this->overrideParams.m_RdpOverrideParams.port = n; + this->overrideParams.m_bOverrideRdpPort = true; } else { - m_bOverrideRdpPort = false; + this->overrideParams.m_bOverrideRdpPort = false; } if (pt.get_optional("rdpoverride.performance")) { @@ -846,56 +843,56 @@ namespace wsgate{ if ((0 > n) || (2 < n)) { throw tracing::invalid_argument("Invalid performance value."); } - m_RdpOverrideParams.perf = n; - m_bOverrideRdpPerf = true; + this->overrideParams.m_RdpOverrideParams.perf = n; + this->overrideParams.m_bOverrideRdpPerf = true; } else { - m_bOverrideRdpPerf = false; + this->overrideParams.m_bOverrideRdpPerf = false; } if (pt.get_optional("rdpoverride.forcentlm")) { int n = pt.get("rdpoverride.forcentlm"); if ((0 > n) || (2 < n)) { throw tracing::invalid_argument("Invalid forcentlm value."); } - m_RdpOverrideParams.fntlm = n; - m_bOverrideRdpFntlm = true; + this->overrideParams.m_RdpOverrideParams.fntlm = n; + this->overrideParams.m_bOverrideRdpFntlm = true; } else { - m_bOverrideRdpFntlm = false; + this->overrideParams.m_bOverrideRdpFntlm = false; } if (pt.get_optional("rdpoverride.nowallpaper")) { - m_RdpOverrideParams.nowallp = str2bint(pt.get("rdpoverride.nowallpaper")); - m_bOverrideRdpNowallp = true; + this->overrideParams.m_RdpOverrideParams.nowallp = str2bint(pt.get("rdpoverride.nowallpaper")); + this->overrideParams.m_bOverrideRdpNowallp = true; } else { - m_bOverrideRdpNowallp = false; + this->overrideParams.m_bOverrideRdpNowallp = false; } if (pt.get_optional("rdpoverride.nofullwindowdrag")) { - m_RdpOverrideParams.nowdrag = str2bint(pt.get("rdpoverride.nofullwindowdrag")); - m_bOverrideRdpNowdrag = true; + this->overrideParams.m_RdpOverrideParams.nowdrag = str2bint(pt.get("rdpoverride.nofullwindowdrag")); + this->overrideParams.m_bOverrideRdpNowdrag = true; } else { - m_bOverrideRdpNowdrag = false; + this->overrideParams.m_bOverrideRdpNowdrag = false; } if (pt.get_optional("rdpoverride.nomenuanimation")) { - m_RdpOverrideParams.nomani = str2bint(pt.get("rdpoverride.nomenuanimation")); - m_bOverrideRdpNomani = true; + this->overrideParams.m_RdpOverrideParams.nomani = str2bint(pt.get("rdpoverride.nomenuanimation")); + this->overrideParams.m_bOverrideRdpNomani = true; } else { - m_bOverrideRdpNomani = false; + this->overrideParams.m_bOverrideRdpNomani = false; } if (pt.get_optional("rdpoverride.notheming")) { - m_RdpOverrideParams.notheme = str2bint(pt.get("rdpoverride.notheming")); - m_bOverrideRdpNotheme = true; + this->overrideParams.m_RdpOverrideParams.notheme = str2bint(pt.get("rdpoverride.notheming")); + this->overrideParams.m_bOverrideRdpNotheme = true; } else { - m_bOverrideRdpNotheme = false; + this->overrideParams.m_bOverrideRdpNotheme = false; } if (pt.get_optional("rdpoverride.notls")) { - m_RdpOverrideParams.notls = str2bint(pt.get("rdpoverride.notls")); - m_bOverrideRdpNotls = true; + this->overrideParams.m_RdpOverrideParams.notls = str2bint(pt.get("rdpoverride.notls")); + this->overrideParams.m_bOverrideRdpNotls = true; } else { - m_bOverrideRdpNotls = false; + this->overrideParams.m_bOverrideRdpNotls = false; } if (pt.get_optional("rdpoverride.nonla")) { - m_RdpOverrideParams.nonla = str2bint(pt.get("rdpoverride.nonla")); - m_bOverrideRdpNonla = true; + this->overrideParams.m_RdpOverrideParams.nonla = str2bint(pt.get("rdpoverride.nonla")); + this->overrideParams.m_bOverrideRdpNonla = true; } else { - m_bOverrideRdpNonla = false; + this->overrideParams.m_bOverrideRdpNonla = false; } if (pt.get_optional("global.hostname")) { m_sHostname.assign(pt.get("global.hostname")); @@ -1079,4 +1076,8 @@ namespace wsgate{ oss << hex << rdp.get(); m_SessionMap.erase(oss.str()); } + + WsRdpOverrideParams WsGate::getOverrideParams(){ + return this->overrideParams; + } } diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index ee36517a..10054d7e 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -81,6 +81,7 @@ namespace wsgate{ void SetPidFile(const string &name); void RegisterRdpSession(rdp_ptr rdp); void UnregisterRdpSession(rdp_ptr rdp); + WsRdpOverrideParams getOverrideParams(); private: typedef enum { TEXT, @@ -106,25 +107,8 @@ namespace wsgate{ SessionMap m_SessionMap; vector m_allowedHosts; vector m_deniedHosts; + WsRdpOverrideParams overrideParams; bool m_bOrderDenyAllow; - bool m_bOverrideRdpHost; - bool m_bOverrideRdpPort; - bool m_bOverrideRdpUser; - bool m_bOverrideRdpPass; - bool m_bOverrideRdpPcb; - bool m_bOverrideRdpPerf; - bool m_bOverrideRdpNowallp; - bool m_bOverrideRdpNowdrag; - bool m_bOverrideRdpNomani; - bool m_bOverrideRdpNotheme; - bool m_bOverrideRdpNotls; - bool m_bOverrideRdpNonla; - bool m_bOverrideRdpFntlm; - string m_sRdpOverrideHost; - string m_sRdpOverrideUser; - string m_sRdpOverridePass; - string m_sRdpOverridePcb; - WsRdpParams m_RdpOverrideParams; string m_sConfigFile; boost::property_tree::ptree m_ptIniConfig; bool m_bDaemon; From cd8db2e5ab0bf856b8e68b14adf0f1c626492dbc Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 22 Apr 2016 17:49:56 +0300 Subject: [PATCH 080/130] Effectuate override before connection --- wsgate/myrawsocket.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/wsgate/myrawsocket.cpp b/wsgate/myrawsocket.cpp index 8405b9f3..fc493e6c 100644 --- a/wsgate/myrawsocket.cpp +++ b/wsgate/myrawsocket.cpp @@ -61,9 +61,32 @@ namespace wsgate{ return true; } - void MyRawSocketHandler::PrepareRDP(const std::string host, const std::string pcb, const std::string user, const std::string pass, const WsRdpParams ¶ms){ + void MyRawSocketHandler::PrepareRDP(const std::string _host, const std::string _pcb, const std::string _user, const std::string _pass, const WsRdpParams &_params){ + std::string host = _host; + std::string pcb = _pcb; + std::string user = _user; + std::string pass = _pass; + WsRdpParams params = _params; + string username; string domain; + + //do needed overrides + WsRdpOverrideParams op = this->m_parent->getOverrideParams(); + if (op.m_bOverrideRdpFntlm) params.fntlm = op.m_RdpOverrideParams.fntlm; + if (op.m_bOverrideRdpNomani) params.nomani = op.m_RdpOverrideParams.nomani; + if (op.m_bOverrideRdpNonla) params.nonla = op.m_RdpOverrideParams.nonla; + if (op.m_bOverrideRdpNotheme) params.notheme = op.m_RdpOverrideParams.notheme; + if (op.m_bOverrideRdpNotls) params.notls = op.m_RdpOverrideParams.notls; + if (op.m_bOverrideRdpNowallp) params.nowallp = op.m_RdpOverrideParams.nowallp; + if (op.m_bOverrideRdpNowdrag) params.nowdrag = op.m_bOverrideRdpNowdrag; + if (op.m_bOverrideRdpPerf) params.perf = op.m_RdpOverrideParams.perf; + if (op.m_bOverrideRdpPort) params.port = op.m_RdpOverrideParams.port; + if (op.m_bOverrideRdpHost) host = op.m_sRdpOverrideHost; + if (op.m_bOverrideRdpPass) pass = op.m_sRdpOverridePass; + if (op.m_bOverrideRdpPcb) pcb = op.m_sRdpOverridePcb; + if (op.m_bOverrideRdpUser) user = op.m_sRdpOverrideUser; + SplitUserDomain(user, username, domain); rdp_ptr r = this->m_cmap[this->conn].get<2>(); @@ -79,7 +102,7 @@ namespace wsgate{ log::debug << "RDP No wallpaper: " << params.nowallp << endl; log::debug << "RDP No full windowdrag: " << params.nowdrag << endl; log::debug << "RDP No menu animation: " << params.nomani << endl; - log::debug << "RDP No theming: " << params.nomani << endl; + log::debug << "RDP No theming: " << params.notheme << endl; log::debug << "RDP Disable TLS: " << params.notls << endl; log::debug << "RDP Disable NLA: " << params.nonla << endl; log::debug << "RDP NTLM auth: " << params.fntlm << endl; From ad446154510c4379787b53d74e809ff4d955feda Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 24 Sep 2015 00:27:26 +0300 Subject: [PATCH 081/130] Setup plugin framework --- wsgate/pluginCommon.h | 16 ++++++++++++++++ wsgate/pluginTemplate/pluginExample.cpp | 5 +++++ 2 files changed, 21 insertions(+) create mode 100644 wsgate/pluginCommon.h create mode 100644 wsgate/pluginTemplate/pluginExample.cpp diff --git a/wsgate/pluginCommon.h b/wsgate/pluginCommon.h new file mode 100644 index 00000000..82991188 --- /dev/null +++ b/wsgate/pluginCommon.h @@ -0,0 +1,16 @@ +#ifndef _PLUGIN_COMMON_ +#define _PLUGIN_COMMON_ + +#define EXPORT_FUNC __declspec(dllexport) + +#include +#include + +bool entryPoint(std::map formValues, std::map & result); + +bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result){ + std::map result; + return entryPoint(std::map(), result); +} + +#endif //_PLUGIN_COMMON_ \ No newline at end of file diff --git a/wsgate/pluginTemplate/pluginExample.cpp b/wsgate/pluginTemplate/pluginExample.cpp new file mode 100644 index 00000000..c8d8371b --- /dev/null +++ b/wsgate/pluginTemplate/pluginExample.cpp @@ -0,0 +1,5 @@ +#include "../pluginCommon.h" + +bool entryPoint(std::map formValues, std::map & result){ + return true; +} \ No newline at end of file From 2556e2368cd9c4dff5ce036848fd338975e69d64 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 28 Sep 2015 15:03:55 -0700 Subject: [PATCH 082/130] Added link splitting for plugin --- wsgate/pluginCommon.h | 36 ++++++++++++++++++++++--- wsgate/pluginTemplate/pluginExample.cpp | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/wsgate/pluginCommon.h b/wsgate/pluginCommon.h index 82991188..1db8a258 100644 --- a/wsgate/pluginCommon.h +++ b/wsgate/pluginCommon.h @@ -5,12 +5,42 @@ #include #include +#include +#include + bool entryPoint(std::map formValues, std::map & result); +void split(std::string input, std::vector& tokens, char delim){ + std::stringstream stream(input); + std::string token; + while (std::getline(stream, token, delim)){ + tokens.push_back(token); + } +} + bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result){ - std::map result; - return entryPoint(std::map(), result); + std::map params; + //split the link in link body and parameter body + std::vector trims; + split(queryInput, trims, '?'); + //split parameters + std::vector tokens; + split(trims[1], tokens, '&'); + for (int i = 0; i < tokens.size(); i++){ + //split by name and value + std::vector splits; + split(tokens[i], splits, '='); + //test is value exists + if (splits.size() == 1){ + params[splits[0]] = std::string(); + } + else{ + params[splits[0]] = splits[1]; + } + splits.resize(0); + } + return entryPoint(params, result); } -#endif //_PLUGIN_COMMON_ \ No newline at end of file +#endif //_PLUGIN_COMMON_ diff --git a/wsgate/pluginTemplate/pluginExample.cpp b/wsgate/pluginTemplate/pluginExample.cpp index c8d8371b..5fbc1c73 100644 --- a/wsgate/pluginTemplate/pluginExample.cpp +++ b/wsgate/pluginTemplate/pluginExample.cpp @@ -2,4 +2,4 @@ bool entryPoint(std::map formValues, std::map & result){ return true; -} \ No newline at end of file +} From c17e25fb7292f15e67ab5d73f29cab9c76f67936 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 28 Sep 2015 15:48:37 -0700 Subject: [PATCH 083/130] Moved common to pluginTemplate --- wsgate/{ => pluginTemplate}/pluginCommon.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wsgate/{ => pluginTemplate}/pluginCommon.h (100%) diff --git a/wsgate/pluginCommon.h b/wsgate/pluginTemplate/pluginCommon.h similarity index 100% rename from wsgate/pluginCommon.h rename to wsgate/pluginTemplate/pluginCommon.h From 1cad712e22e774ee6c064371e54a3043c79dc267 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 28 Sep 2015 15:59:01 -0700 Subject: [PATCH 084/130] Moved code from .h --- wsgate/pluginTemplate/pluginCommon.cpp | 33 +++++++++++++++++++++++++ wsgate/pluginTemplate/pluginCommon.h | 32 +----------------------- wsgate/pluginTemplate/pluginExample.cpp | 2 +- 3 files changed, 35 insertions(+), 32 deletions(-) create mode 100644 wsgate/pluginTemplate/pluginCommon.cpp diff --git a/wsgate/pluginTemplate/pluginCommon.cpp b/wsgate/pluginTemplate/pluginCommon.cpp new file mode 100644 index 00000000..8882f655 --- /dev/null +++ b/wsgate/pluginTemplate/pluginCommon.cpp @@ -0,0 +1,33 @@ +#include "pluginCommon.h" + +void split(std::string input, std::vector& tokens, char delim){ + std::stringstream stream(input); + std::string token; + while (std::getline(stream, token, delim)){ + tokens.push_back(token); + } +} + +bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result){ + std::map params; + //split the link in link body and parameter body + std::vector trims; + split(queryInput, trims, '?'); + //split parameters + std::vector tokens; + split(trims[1], tokens, '&'); + for (int i = 0; i < tokens.size(); i++){ + //split by name and value + std::vector splits; + split(tokens[i], splits, '='); + //test is value exists + if (splits.size() == 1){ + params[splits[0]] = std::string(); + } + else{ + params[splits[0]] = splits[1]; + } + splits.resize(0); + } + return entryPoint(params, result); +} \ No newline at end of file diff --git a/wsgate/pluginTemplate/pluginCommon.h b/wsgate/pluginTemplate/pluginCommon.h index 1db8a258..9c94e1e3 100644 --- a/wsgate/pluginTemplate/pluginCommon.h +++ b/wsgate/pluginTemplate/pluginCommon.h @@ -11,36 +11,6 @@ bool entryPoint(std::map formValues, std::map & result); -void split(std::string input, std::vector& tokens, char delim){ - std::stringstream stream(input); - std::string token; - while (std::getline(stream, token, delim)){ - tokens.push_back(token); - } -} - -bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result){ - std::map params; - //split the link in link body and parameter body - std::vector trims; - split(queryInput, trims, '?'); - //split parameters - std::vector tokens; - split(trims[1], tokens, '&'); - for (int i = 0; i < tokens.size(); i++){ - //split by name and value - std::vector splits; - split(tokens[i], splits, '='); - //test is value exists - if (splits.size() == 1){ - params[splits[0]] = std::string(); - } - else{ - params[splits[0]] = splits[1]; - } - splits.resize(0); - } - return entryPoint(params, result); -} +extern "C" bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result); #endif //_PLUGIN_COMMON_ diff --git a/wsgate/pluginTemplate/pluginExample.cpp b/wsgate/pluginTemplate/pluginExample.cpp index 5fbc1c73..fc03414f 100644 --- a/wsgate/pluginTemplate/pluginExample.cpp +++ b/wsgate/pluginTemplate/pluginExample.cpp @@ -1,4 +1,4 @@ -#include "../pluginCommon.h" +#include "pluginCommon.h" bool entryPoint(std::map formValues, std::map & result){ return true; From 84c0abe12c99bdddd413249e4009ca93381e6a2c Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 28 Sep 2015 16:44:40 -0700 Subject: [PATCH 085/130] Definition of pluginManager --- wsgate/pluginManager.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 wsgate/pluginManager.h diff --git a/wsgate/pluginManager.h b/wsgate/pluginManager.h new file mode 100644 index 00000000..3add4110 --- /dev/null +++ b/wsgate/pluginManager.h @@ -0,0 +1,27 @@ +#ifndef _PLUGIN_MANAGER_ +#define _PLUGIN_MANAGER_ + +#include +#define LIBHANDLER HMODULE + +#include +#include +#include + +typedef bool(*queryPluginFUNC)(std::string, std::map&); + +class PluginManager { +public: + PluginManager* getInstance(); + void shutDown(); + bool queryPlugins(std::string query, std::map& output); +private: + std::vector listPlugins(); + void loadPlugins(); + std::vector functionPointers; + PluginManager(); + ~PluginManager(); + + std::vector pluginHandles; +}; +#endif //_PLUGIN_MANAGER_ \ No newline at end of file From 8fce8ea60de69f88ed2a9ac734377b88330bd5a8 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 28 Sep 2015 23:37:26 -0700 Subject: [PATCH 086/130] Implementation for pluginManager --- wsgate/pluginManager.cpp | 100 +++++++++++++++++++++++++++++++++++++++ wsgate/pluginManager.h | 9 +++- 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 wsgate/pluginManager.cpp diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp new file mode 100644 index 00000000..178bef2b --- /dev/null +++ b/wsgate/pluginManager.cpp @@ -0,0 +1,100 @@ +#include "pluginManager.h" +#include + +PluginManager* PluginManager::instance = NULL; + +PluginManager::PluginManager(){ + this->loadPlugins(false); +} + +PluginManager::~PluginManager(){ + this->loadPlugins(true); +} + +void PluginManager::loadPlugins(bool orUnload){ + if (!orUnload){ + std::vector files; + listPlugins("./plugins/*", files); + for (int i = 0; i < files.size(); i++){ + queryPluginFUNC func = this->loadPlugin(files[i]); + if (func != NULL){ + functionPointers.push_back(func); + } + } + } + //unload + else{ + for (int i = 0; i < pluginHandles.size(); i++){ + unloadPlugin(pluginHandles[i]); + } + } +} + +PluginManager* PluginManager::getInstance(){ + if (PluginManager::instance == NULL) + PluginManager::instance = new PluginManager(); + return PluginManager::instance; +} + +bool PluginManager::queryPlugins(std::string query, std::map& output){ + bool result = false; + for (int i = 0; i < functionPointers.size(); i++){ + result |= functionPointers[i](query, output); + } + return result; +} + +//TODO will not work with unicode +#define string2LPCSTR(str) (LPCSTR)std::wstring( str .begin(), str .end()).c_str() + +queryPluginFUNC PluginManager::loadPlugin(std::string fileName){ + LIBHANDLER handle = LoadLibrary(string2LPCSTR(fileName)); + if (handle != NULL){ + queryPluginFUNC function = (queryPluginFUNC)GetProcAddress(handle, "queryPlugin"); + if (function != NULL){ + wsgate::logger::debug << "Found plugin " << fileName << std::endl; + pluginHandles.push_back(handle); + functionPointers.push_back(function); + } + else{ + FreeLibrary(handle); + wsgate::logger::err << "Error getting function pointer to \"queryPlugin\" in " << fileName << std::endl; + } + } + else{ + wsgate::logger::err << "Error loading plugin " << fileName << std::endl; + } + return 0; +} + +void PluginManager::unloadPlugin(LIBHANDLER handle){ + FreeLibrary(handle); +} + +void PluginManager::listPlugins(std::string findPath, std::vector& pluginFileNames){ + WIN32_FIND_DATA file; + size_t length_of_arg; + HANDLE findHandle = INVALID_HANDLE_VALUE; + DWORD dwError = 0; + + findHandle = FindFirstFile(string2LPCSTR(findPath), &file); + + if (findHandle == INVALID_HANDLE_VALUE) + { + wsgate::logger::err << "Bad find path." << std::endl; + } + + do + { + if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + //TODO find recursively + } + else + { + pluginFileNames.push_back(std::string(file.cFileName)); + } + } while (FindNextFile(findHandle, &file) != 0); + + FindClose(findHandle); +} diff --git a/wsgate/pluginManager.h b/wsgate/pluginManager.h index 3add4110..bb6c6db6 100644 --- a/wsgate/pluginManager.h +++ b/wsgate/pluginManager.h @@ -1,6 +1,8 @@ #ifndef _PLUGIN_MANAGER_ #define _PLUGIN_MANAGER_ +#include "logging.hpp" + #include #define LIBHANDLER HMODULE @@ -16,8 +18,11 @@ class PluginManager { void shutDown(); bool queryPlugins(std::string query, std::map& output); private: - std::vector listPlugins(); - void loadPlugins(); + static PluginManager* instance; + void listPlugins(std::string findPath, std::vector& pluginFileNames); + void loadPlugins(bool orUnload); + queryPluginFUNC loadPlugin(std::string fileName); + void unloadPlugin(LIBHANDLER handle); std::vector functionPointers; PluginManager(); ~PluginManager(); From 0b1bf1bdffff4a16d9546b27ead5224f36708765 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 01:38:48 -0700 Subject: [PATCH 087/130] Fixed pluginManager --- wsgate/pluginManager.cpp | 37 +++++++++++++++++++++++++------------ wsgate/pluginManager.h | 6 +++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 178bef2b..8890fa91 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -1,5 +1,6 @@ #include "pluginManager.h" #include +#include PluginManager* PluginManager::instance = NULL; @@ -11,15 +12,16 @@ PluginManager::~PluginManager(){ this->loadPlugins(true); } +void PluginManager::shutDown(){ + delete PluginManager::instance; +} + void PluginManager::loadPlugins(bool orUnload){ if (!orUnload){ std::vector files; - listPlugins("./plugins/*", files); + listPlugins("plugins\\", files); for (int i = 0; i < files.size(); i++){ - queryPluginFUNC func = this->loadPlugin(files[i]); - if (func != NULL){ - functionPointers.push_back(func); - } + loadPlugin(files[i]); } } //unload @@ -44,10 +46,14 @@ bool PluginManager::queryPlugins(std::string query, std::map& size_t length_of_arg; HANDLE findHandle = INVALID_HANDLE_VALUE; DWORD dwError = 0; - - findHandle = FindFirstFile(string2LPCSTR(findPath), &file); + std::string path(getexepath()); + //find path delimiter + int n = path.length(); + int i = n - 1; + while (path[i] != '\\') i--; + path.erase(i + 1, n); + path += findPath; + findPath = path; + findHandle = FindFirstFile(string2LPCSTR((findPath + "*.dll")), &file); if (findHandle == INVALID_HANDLE_VALUE) { wsgate::logger::err << "Bad find path." << std::endl; + return; } do @@ -92,7 +105,7 @@ void PluginManager::listPlugins(std::string findPath, std::vector& } else { - pluginFileNames.push_back(std::string(file.cFileName)); + pluginFileNames.push_back(findPath + std::string(file.cFileName)); } } while (FindNextFile(findHandle, &file) != 0); diff --git a/wsgate/pluginManager.h b/wsgate/pluginManager.h index bb6c6db6..72a92296 100644 --- a/wsgate/pluginManager.h +++ b/wsgate/pluginManager.h @@ -14,14 +14,14 @@ typedef bool(*queryPluginFUNC)(std::string, std::map&) class PluginManager { public: - PluginManager* getInstance(); - void shutDown(); + static PluginManager* getInstance(); + static void shutDown(); bool queryPlugins(std::string query, std::map& output); private: static PluginManager* instance; void listPlugins(std::string findPath, std::vector& pluginFileNames); void loadPlugins(bool orUnload); - queryPluginFUNC loadPlugin(std::string fileName); + void loadPlugin(std::string fileName); void unloadPlugin(LIBHANDLER handle); std::vector functionPointers; PluginManager(); From 7718872520173fa8927e7653fa013f5fa0c754a0 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 19:00:39 -0700 Subject: [PATCH 088/130] Added Openstack plugin --- wsgate/pluginOpenstack/pluginOpenstack.cpp | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 wsgate/pluginOpenstack/pluginOpenstack.cpp diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp new file mode 100644 index 00000000..0156fb15 --- /dev/null +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -0,0 +1,5 @@ +#include "../pluginTemplate/pluginCommon.h" + +bool entryPoint(std::map formValues, std::map & result){ + return true; +} \ No newline at end of file From e292fc79841d4561debf49d84f5a8813578d8726 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 19:26:34 -0700 Subject: [PATCH 089/130] Added code for Openstack --- wsgate/pluginOpenstack/pluginOpenstack.cpp | 49 +++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 0156fb15..ec19571f 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -1,5 +1,52 @@ #include "../pluginTemplate/pluginCommon.h" +#include +#include bool entryPoint(std::map formValues, std::map & result){ - return true; + bool returnValue = false; + std::string debugStr; + std::string errStr; + std::stringstream debug(debugStr); + std::stringstream err(errStr); + + if (formValues.count("wsgate") && formValues.count("token")) + { + // OpenStack console authentication + try + { + debug << "Starting OpenStack token authentication" << std::endl; + + std::string tokenId = formValues["token"]; + + nova_console_token_auth* token_auth = nova_console_token_auth_factory::get_instance(); + + nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, + m_sOpenStackPassword, m_sOpenStackTenantName, + tokenId); + + debug << "Host: " << info.host << " Port: " << info.port + << " Internal access path: " << info.internal_access_path + << std::endl; + + result["rdphost"] = info.host; + result["rdpport"] = info.port; + result["rdppcb"] = info.internal_access_path; + + result["rdpuser"] = m_sHyperVHostUsername; + result["rdppass"] = m_sHyperVHostPassword; + + returnValue = true; + } + catch (std::exception& ex) + { + err << "OpenStack token authentication failed: " << ex.what() << std::endl; + returnValue = false; + } + } + else{ + returnValue = false; + } + result["err"] = result["err"] + errStr; + result["debug"] = result["debug"] + debugStr; + return returnValue; } \ No newline at end of file From f16d2bdb1aa35fb033768dc4dde921593e6da9c0 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:05:46 -0700 Subject: [PATCH 090/130] Removed Nova code --- wsgate/wsgateEHS.cpp | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index fd4998c3..f9d9e6c6 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -1,5 +1,6 @@ #include "wsgateEHS.hpp" #include "wsgate.hpp" +#include "pluginManager.h" namespace wsgate{ WsGate::MimeType WsGate::simpleMime(const string & filename) @@ -273,40 +274,17 @@ namespace wsgate{ bool setCookie = true; EmbeddedContext embeddedContext = CONTEXT_PLAIN; - if(boost::starts_with(uri, "/wsgate?token=")) - { - // OpenStack console authentication + std::map pluginOutput; + if (PluginManager::getInstance()->queryPlugins(uri, pluginOutput)){ + //wsgate will get auth info from the plugin setCookie = false; - try - { - log::info << "Starting OpenStack token authentication" << endl; - - string tokenId = request->FormValues("token").m_sBody; - - nova_console_token_auth* token_auth = nova_console_token_auth_factory::get_instance(); - - nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, - m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId); - - log::info << "Host: " << info.host << " Port: " << info.port - << " Internal access path: " << info.internal_access_path - << endl; + embeddedContext = CONTEXT_EMBEDDED; - rdphost = info.host; - rdpport = info.port; - rdppcb = info.internal_access_path; - - rdpuser = m_sHyperVHostUsername; - rdppass = m_sHyperVHostPassword; - - embeddedContext = CONTEXT_EMBEDDED; - } - catch(exception& ex) - { - log::err << "OpenStack token authentication failed: " << ex.what() << endl; - return HTTPRESPONSECODE_400_BADREQUEST; - } + rdphost = pluginOutput["rdphost"]; + rdpport = std::stoi(pluginOutput["rdpport"]); + rdppcb = pluginOutput["rdppcb"]; + rdpuser = pluginOutput["rdpuser"]; + rdppass = pluginOutput["rdppass"]; } params = From 0016dfd47eaf5311b7277e6e47472fc451aa049b Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:11:30 -0700 Subject: [PATCH 091/130] Moved nova code to the plugin --- wsgate/{ => pluginOpenstack}/nova_token_auth.cpp | 0 wsgate/{ => pluginOpenstack}/nova_token_auth.hpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename wsgate/{ => pluginOpenstack}/nova_token_auth.cpp (100%) rename wsgate/{ => pluginOpenstack}/nova_token_auth.hpp (100%) diff --git a/wsgate/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp similarity index 100% rename from wsgate/nova_token_auth.cpp rename to wsgate/pluginOpenstack/nova_token_auth.cpp diff --git a/wsgate/nova_token_auth.hpp b/wsgate/pluginOpenstack/nova_token_auth.hpp similarity index 100% rename from wsgate/nova_token_auth.hpp rename to wsgate/pluginOpenstack/nova_token_auth.hpp From ffd45df255cf568fda85c5f2844ff3f04c2165c7 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:13:51 -0700 Subject: [PATCH 092/130] Removed nova include --- wsgate/wsgateEHS.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index 10054d7e..25cde2e3 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -36,7 +36,6 @@ #include "logging.hpp" #include "wsendpoint.hpp" #include "myrawsocket.hpp" -#include "nova_token_auth.hpp" using namespace std; using boost::algorithm::iequals; From bec481285315dac251f662589e2d64d74ab2d6ff Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:17:09 -0700 Subject: [PATCH 093/130] Included nova in plugin --- wsgate/pluginOpenstack/pluginOpenstack.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index ec19571f..42fd86c8 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -1,7 +1,10 @@ #include "../pluginTemplate/pluginCommon.h" +#include "nova_token_auth.hpp" #include #include +using namespace wsgate; + bool entryPoint(std::map formValues, std::map & result){ bool returnValue = false; std::string debugStr; From f0e7228f76e318edb05a5f91b9e6d6b88e495937 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:19:20 -0700 Subject: [PATCH 094/130] Send config file to the plugins --- wsgate/wsgateEHS.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index f9d9e6c6..53caeb05 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -275,6 +275,7 @@ namespace wsgate{ EmbeddedContext embeddedContext = CONTEXT_PLAIN; std::map pluginOutput; + pluginOutput["configfile"] = m_sConfigFile; if (PluginManager::getInstance()->queryPlugins(uri, pluginOutput)){ //wsgate will get auth info from the plugin setCookie = false; From 9f67ed65e5e6affeea0ae80986a976ae0c5d0593 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 29 Sep 2015 20:49:21 -0700 Subject: [PATCH 095/130] Added openstack ini parsing --- wsgate/pluginOpenstack/pluginOpenstack.cpp | 127 +++++++++++++++++---- 1 file changed, 102 insertions(+), 25 deletions(-) diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 42fd86c8..1a9c65d7 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -2,9 +2,85 @@ #include "nova_token_auth.hpp" #include #include +#include +#include +#include using namespace wsgate; +std::string m_sOpenStackAuthUrl; +std::string m_sOpenStackUsername; +std::string m_sOpenStackPassword; +std::string m_sOpenStackTenantName; +std::string m_sHyperVHostUsername; +std::string m_sHyperVHostPassword; + +bool readConfigFile(std::map & result){ + std::string errStr; + std::stringstream err(errStr); + bool returnValue = false; + + if (result.count["configfile"]){ + try { + boost::property_tree::ptree pt; + boost::property_tree::ini_parser::read_ini(result["configfile"], pt); + + try { + if (pt.get_optional("openstack.authurl")) { + m_sOpenStackAuthUrl.assign(pt.get("openstack.authurl")); + } + else { + m_sOpenStackAuthUrl.clear(); + } + if (pt.get_optional("openstack.username")) { + m_sOpenStackUsername.assign(pt.get("openstack.username")); + } + else { + m_sOpenStackUsername.clear(); + } + if (pt.get_optional("openstack.password")) { + m_sOpenStackPassword.assign(pt.get("openstack.password")); + } + else { + m_sOpenStackPassword.clear(); + } + if (pt.get_optional("openstack.tenantname")) { + m_sOpenStackTenantName.assign(pt.get("openstack.tenantname")); + } + else { + m_sOpenStackTenantName.clear(); + } + if (pt.get_optional("hyperv.hostusername")) { + m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); + } + else { + m_sHyperVHostUsername.clear(); + } + if (pt.get_optional("hyperv.hostpassword")) { + m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); + } + else { + m_sHyperVHostPassword.clear(); + } + returnValue = true; + } + catch (const std::exception & e) { + err << e.what() << std::endl; + err << e.what() << std::endl; + } + + } + catch (const boost::property_tree::ini_parser_error &e) { + err << e.what() << std::endl; + } + } + else{ + err << "Plugin got no config file path" << std::endl; + } + result["err"] = result["err"] + errStr; + return returnValue; +} + bool entryPoint(std::map formValues, std::map & result){ bool returnValue = false; std::string debugStr; @@ -12,42 +88,43 @@ bool entryPoint(std::map formValues, std::mapget_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, - m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId); + nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, + m_sOpenStackPassword, m_sOpenStackTenantName, + tokenId); - debug << "Host: " << info.host << " Port: " << info.port - << " Internal access path: " << info.internal_access_path - << std::endl; + debug << "Host: " << info.host << " Port: " << info.port + << " Internal access path: " << info.internal_access_path + << std::endl; - result["rdphost"] = info.host; - result["rdpport"] = info.port; - result["rdppcb"] = info.internal_access_path; + result["rdphost"] = info.host; + result["rdpport"] = info.port; + result["rdppcb"] = info.internal_access_path; - result["rdpuser"] = m_sHyperVHostUsername; - result["rdppass"] = m_sHyperVHostPassword; + result["rdpuser"] = m_sHyperVHostUsername; + result["rdppass"] = m_sHyperVHostPassword; - returnValue = true; - } - catch (std::exception& ex) - { - err << "OpenStack token authentication failed: " << ex.what() << std::endl; - returnValue = false; + returnValue = true; + } + catch (std::exception& ex) + { + err << "OpenStack token authentication failed: " << ex.what() << std::endl; + } } } else{ - returnValue = false; + err << "Error parsing config file." << std::endl; } result["err"] = result["err"] + errStr; result["debug"] = result["debug"] + debugStr; From 2af0d853e065f7d37863764aad96e083363212fb Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 1 Oct 2015 02:18:38 -0700 Subject: [PATCH 096/130] Verify if the URI contains parameters --- wsgate/wsgateEHS.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index 53caeb05..c808f125 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -274,18 +274,20 @@ namespace wsgate{ bool setCookie = true; EmbeddedContext embeddedContext = CONTEXT_PLAIN; - std::map pluginOutput; - pluginOutput["configfile"] = m_sConfigFile; - if (PluginManager::getInstance()->queryPlugins(uri, pluginOutput)){ - //wsgate will get auth info from the plugin - setCookie = false; - embeddedContext = CONTEXT_EMBEDDED; - - rdphost = pluginOutput["rdphost"]; - rdpport = std::stoi(pluginOutput["rdpport"]); - rdppcb = pluginOutput["rdppcb"]; - rdpuser = pluginOutput["rdpuser"]; - rdppass = pluginOutput["rdppass"]; + if (boost::contains(uri, "?")){ + std::map pluginOutput; + pluginOutput["configfile"] = m_sConfigFile; + if (PluginManager::getInstance()->queryPlugins(uri, pluginOutput)){ + //wsgate will get auth info from the plugin + setCookie = false; + embeddedContext = CONTEXT_EMBEDDED; + + rdphost = pluginOutput["rdphost"]; + rdpport = std::stoi(pluginOutput["rdpport"]); + rdppcb = pluginOutput["rdppcb"]; + rdpuser = pluginOutput["rdpuser"]; + rdppass = pluginOutput["rdppass"]; + } } params = From 33b6ae11fd12eccb6f59f0e4e5be2976bfe0d5a3 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 7 Oct 2015 21:46:20 +0300 Subject: [PATCH 097/130] Fixed runtime errors --- wsgate/pluginOpenstack/nova_token_auth.cpp | 14 +++++++------- wsgate/pluginOpenstack/pluginOpenstack.cpp | 7 ++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index 5008e1e9..e90c24e3 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -82,10 +82,10 @@ json::value nova_console_token_auth_impl::get_auth_token_data( auto jsonRequestBody = json::value::object(); auto auth = json::value::object(); auto cred = json::value::object(); - cred[U("username")] = json::value::string(to_string_t(osUserName)); - cred[U("password")] = json::value::string(to_string_t(osPassword)); + cred[U("username")] = json::value::string(utility::conversions::to_string_t(osUserName)); + cred[U("password")] = json::value::string(utility::conversions::to_string_t(osPassword)); auth[U("passwordCredentials")] = cred; - auth[U("tenantName")] = json::value::string(to_string_t(osTenantName)); + auth[U("tenantName")] = json::value::string(utility::conversions::to_string_t(osTenantName)); jsonRequestBody[U("auth")] = auth; http::http_request request(http::methods::POST); request.set_request_uri(U("tokens")); @@ -93,21 +93,21 @@ json::value nova_console_token_auth_impl::get_auth_token_data( request.headers().set_content_type(U("application/json")); request.set_body(jsonRequestBody); - http::client::http_client client(to_string_t(osAuthUrl)); + http::client::http_client client(utility::conversions::to_string_t(osAuthUrl)); return execute_request_and_get_json_value(client, request); } json::value nova_console_token_auth_impl::get_console_token_data( string authToken, string novaUrl, string consoleToken) { - http::client::http_client client(to_string_t(novaUrl)); + http::client::http_client client(utility::conversions::to_string_t(novaUrl)); http::uri_builder console_token_uri; console_token_uri.append(U("os-console-auth-tokens")); - console_token_uri.append(to_string_t(consoleToken)); + console_token_uri.append(utility::conversions::to_string_t(consoleToken)); http::http_request request(http::methods::GET); request.set_request_uri(console_token_uri.to_string()); - request.headers().add(U("X-Auth-Token"), to_string_t(authToken)); + request.headers().add(U("X-Auth-Token"), utility::conversions::to_string_t(authToken)); request.headers().add(http::header_names::accept, U("application/json")); request.headers().set_content_type(U("application/json")); diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 1a9c65d7..5241422f 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace wsgate; @@ -20,7 +21,7 @@ bool readConfigFile(std::map & result){ std::stringstream err(errStr); bool returnValue = false; - if (result.count["configfile"]){ + if (result.count("configfile")){ try { boost::property_tree::ptree pt; boost::property_tree::ini_parser::read_ini(result["configfile"], pt); @@ -89,7 +90,7 @@ bool entryPoint(std::map formValues, std::map formValues, std::map(info.port); result["rdppcb"] = info.internal_access_path; result["rdpuser"] = m_sHyperVHostUsername; From 78be2884fa8d38be112ee488843b03feb2c80b61 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 9 Oct 2015 17:20:11 +0300 Subject: [PATCH 098/130] Renamed pluginManager --- wsgate/{pluginManager.h => pluginManager.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wsgate/{pluginManager.h => pluginManager.hpp} (100%) diff --git a/wsgate/pluginManager.h b/wsgate/pluginManager.hpp similarity index 100% rename from wsgate/pluginManager.h rename to wsgate/pluginManager.hpp From ef1dc6e6bb42cb64ed65b861ee11bbf47467281f Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 9 Oct 2015 17:26:13 +0300 Subject: [PATCH 099/130] Renamed include file --- wsgate/pluginManager.cpp | 2 +- wsgate/wsgateEHS.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 8890fa91..b22910cc 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -1,4 +1,4 @@ -#include "pluginManager.h" +#include "pluginManager.hpp" #include #include diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index c808f125..f084f03d 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -1,6 +1,6 @@ #include "wsgateEHS.hpp" #include "wsgate.hpp" -#include "pluginManager.h" +#include "pluginManager.hpp" namespace wsgate{ WsGate::MimeType WsGate::simpleMime(const string & filename) From 48d0a418d08ad3fb887136aa60c2b8aaa24955af Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 12 Oct 2015 17:19:37 +0300 Subject: [PATCH 100/130] Adds plugin ordered calling --- wsgate/pluginManager.cpp | 28 ++++++++++++++++++++++++++-- wsgate/pluginManager.hpp | 3 +++ wsgate/wsgateEHS.cpp | 7 +++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index b22910cc..d61dc2d8 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -1,6 +1,7 @@ #include "pluginManager.hpp" #include #include +#include PluginManager* PluginManager::instance = NULL; @@ -40,8 +41,30 @@ PluginManager* PluginManager::getInstance(){ bool PluginManager::queryPlugins(std::string query, std::map& output){ bool result = false; - for (int i = 0; i < functionPointers.size(); i++){ - result |= functionPointers[i](query, output); + //execute queries with respect to the config file + for (int i = 0; i < pluginOrder.size(); i++){ + for (int j = 0; j < pluginNames.size(); j++){ + if (boost::algorithm::ends_with(pluginNames[j], pluginOrder[i])){ + result |= functionPointers[j](query, output); + } + } + } + //execute remaining queries + for (int j = 0; j < pluginNames.size(); j++){ + if (pluginOrder.size()){ + bool found = false; + for (int i = 0; i < pluginOrder.size(); i++){ + if (boost::algorithm::ends_with(pluginNames[j], pluginOrder[i])){ + found = true; + } + } + if (!found) + result |= functionPointers[j](query, output); + } + else + { + result |= functionPointers[j](query, output); + } } return result; } @@ -61,6 +84,7 @@ void PluginManager::loadPlugin(std::string fileName){ wsgate::logger::debug << "Found plugin " << fileName << std::endl; pluginHandles.push_back(handle); functionPointers.push_back(function); + pluginNames.push_back(fileName); } else{ FreeLibrary(handle); diff --git a/wsgate/pluginManager.hpp b/wsgate/pluginManager.hpp index 72a92296..759ae0ee 100644 --- a/wsgate/pluginManager.hpp +++ b/wsgate/pluginManager.hpp @@ -17,6 +17,7 @@ class PluginManager { static PluginManager* getInstance(); static void shutDown(); bool queryPlugins(std::string query, std::map& output); + inline void setOrder(std::vector order){ pluginOrder = order; } private: static PluginManager* instance; void listPlugins(std::string findPath, std::vector& pluginFileNames); @@ -28,5 +29,7 @@ class PluginManager { ~PluginManager(); std::vector pluginHandles; + std::vector pluginOrder; + std::vector pluginNames; }; #endif //_PLUGIN_MANAGER_ \ No newline at end of file diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index f084f03d..ec7f9c5c 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -910,6 +910,13 @@ namespace wsgate{ } else { m_sHyperVHostPassword.clear(); } + + if (pt.get_optional("plugins.order")){ + std::string str = pt.get("plugins.order"); + std::vector order; + boost::split(order, str, boost::is_any_of(";")); + PluginManager::getInstance()->setOrder(order); + } } catch (const tracing::invalid_argument & e) { cerr << e.what() << endl; wsgate::log::err << e.what() << endl; From f3d3908cace9ecb52e72b397681cd2c75f8a36e3 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 12 Oct 2015 19:17:57 +0300 Subject: [PATCH 101/130] Update cmake file for wsgate --- wsgate/CMakeLists.txt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 4fd6d1a8..f9f77cec 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -365,13 +365,6 @@ set(HAVE_EHS_H 1) # add ehs to libs list set(LIBS ${LIBS} ${EHS_LIBRARIES}) -# find casablanca -find_package(Casablanca REQUIRED) -include_directories(${CASABLANCA_INCLUDE_DIR}) -# add casablanca to libs list -set(LIBS ${LIBS} ${CASABLANCA_LIBRARIES}) - - CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET) CHECK_FUNCTION_EXISTS(select HAVE_SELECT) CHECK_FUNCTION_EXISTS(setlocale HAVE_SETLOCALE) @@ -591,13 +584,13 @@ set(WSGATE_SOURCES base64.cpp btexception.cpp logging.cpp sha1.cpp wsgate_main.cpp RDP.cpp Update.cpp Primary.cpp myBindHelper.cpp myWsHandler.cpp myrawsocket.cpp wsendpoint.cpp wsgateEHS.cpp wshandler.cpp - Png.cpp nova_token_auth.cpp) + Png.cpp pluginManager.cpp) if (WIN32) set(WSGATE_SOURCES "${WSGATE_SOURCES}" NTService.cpp wsGateService.cpp) # in order for header files to appear in VS solution, add them to the sources list set(WSGATE_SOURCES "${WSGATE_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR}/config.h base64.hpp btexception.hpp common.hpp - logging.hpp myrawsocket.hpp nova_token_auth.hpp NTService.hpp + logging.hpp myrawsocket.hpp pluginManager.hpp NTService.hpp Png.hpp Primary.hpp rdpcommon.hpp RDP.hpp sha1.hpp Update.hpp wscommon.hpp wsendpoint.hpp wsframe.hpp wsgate.hpp wshandler.hpp myBindHelper.hpp myWsHandler.hpp wsGateService.hpp wsgateEHS.hpp From df226ede17201d50abbb132a92ce485788b5e818 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 12 Oct 2015 20:27:54 +0300 Subject: [PATCH 102/130] Added cmake definition for pluginOpenstack --- wsgate/pluginOpenstack/CMakeLists.txt | 57 +++++++++++++++++++ .../cmake/FindCasablanca.cmake | 0 wsgate/pluginOpenstack/config.h.cmake | 14 +++++ .../{pluginCommon.h => pluginCommon.hpp} | 0 4 files changed, 71 insertions(+) create mode 100644 wsgate/pluginOpenstack/CMakeLists.txt rename wsgate/{ => pluginOpenstack}/cmake/FindCasablanca.cmake (100%) create mode 100644 wsgate/pluginOpenstack/config.h.cmake rename wsgate/pluginTemplate/{pluginCommon.h => pluginCommon.hpp} (100%) diff --git a/wsgate/pluginOpenstack/CMakeLists.txt b/wsgate/pluginOpenstack/CMakeLists.txt new file mode 100644 index 00000000..60a9c800 --- /dev/null +++ b/wsgate/pluginOpenstack/CMakeLists.txt @@ -0,0 +1,57 @@ +#pluginOpenstack + +cmake_minimum_required(VERSION 2.8) + +project("pluginOpenstack") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../cmake/) + +# find casablanca +find_package(Casablanca REQUIRED) +include_directories(${CASABLANCA_INCLUDE_DIR}) +# add casablanca to libs list +set(LIBS ${LIBS} ${CASABLANCA_LIBRARIES}) + +# search for boost libs +set(Boost_USE_STATIC_LIBS OFF) +set(Boost_USE_MULTITHREADED ON) +set(Boost_USE_STATIC_RUNTIME OFF) +set(BOOST_ALL_DYN_LINK ON) +set(BOOST_ALL_NO_LIB ON) +find_package(Boost 1.48 REQUIRED) + +set(HAVE_BOOST 1) + +include_directories(${Boost_INCLUDE_DIR}) +link_directories(${Boost_LIBRARY_DIRS}) +set(LIBS ${LIBS} ${Boost_LIBRARIES}) + +if(WIN32) + set(_UNICODE 1) + + set(_WIN32 1) + # Minimum Windows version (XP) + SET(_WIN32_WINNT 0x0501) + # find winSDK path + find_package(WindowsSDK REQUIRED) + include_directories(${WINSDK_INCLUDE_DIRS}) + # check for headers + check_include_file(Windows.h HAVE_WINDOWS_H) + check_include_file(winsock2.h HAVE_WINSOCK2_H) +endif() + +# create config.h from config.h.cmake +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +set(PLUGINOPENSTACK_SOURCE nova_token_auth.cpp pluginOpenstack.cpp ../pluginCommon.cpp) + +if(WIN32) + set(PLUGINOPENSTACK_SOURCE nova_token_auth.hpp ../pluginCommon.hpp) +endif() + +add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) diff --git a/wsgate/cmake/FindCasablanca.cmake b/wsgate/pluginOpenstack/cmake/FindCasablanca.cmake similarity index 100% rename from wsgate/cmake/FindCasablanca.cmake rename to wsgate/pluginOpenstack/cmake/FindCasablanca.cmake diff --git a/wsgate/pluginOpenstack/config.h.cmake b/wsgate/pluginOpenstack/config.h.cmake new file mode 100644 index 00000000..f63340d2 --- /dev/null +++ b/wsgate/pluginOpenstack/config.h.cmake @@ -0,0 +1,14 @@ +/* Defined if the requested minimum BOOST version is satisfied */ +#cmakedefine HAVE_BOOST 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const 1 + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#cmakedefine inline 1 +#endif diff --git a/wsgate/pluginTemplate/pluginCommon.h b/wsgate/pluginTemplate/pluginCommon.hpp similarity index 100% rename from wsgate/pluginTemplate/pluginCommon.h rename to wsgate/pluginTemplate/pluginCommon.hpp From 2438dfdb0753ae558274bf2e70795a01e4c10596 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 14 Oct 2015 22:32:07 +0300 Subject: [PATCH 103/130] Fixed cmake file errors --- wsgate/pluginOpenstack/CMakeLists.txt | 34 ++++++++++++++++++++-- wsgate/pluginOpenstack/pluginOpenstack.cpp | 2 +- wsgate/pluginTemplate/pluginCommon.cpp | 2 +- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/wsgate/pluginOpenstack/CMakeLists.txt b/wsgate/pluginOpenstack/CMakeLists.txt index 60a9c800..c2fc2317 100644 --- a/wsgate/pluginOpenstack/CMakeLists.txt +++ b/wsgate/pluginOpenstack/CMakeLists.txt @@ -4,6 +4,15 @@ cmake_minimum_required(VERSION 2.8) project("pluginOpenstack") +set(LIBS) + +include(FindPackageHandleStandardArgs) +include(CheckIncludeFile) +include(CheckLibraryExists) +include(CheckFunctionExists) +include(CheckCXXCompilerFlag) +include(CheckTypeSize) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../cmake/) @@ -13,13 +22,19 @@ include_directories(${CASABLANCA_INCLUDE_DIR}) # add casablanca to libs list set(LIBS ${LIBS} ${CASABLANCA_LIBRARIES}) +# find winpr (part of freerdp) +find_package(WinPR REQUIRED ) +include_directories(${WINPR_INCLUDE_DIR}) +# add winpr to libs list +set(LIBS ${LIBS} ${WINPR_LIBRARIES}) + # search for boost libs set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) set(BOOST_ALL_DYN_LINK ON) set(BOOST_ALL_NO_LIB ON) -find_package(Boost 1.48 REQUIRED) +find_package(Boost 1.48 REQUIRED filesystem system) set(HAVE_BOOST 1) @@ -27,6 +42,17 @@ include_directories(${Boost_INCLUDE_DIR}) link_directories(${Boost_LIBRARY_DIRS}) set(LIBS ${LIBS} ${Boost_LIBRARIES}) +# create config.h from config.h.cmake +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +# add config.h location to include search path +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# add preprocessor definition +add_definitions(-DHAVE_CONFIG_H) +add_definitions(-DBOOST_ALL_DYN_LINK) + if(WIN32) set(_UNICODE 1) @@ -48,10 +74,12 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -set(PLUGINOPENSTACK_SOURCE nova_token_auth.cpp pluginOpenstack.cpp ../pluginCommon.cpp) +set(PLUGINOPENSTACK_SOURCE nova_token_auth.cpp pluginOpenstack.cpp ../pluginTemplate/pluginCommon.cpp) if(WIN32) - set(PLUGINOPENSTACK_SOURCE nova_token_auth.hpp ../pluginCommon.hpp) + set(PLUGINOPENSTACK_SOURCE ${PLUGINOPENSTACK_SOURCE} nova_token_auth.hpp ../pluginTemplate/pluginCommon.hpp) endif() add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) +target_link_libraries(pluginOpenstack ${LIBS}) +set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++) diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 5241422f..1e27fe85 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -1,4 +1,4 @@ -#include "../pluginTemplate/pluginCommon.h" +#include "../pluginTemplate/pluginCommon.hpp" #include "nova_token_auth.hpp" #include #include diff --git a/wsgate/pluginTemplate/pluginCommon.cpp b/wsgate/pluginTemplate/pluginCommon.cpp index 8882f655..03078d27 100644 --- a/wsgate/pluginTemplate/pluginCommon.cpp +++ b/wsgate/pluginTemplate/pluginCommon.cpp @@ -1,4 +1,4 @@ -#include "pluginCommon.h" +#include "pluginCommon.hpp" void split(std::string input, std::vector& tokens, char delim){ std::stringstream stream(input); From d15ff94e192be992359389dcc4943cf1390843e9 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 15 Oct 2015 00:58:20 +0300 Subject: [PATCH 104/130] Moved pluginOpenstack inside the same cmake file(solution) --- wsgate/CMakeLists.txt | 19 +++++ .../cmake/FindCasablanca.cmake | 0 wsgate/pluginOpenstack/CMakeLists.txt | 85 ------------------- wsgate/pluginOpenstack/config.h.cmake | 14 --- wsgate/pluginOpenstack/nova_token_auth.cpp | 3 + wsgate/pluginOpenstack/nova_token_auth.hpp | 1 - 6 files changed, 22 insertions(+), 100 deletions(-) rename wsgate/{pluginOpenstack => }/cmake/FindCasablanca.cmake (100%) delete mode 100644 wsgate/pluginOpenstack/CMakeLists.txt delete mode 100644 wsgate/pluginOpenstack/config.h.cmake diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index f9f77cec..a1225830 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -345,6 +345,12 @@ include_directories(${PNG_INCLUDE_DIR}) # add png to libs list set(LIBS ${LIBS} ${PNG_LIBRARIES}) +# find casablanca +find_package(Casablanca REQUIRED) +include_directories(${CASABLANCA_INCLUDE_DIR}) +# add casablanca to libs list +set(LIBS ${LIBS} ${CASABLANCA_LIBRARIES}) + # find freerdp find_package(FreeRDP REQUIRED) include_directories(${FREERDP_INCLUDE_DIR}) @@ -600,3 +606,16 @@ endif() add_executable(wsgate ${WSGATE_SOURCES}) target_link_libraries(wsgate ${LIBS}) + + +set(PLUGINOPENSTACK_SOURCE pluginOpenstack/nova_token_auth.cpp pluginOpenstack/pluginOpenstack.cpp pluginTemplate/pluginCommon.cpp) + +if(WIN32) + set(PLUGINOPENSTACK_SOURCE ${PLUGINOPENSTACK_SOURCE} pluginOpenstack/nova_token_auth.hpp pluginTemplate/pluginCommon.hpp config.h) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) +target_link_libraries(pluginOpenstack ${LIBS}) +set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++) diff --git a/wsgate/pluginOpenstack/cmake/FindCasablanca.cmake b/wsgate/cmake/FindCasablanca.cmake similarity index 100% rename from wsgate/pluginOpenstack/cmake/FindCasablanca.cmake rename to wsgate/cmake/FindCasablanca.cmake diff --git a/wsgate/pluginOpenstack/CMakeLists.txt b/wsgate/pluginOpenstack/CMakeLists.txt deleted file mode 100644 index c2fc2317..00000000 --- a/wsgate/pluginOpenstack/CMakeLists.txt +++ /dev/null @@ -1,85 +0,0 @@ -#pluginOpenstack - -cmake_minimum_required(VERSION 2.8) - -project("pluginOpenstack") - -set(LIBS) - -include(FindPackageHandleStandardArgs) -include(CheckIncludeFile) -include(CheckLibraryExists) -include(CheckFunctionExists) -include(CheckCXXCompilerFlag) -include(CheckTypeSize) - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../cmake/) - -# find casablanca -find_package(Casablanca REQUIRED) -include_directories(${CASABLANCA_INCLUDE_DIR}) -# add casablanca to libs list -set(LIBS ${LIBS} ${CASABLANCA_LIBRARIES}) - -# find winpr (part of freerdp) -find_package(WinPR REQUIRED ) -include_directories(${WINPR_INCLUDE_DIR}) -# add winpr to libs list -set(LIBS ${LIBS} ${WINPR_LIBRARIES}) - -# search for boost libs -set(Boost_USE_STATIC_LIBS OFF) -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_RUNTIME OFF) -set(BOOST_ALL_DYN_LINK ON) -set(BOOST_ALL_NO_LIB ON) -find_package(Boost 1.48 REQUIRED filesystem system) - -set(HAVE_BOOST 1) - -include_directories(${Boost_INCLUDE_DIR}) -link_directories(${Boost_LIBRARY_DIRS}) -set(LIBS ${LIBS} ${Boost_LIBRARIES}) - -# create config.h from config.h.cmake -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -# add config.h location to include search path -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# add preprocessor definition -add_definitions(-DHAVE_CONFIG_H) -add_definitions(-DBOOST_ALL_DYN_LINK) - -if(WIN32) - set(_UNICODE 1) - - set(_WIN32 1) - # Minimum Windows version (XP) - SET(_WIN32_WINNT 0x0501) - # find winSDK path - find_package(WindowsSDK REQUIRED) - include_directories(${WINSDK_INCLUDE_DIRS}) - # check for headers - check_include_file(Windows.h HAVE_WINDOWS_H) - check_include_file(winsock2.h HAVE_WINSOCK2_H) -endif() - -# create config.h from config.h.cmake -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -set(PLUGINOPENSTACK_SOURCE nova_token_auth.cpp pluginOpenstack.cpp ../pluginTemplate/pluginCommon.cpp) - -if(WIN32) - set(PLUGINOPENSTACK_SOURCE ${PLUGINOPENSTACK_SOURCE} nova_token_auth.hpp ../pluginTemplate/pluginCommon.hpp) -endif() - -add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) -target_link_libraries(pluginOpenstack ${LIBS}) -set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++) diff --git a/wsgate/pluginOpenstack/config.h.cmake b/wsgate/pluginOpenstack/config.h.cmake deleted file mode 100644 index f63340d2..00000000 --- a/wsgate/pluginOpenstack/config.h.cmake +++ /dev/null @@ -1,14 +0,0 @@ -/* Defined if the requested minimum BOOST version is satisfied */ -#cmakedefine HAVE_BOOST 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_WINDOWS_H 1 - -/* Define to empty if `const' does not conform to ANSI C. */ -#cmakedefine const 1 - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#cmakedefine inline 1 -#endif diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index e90c24e3..4ed5b731 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -14,6 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifdef HAVE_CONFIG_H +# include "..\config.h" +#endif #include #include diff --git a/wsgate/pluginOpenstack/nova_token_auth.hpp b/wsgate/pluginOpenstack/nova_token_auth.hpp index 45fd9c87..837a93d5 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.hpp +++ b/wsgate/pluginOpenstack/nova_token_auth.hpp @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef _NOVA_TOKEN_AUTH_ #define _NOVA_TOKEN_AUTH_ From 7ef4e64f7625bc5476fa9ba983ded6e8ec06c1f7 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 15 Oct 2015 03:29:02 +0300 Subject: [PATCH 105/130] Added Exception Handling flag for MSVC toolset --- wsgate/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index a1225830..0693fd52 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -607,7 +607,7 @@ add_executable(wsgate ${WSGATE_SOURCES}) target_link_libraries(wsgate ${LIBS}) - +#pluginOpenstack set(PLUGINOPENSTACK_SOURCE pluginOpenstack/nova_token_auth.cpp pluginOpenstack/pluginOpenstack.cpp pluginTemplate/pluginCommon.cpp) if(WIN32) @@ -618,4 +618,4 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) target_link_libraries(pluginOpenstack ${LIBS}) -set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++) +set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++ COMPILE_FLAGS "${CMAKE_CXX_FLAGS}") From f1ede62ac22426edd6e34b9fa00cc04b0cb74537 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 19 Oct 2015 13:58:51 +0300 Subject: [PATCH 106/130] Use boost for file listing --- wsgate/pluginManager.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index d61dc2d8..bd131a6b 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -2,6 +2,7 @@ #include #include #include +#include PluginManager* PluginManager::instance = NULL; @@ -101,7 +102,31 @@ void PluginManager::unloadPlugin(LIBHANDLER handle){ } void PluginManager::listPlugins(std::string findPath, std::vector& pluginFileNames){ - WIN32_FIND_DATA file; + std::string path(getexepath()); + //find path delimiter + int n = path.length(); + int i = n - 1; + while (path[i] != '\\') i--; + path.erase(i + 1, n); + path += findPath; + findPath = path; + + namespace fs = boost::filesystem; + fs::path directory(findPath); + fs::directory_iterator end; + + if (fs::exists(directory) && fs::is_directory(directory)) + { + for (fs::directory_iterator i(path); i != end; ++i) + { + if (fs::is_regular_file(i->status())) + { + pluginFileNames.push_back(i->path().string()); + } + } + } + +/* WIN32_FIND_DATA file; size_t length_of_arg; HANDLE findHandle = INVALID_HANDLE_VALUE; DWORD dwError = 0; @@ -133,5 +158,5 @@ void PluginManager::listPlugins(std::string findPath, std::vector& } } while (FindNextFile(findHandle, &file) != 0); - FindClose(findHandle); + FindClose(findHandle);*/ } From 3bce565ce227bd76251091c3a5e64a4d9574731e Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 19 Oct 2015 15:38:44 +0300 Subject: [PATCH 107/130] Removed redundant code from pluginManager --- wsgate/pluginManager.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index bd131a6b..3f2e67ef 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -52,20 +52,14 @@ bool PluginManager::queryPlugins(std::string query, std::map Date: Tue, 10 Nov 2015 22:24:06 +0200 Subject: [PATCH 108/130] Set cmake shared object variable --- wsgate/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 0693fd52..ac266d81 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -608,6 +608,7 @@ add_executable(wsgate ${WSGATE_SOURCES}) target_link_libraries(wsgate ${LIBS}) #pluginOpenstack +set(CMAKE_C++_CREATE_SHARED_LIBRARY 1) set(PLUGINOPENSTACK_SOURCE pluginOpenstack/nova_token_auth.cpp pluginOpenstack/pluginOpenstack.cpp pluginTemplate/pluginCommon.cpp) if(WIN32) From 091e96cf4e2e4b95da0fe9550e251b89c377c153 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 10 Nov 2015 22:26:32 +0200 Subject: [PATCH 109/130] Changed directory separator --- wsgate/pluginOpenstack/nova_token_auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index 4ed5b731..8306e30e 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ #ifdef HAVE_CONFIG_H -# include "..\config.h" +#include "../config.h" #endif #include From aaa1bc644cc0d1dbf035f37cf40d7441fb0d724b Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 10 Nov 2015 22:33:17 +0200 Subject: [PATCH 110/130] __declspec is WIN32 only --- wsgate/pluginTemplate/pluginCommon.cpp | 10 ++++++++-- wsgate/pluginTemplate/pluginCommon.hpp | 12 +++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/wsgate/pluginTemplate/pluginCommon.cpp b/wsgate/pluginTemplate/pluginCommon.cpp index 03078d27..8fda25b1 100644 --- a/wsgate/pluginTemplate/pluginCommon.cpp +++ b/wsgate/pluginTemplate/pluginCommon.cpp @@ -8,7 +8,13 @@ void split(std::string input, std::vector& tokens, char delim){ } } -bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result){ +#ifdef _WIN32 +bool EXPORT_FUNC +#elif +bool +#endif +queryPlugin(std::string queryInput, std::map & result) +{ std::map params; //split the link in link body and parameter body std::vector trims; @@ -30,4 +36,4 @@ bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map #include @@ -11,6 +13,14 @@ bool entryPoint(std::map formValues, std::map & result); -extern "C" bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result); +extern "C" +{ +#ifdef _WIN32 + bool EXPORT_FUNC +#elif + bool +#endif + queryPlugin(std::string queryInput, std::map & result); +} #endif //_PLUGIN_COMMON_ From 0e1cbf41097a38bc6a538798399e0a762733510d Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 11 Nov 2015 06:12:38 +0200 Subject: [PATCH 111/130] Fixed cmake issues for UNIX systems --- wsgate/CMakeLists.txt | 4 ++-- wsgate/pluginOpenstack/nova_token_auth.cpp | 2 +- wsgate/pluginTemplate/pluginCommon.cpp | 11 ++++++----- wsgate/pluginTemplate/pluginCommon.hpp | 7 +++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index ac266d81..4062ab32 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -608,8 +608,8 @@ add_executable(wsgate ${WSGATE_SOURCES}) target_link_libraries(wsgate ${LIBS}) #pluginOpenstack -set(CMAKE_C++_CREATE_SHARED_LIBRARY 1) -set(PLUGINOPENSTACK_SOURCE pluginOpenstack/nova_token_auth.cpp pluginOpenstack/pluginOpenstack.cpp pluginTemplate/pluginCommon.cpp) +#set(CMAKE_C++_CREATE_SHARED_LIBRARY 2) +set(PLUGINOPENSTACK_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/pluginOpenstack/nova_token_auth.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pluginOpenstack/pluginOpenstack.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pluginTemplate/pluginCommon.cpp) if(WIN32) set(PLUGINOPENSTACK_SOURCE ${PLUGINOPENSTACK_SOURCE} pluginOpenstack/nova_token_auth.hpp pluginTemplate/pluginCommon.hpp config.h) diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index 8306e30e..403caa5f 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ #ifdef HAVE_CONFIG_H -#include "../config.h" +#include "../build/config.h" #endif #include diff --git a/wsgate/pluginTemplate/pluginCommon.cpp b/wsgate/pluginTemplate/pluginCommon.cpp index 8fda25b1..93b518f2 100644 --- a/wsgate/pluginTemplate/pluginCommon.cpp +++ b/wsgate/pluginTemplate/pluginCommon.cpp @@ -7,13 +7,13 @@ void split(std::string input, std::vector& tokens, char delim){ tokens.push_back(token); } } - +extern "C" { #ifdef _WIN32 -bool EXPORT_FUNC -#elif -bool +bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result) +#endif +#ifndef _WIN32 +bool queryPlugin(std::string queryInput, std::map & result) #endif -queryPlugin(std::string queryInput, std::map & result) { std::map params; //split the link in link body and parameter body @@ -37,3 +37,4 @@ queryPlugin(std::string queryInput, std::map & result) } return entryPoint(params, result); } +} diff --git a/wsgate/pluginTemplate/pluginCommon.hpp b/wsgate/pluginTemplate/pluginCommon.hpp index 5f748dd1..caf857b0 100644 --- a/wsgate/pluginTemplate/pluginCommon.hpp +++ b/wsgate/pluginTemplate/pluginCommon.hpp @@ -16,11 +16,10 @@ bool entryPoint(std::map formValues, std::map & result); +#elif _UNIX + bool queryPlugin(std::string queryInput, std::map & result); #endif - queryPlugin(std::string queryInput, std::map & result); } #endif //_PLUGIN_COMMON_ From b49cb0e5ed64ad80b9332e0d3d06053e18998880 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 11 Nov 2015 08:53:48 +0200 Subject: [PATCH 112/130] Target properties are WIN32 only --- wsgate/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 4062ab32..1e13e369 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -608,7 +608,6 @@ add_executable(wsgate ${WSGATE_SOURCES}) target_link_libraries(wsgate ${LIBS}) #pluginOpenstack -#set(CMAKE_C++_CREATE_SHARED_LIBRARY 2) set(PLUGINOPENSTACK_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/pluginOpenstack/nova_token_auth.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pluginOpenstack/pluginOpenstack.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pluginTemplate/pluginCommon.cpp) if(WIN32) @@ -619,4 +618,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) target_link_libraries(pluginOpenstack ${LIBS}) -set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++ COMPILE_FLAGS "${CMAKE_CXX_FLAGS}") +if(WIN32) + set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++ COMPILE_FLAGS "${CMAKE_CXX_FLAGS}") +endif() From 1e8cd900900c9362c6309eb71e236928fcf1934f Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 16 Nov 2015 21:55:05 +0200 Subject: [PATCH 113/130] Backslash to forwardslash --- wsgate/pluginManager.cpp | 7 +++---- wsgate/pluginManager.hpp | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 3f2e67ef..a1bd819b 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -1,8 +1,7 @@ #include "pluginManager.hpp" -#include #include -#include -#include +#include +#include PluginManager* PluginManager::instance = NULL; @@ -21,7 +20,7 @@ void PluginManager::shutDown(){ void PluginManager::loadPlugins(bool orUnload){ if (!orUnload){ std::vector files; - listPlugins("plugins\\", files); + listPlugins("plugins/", files); for (int i = 0; i < files.size(); i++){ loadPlugin(files[i]); } diff --git a/wsgate/pluginManager.hpp b/wsgate/pluginManager.hpp index 759ae0ee..8d042484 100644 --- a/wsgate/pluginManager.hpp +++ b/wsgate/pluginManager.hpp @@ -3,8 +3,13 @@ #include "logging.hpp" +#ifdef _WIN32 #include #define LIBHANDLER HMODULE +#elif _UNIX +#include +#define LIBHANDLER void* +#endif #include #include @@ -32,4 +37,4 @@ class PluginManager { std::vector pluginOrder; std::vector pluginNames; }; -#endif //_PLUGIN_MANAGER_ \ No newline at end of file +#endif //_PLUGIN_MANAGER_ From faed8bd613ade42228874af41278a37605bdbc34 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 16 Nov 2015 23:12:46 +0200 Subject: [PATCH 114/130] Module path fixed --- wsgate/pluginManager.cpp | 11 +++++------ wsgate/pluginManager.hpp | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index a1bd819b..6cece26b 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -67,7 +67,11 @@ bool PluginManager::queryPlugins(std::string query, std::map& pluginFileNames){ std::string path(getexepath()); - //find path delimiter - int n = path.length(); - int i = n - 1; - while (path[i] != '\\') i--; - path.erase(i + 1, n); path += findPath; findPath = path; diff --git a/wsgate/pluginManager.hpp b/wsgate/pluginManager.hpp index 8d042484..64809fe0 100644 --- a/wsgate/pluginManager.hpp +++ b/wsgate/pluginManager.hpp @@ -6,9 +6,11 @@ #ifdef _WIN32 #include #define LIBHANDLER HMODULE -#elif _UNIX +#else #include +#include #define LIBHANDLER void* +#define MAX_PATH PATH_MAX #endif #include From 3ae465a866b6e676696bc86c3fed2013c129b425 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 17 Nov 2015 00:05:13 +0200 Subject: [PATCH 115/130] Added UNIX code --- wsgate/pluginManager.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 6cece26b..3a916d63 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -62,8 +62,9 @@ bool PluginManager::queryPlugins(std::string query, std::map& pluginFileNames){ From d7d1b938e4c017059f11839509ab703f7167a435 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 17 Nov 2015 00:35:10 +0200 Subject: [PATCH 116/130] Add DL library for UNIX --- wsgate/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 1e13e369..70b8720d 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -300,6 +300,11 @@ set(CMAKE_EXTRA_INCLUDE_FILES) # linked libraries list SET(LIBS) +#if UNIX add DL library for dynamic linking +if(UNIX) + set(LIBS ${LIBS} dl) +endif() + # if win32 use PTHREADS_WIN32 if(WIN32) From f19687fd460ae0afd9821921467a470aad46329b Mon Sep 17 00:00:00 2001 From: Cosmin Muteanu Date: Tue, 17 Nov 2015 20:51:47 +0200 Subject: [PATCH 117/130] config.h path varies on different os --- wsgate/pluginOpenstack/nova_token_auth.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index 403caa5f..46bf6f78 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -15,8 +15,12 @@ * limitations under the License. */ #ifdef HAVE_CONFIG_H +#ifdef _WIN32 +#include "../config.h" +#else #include "../build/config.h" #endif +#endif #include #include From 680dcaf3692f25743a5ea79e72a7d3bf69215024 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 27 Apr 2016 14:17:47 +0300 Subject: [PATCH 118/130] Change build path for plugins --- wsgate/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index 70b8720d..a08fe020 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -621,6 +621,9 @@ endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +#plugin should go into ./plugins/ folder +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/plugins) +#build library for openstack add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) target_link_libraries(pluginOpenstack ${LIBS}) if(WIN32) From f41474c63e897225ae68fdaed3d0ff984657dbd3 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Sat, 30 Apr 2016 04:23:23 +0300 Subject: [PATCH 119/130] Path fix for Windows --- wsgate/pluginManager.cpp | 9 +++++++++ wsgate/pluginTemplate/pluginCommon.cpp | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 3a916d63..d3dd6403 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -118,6 +118,15 @@ void PluginManager::unloadPlugin(LIBHANDLER handle){ void PluginManager::listPlugins(std::string findPath, std::vector& pluginFileNames){ std::string path(getexepath()); + //check if path ends with '/' or '\\' +#ifdef _WIN32 + if (!boost::algorithm::ends_with(path, "\\")) + path += "\\"; +#else + if (!boost::algorithm::ends_with(path, "/")) + path += "/"; +#endif + path += findPath; findPath = path; diff --git a/wsgate/pluginTemplate/pluginCommon.cpp b/wsgate/pluginTemplate/pluginCommon.cpp index 93b518f2..837ee164 100644 --- a/wsgate/pluginTemplate/pluginCommon.cpp +++ b/wsgate/pluginTemplate/pluginCommon.cpp @@ -10,8 +10,7 @@ void split(std::string input, std::vector& tokens, char delim){ extern "C" { #ifdef _WIN32 bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result) -#endif -#ifndef _WIN32 +#else bool queryPlugin(std::string queryInput, std::map & result) #endif { From 0885ac2ed4a06a968c733577d5dec46ae0a38701 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 3 May 2016 13:27:01 +0300 Subject: [PATCH 120/130] Replaced std::string with char* in plugin definition --- wsgate/pluginManager.cpp | 28 ++++++++++++++++++---- wsgate/pluginManager.hpp | 5 ++-- wsgate/pluginOpenstack/pluginOpenstack.cpp | 3 +++ wsgate/pluginTemplate/pluginCommon.cpp | 27 +++++++++++++++++---- wsgate/pluginTemplate/pluginCommon.hpp | 6 ++--- wsgate/wsgateEHS.cpp | 3 +-- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index d3dd6403..d4d56ecb 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -1,6 +1,6 @@ #include "pluginManager.hpp" #include -#include +#include #include PluginManager* PluginManager::instance = NULL; @@ -39,13 +39,16 @@ PluginManager* PluginManager::getInstance(){ return PluginManager::instance; } -bool PluginManager::queryPlugins(std::string query, std::map& output){ +bool PluginManager::queryPlugins(std::string query, std::string configFile, std::map& output){ bool result = false; //execute queries with respect to the config file for (int i = 0; i < pluginOrder.size(); i++){ for (int j = 0; j < pluginNames.size(); j++){ if (boost::algorithm::ends_with(pluginNames[j], pluginOrder[i])){ - result |= functionPointers[j](query, output); + char* buffer = new char[1024]; + result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer, 1024); + deserialize(buffer, output); + delete[] buffer; } } } @@ -57,11 +60,26 @@ bool PluginManager::queryPlugins(std::string query, std::map& output){ + std::vector pairs; + std::string input(serialized); + + boost::algorithm::split(pairs, input, boost::is_any_of("\2")); + for (int i = 0; i < pairs.size(); i++){ + std::cout << "bleh:" << pairs[i] << std::endl; + } +} + #ifdef _WIN32 #define string2LPCSTR(str) (LPCSTR)str.c_str() #endif diff --git a/wsgate/pluginManager.hpp b/wsgate/pluginManager.hpp index 64809fe0..afbe5e86 100644 --- a/wsgate/pluginManager.hpp +++ b/wsgate/pluginManager.hpp @@ -17,13 +17,13 @@ #include #include -typedef bool(*queryPluginFUNC)(std::string, std::map&); +typedef bool(*queryPluginFUNC)(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer); class PluginManager { public: static PluginManager* getInstance(); static void shutDown(); - bool queryPlugins(std::string query, std::map& output); + bool queryPlugins(std::string query, std::string configFile, std::map& output); inline void setOrder(std::vector order){ pluginOrder = order; } private: static PluginManager* instance; @@ -31,6 +31,7 @@ class PluginManager { void loadPlugins(bool orUnload); void loadPlugin(std::string fileName); void unloadPlugin(LIBHANDLER handle); + void deserialize(char* serialized, std::map& output); std::vector functionPointers; PluginManager(); ~PluginManager(); diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 1e27fe85..fd9e3573 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -117,6 +117,9 @@ bool entryPoint(std::map formValues, std::map& tokens, char delim){ } extern "C" { #ifdef _WIN32 -bool EXPORT_FUNC queryPlugin(std::string queryInput, std::map & result) +bool EXPORT_FUNC queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer) #else -bool queryPlugin(std::string queryInput, std::map & result) +bool queryPlugin(char* queryInput, char* configFile, char* resultBuffer, int max_resultBuffer) #endif { std::map params; //split the link in link body and parameter body std::vector trims; - split(queryInput, trims, '?'); + split(std::string(queryInput), trims, '?'); //split parameters std::vector tokens; split(trims[1], tokens, '&'); @@ -34,6 +34,25 @@ bool queryPlugin(std::string queryInput, std::map & re } splits.resize(0); } - return entryPoint(params, result); + + std::map result; + result["configfile"] = std::string(configFile); + + bool success = entryPoint(params, result); + + //serialize the results + std::string serialized; + for (std::map::iterator i = result.begin(); i != result.end(); i++){ + //each key-value pair is stored as + //key\1value\2 + serialized += i->first; + serialized += "\1"; + serialized += i->second; + serialized += "\2"; + } + + memcpy_s(resultBuffer, max_resultBuffer, serialized.c_str(), serialized.size() + 1); + + return success; } } diff --git a/wsgate/pluginTemplate/pluginCommon.hpp b/wsgate/pluginTemplate/pluginCommon.hpp index caf857b0..1175fa0e 100644 --- a/wsgate/pluginTemplate/pluginCommon.hpp +++ b/wsgate/pluginTemplate/pluginCommon.hpp @@ -16,9 +16,9 @@ bool entryPoint(std::map formValues, std::map & result); -#elif _UNIX - bool queryPlugin(std::string queryInput, std::map & result); + bool EXPORT_FUNC queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer); +#else + bool queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer); #endif } diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index ec7f9c5c..fba6d3f9 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -276,8 +276,7 @@ namespace wsgate{ if (boost::contains(uri, "?")){ std::map pluginOutput; - pluginOutput["configfile"] = m_sConfigFile; - if (PluginManager::getInstance()->queryPlugins(uri, pluginOutput)){ + if (PluginManager::getInstance()->queryPlugins(uri, m_sConfigFile, pluginOutput)){ //wsgate will get auth info from the plugin setCookie = false; embeddedContext = CONTEXT_EMBEDDED; From fd3e7e836f96534798abef8c14cf168c05bb6813 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 5 May 2016 17:50:01 +0300 Subject: [PATCH 121/130] Better logging for plugins --- wsgate/pluginManager.cpp | 31 ++++++++++++++++++---- wsgate/pluginManager.hpp | 3 ++- wsgate/pluginOpenstack/nova_token_auth.cpp | 1 + wsgate/pluginOpenstack/pluginOpenstack.cpp | 22 +++++++-------- wsgate/pluginTemplate/pluginCommon.cpp | 7 ++--- wsgate/pluginTemplate/pluginCommon.hpp | 4 +-- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index d4d56ecb..00c943eb 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -39,16 +39,20 @@ PluginManager* PluginManager::getInstance(){ return PluginManager::instance; } +#define PLUGIN_BUFFER_SIZE 2048 + bool PluginManager::queryPlugins(std::string query, std::string configFile, std::map& output){ bool result = false; //execute queries with respect to the config file for (int i = 0; i < pluginOrder.size(); i++){ for (int j = 0; j < pluginNames.size(); j++){ if (boost::algorithm::ends_with(pluginNames[j], pluginOrder[i])){ - char* buffer = new char[1024]; - result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer, 1024); + char* buffer = new char[PLUGIN_BUFFER_SIZE]; + result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer); deserialize(buffer, output); delete[] buffer; + + doLogging(pluginNames[j], output); } } } @@ -61,10 +65,12 @@ bool PluginManager::queryPlugins(std::string query, std::string configFile, std: } } if (!found){ - char* buffer = new char[1024]; - result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer, 1024); + char* buffer = new char[PLUGIN_BUFFER_SIZE]; + result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer); deserialize(buffer, output); delete[] buffer; + + doLogging(pluginNames[j], output); } } return result; @@ -76,7 +82,22 @@ void PluginManager::deserialize(char* serialized, std::map pair; + boost::algorithm::split(pair, pairs[i], boost::is_any_of("\1")); + if (pair.size() == 2) + if (pair[1].length() > 0){ + output[pair[0]] = pair[1]; + } + } +} + +void PluginManager::doLogging(std::string pluginName, std::map output){ + if (output.count("err")){ + wsgate::logger::err << pluginName << ":" << output["err"] << std::endl; + } + + if (output.count("debug")){ + wsgate::logger::debug << pluginName << ":" << output["debug"] << std::endl; } } diff --git a/wsgate/pluginManager.hpp b/wsgate/pluginManager.hpp index afbe5e86..96bbeedc 100644 --- a/wsgate/pluginManager.hpp +++ b/wsgate/pluginManager.hpp @@ -17,7 +17,7 @@ #include #include -typedef bool(*queryPluginFUNC)(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer); +typedef bool(*queryPluginFUNC)(const char* queryInput, const char* configFile, char* resultBuffer); class PluginManager { public: @@ -32,6 +32,7 @@ class PluginManager { void loadPlugin(std::string fileName); void unloadPlugin(LIBHANDLER handle); void deserialize(char* serialized, std::map& output); + void doLogging(std::string pluginName, std::map output); std::vector functionPointers; PluginManager(); ~PluginManager(); diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index 46bf6f78..c3a75562 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -89,6 +89,7 @@ json::value nova_console_token_auth_impl::get_auth_token_data( auto jsonRequestBody = json::value::object(); auto auth = json::value::object(); auto cred = json::value::object(); + cred[U("username")] = json::value::string(utility::conversions::to_string_t(osUserName)); cred[U("password")] = json::value::string(utility::conversions::to_string_t(osPassword)); auth[U("passwordCredentials")] = cred; diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index fd9e3573..311b63ff 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -17,8 +17,7 @@ std::string m_sHyperVHostUsername; std::string m_sHyperVHostPassword; bool readConfigFile(std::map & result){ - std::string errStr; - std::stringstream err(errStr); + std::stringstream err; bool returnValue = false; if (result.count("configfile")){ @@ -78,16 +77,14 @@ bool readConfigFile(std::map & result){ else{ err << "Plugin got no config file path" << std::endl; } - result["err"] = result["err"] + errStr; + result["err"] = result["err"] + err.str(); return returnValue; } bool entryPoint(std::map formValues, std::map & result){ bool returnValue = false; - std::string debugStr; - std::string errStr; - std::stringstream debug(debugStr); - std::stringstream err(errStr); + std::stringstream debug; + std::stringstream err; if (readConfigFile(result)){ if (formValues.count("token") && formValues.count("title")) @@ -117,9 +114,6 @@ bool entryPoint(std::map formValues, std::map formValues, std::map void split(std::string input, std::vector& tokens, char delim){ std::stringstream stream(input); @@ -9,9 +10,9 @@ void split(std::string input, std::vector& tokens, char delim){ } extern "C" { #ifdef _WIN32 -bool EXPORT_FUNC queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer, int max_resultBuffer) +bool EXPORT_FUNC queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer) #else -bool queryPlugin(char* queryInput, char* configFile, char* resultBuffer, int max_resultBuffer) +bool queryPlugin(const char* queryInput, const char* configFile, char* resultBuffer) #endif { std::map params; @@ -51,7 +52,7 @@ bool queryPlugin(char* queryInput, char* configFile, char* resultBuffer, int max serialized += "\2"; } - memcpy_s(resultBuffer, max_resultBuffer, serialized.c_str(), serialized.size() + 1); + strcpy(resultBuffer, serialized.c_str()); return success; } diff --git a/wsgate/pluginTemplate/pluginCommon.hpp b/wsgate/pluginTemplate/pluginCommon.hpp index 1175fa0e..1deb624c 100644 --- a/wsgate/pluginTemplate/pluginCommon.hpp +++ b/wsgate/pluginTemplate/pluginCommon.hpp @@ -16,9 +16,9 @@ bool entryPoint(std::map formValues, std::map Date: Fri, 6 May 2016 21:48:01 +0300 Subject: [PATCH 122/130] Trailing slash is not needed on Linux --- wsgate/pluginManager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 00c943eb..7228045a 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -161,9 +161,6 @@ void PluginManager::listPlugins(std::string findPath, std::vector& #ifdef _WIN32 if (!boost::algorithm::ends_with(path, "\\")) path += "\\"; -#else - if (!boost::algorithm::ends_with(path, "/")) - path += "/"; #endif path += findPath; From db26ef94cd79bc31ba1f79306d01c1fef4cd16d4 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 18 May 2016 00:48:08 +0300 Subject: [PATCH 123/130] Documentation on plugins --- README | 15 ++++++++++++++- wsgate/pluginTemplate/pluginExample.cpp | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/README b/README index 9fa6e9ac..9cf71ee5 100644 --- a/README +++ b/README @@ -19,4 +19,17 @@ Added automated build/install script setup-all.sh For unattended setup, installing all prereqs and deleting conflicting packages, run the script as root, specifying the following command: ./setup-all.sh -f -i -d -For addition details on the setup script and webconnect prereqs consult wsgate/README. \ No newline at end of file +For addition details on the setup script and webconnect prereqs consult wsgate/README. + + +FreeRDP-WebConnect also uses a plugin system based on shared objects that will be placed in a "plugins" subdirectory +In order to implement a new plugin, one must build a new shared library that will include the following files +/wsgate/pluginTemplate/pluginCommon.cpp +this facilitates the query parsing for easier use + +/wsgate/pluginTemplate/pluginCommon.hpp + +and also an implementation of entryPoint function as described in +/wsgate/pluginTemplate/pluginExample.cpp + +One can also follow the pluginOpenstack for reference diff --git a/wsgate/pluginTemplate/pluginExample.cpp b/wsgate/pluginTemplate/pluginExample.cpp index fc03414f..b18f14c9 100644 --- a/wsgate/pluginTemplate/pluginExample.cpp +++ b/wsgate/pluginTemplate/pluginExample.cpp @@ -1,5 +1,27 @@ #include "pluginCommon.h" bool entryPoint(std::map formValues, std::map & result){ + //to test if a field exists use formValues.count("field_name") + //to get a value for a field use formValues["field_name"] + // + //to change the RDP parameters fill the following fields + //result["rdphost"] = "127.0.0.1" + //result["rdpport"] = "12345" + //result["rdppcb"] = "pcb id" + //result["rdpuser"] = "username" + //result["rdppass"] = "password" + // + //to pass a debug message to wsgate use + //result["debug"] = "somedebug message" + // + //debug messages can be split by new line character and + //will appear as separate debug messages + //result["debug"] = "somedebug message" + "\n" + "otherdebug message" + // + //to pass an error message + //result["err"] = "error message here" + "\n" + "error message there" + // + //to take the path for the config file that WebConnect takes as "-c" parameter use + //result["configfile"] return true; } From 46d3445e232939037e23d9534225ac7e5a2e7bc6 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 8 Jun 2016 18:03:38 +0300 Subject: [PATCH 124/130] Declaration type change --- wsgate/pluginManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wsgate/pluginManager.cpp b/wsgate/pluginManager.cpp index 7228045a..f9761ef0 100644 --- a/wsgate/pluginManager.cpp +++ b/wsgate/pluginManager.cpp @@ -65,10 +65,9 @@ bool PluginManager::queryPlugins(std::string query, std::string configFile, std: } } if (!found){ - char* buffer = new char[PLUGIN_BUFFER_SIZE]; + char buffer[PLUGIN_BUFFER_SIZE]; result |= functionPointers[j](query.c_str(), configFile.c_str(), buffer); deserialize(buffer, output); - delete[] buffer; doLogging(pluginNames[j], output); } From e21d7d7673065d8b3d05903667bdd0b9661e0346 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 10 Jun 2016 23:33:12 +0300 Subject: [PATCH 125/130] Run in the same path --- wsgate/wsGateService.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wsgate/wsGateService.cpp b/wsgate/wsGateService.cpp index f2a12efb..f88ee3d1 100644 --- a/wsgate/wsGateService.cpp +++ b/wsgate/wsGateService.cpp @@ -42,15 +42,15 @@ namespace wsgate{ void WsGateService::RunService(){ WsGateService::g_signaled = false; - // On Windows, always set out working dir to ../ relatively seen from - // the binary's path. + + //change path to the running binary path p(m_sModulePath); - string wdir(p.branch_path().branch_path().string()); - chdir(wdir.c_str()); + chdir(p.branch_path().string().c_str()); + char *argv[] = { strdup("wsgate"), strdup("-c"), - strdup("etc/wsgate.ini"), + strdup("../etc/wsgate.ini"), NULL }; int r = _service_main(3, argv); From ba67aa53271e3d6793e5a179a8529ad03eebc6d6 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Thu, 23 Jun 2016 18:11:55 +0300 Subject: [PATCH 126/130] Added exception if nova endpoint is not found --- wsgate/pluginOpenstack/nova_token_auth.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wsgate/pluginOpenstack/nova_token_auth.cpp b/wsgate/pluginOpenstack/nova_token_auth.cpp index c3a75562..4e2a5cdd 100644 --- a/wsgate/pluginOpenstack/nova_token_auth.cpp +++ b/wsgate/pluginOpenstack/nova_token_auth.cpp @@ -127,6 +127,8 @@ utility::string_t nova_console_token_auth_impl::get_nova_url(web::json::value to for (auto serviceCatalog : token_data[U("access")][U("serviceCatalog")].as_array()) if (serviceCatalog[U("name")].as_string() == U("nova")) return serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + + throw std::runtime_error("Nova endpoint not found"); } nova_console_info nova_console_token_auth_impl::get_console_info( From 8113cb803db35ac3037cb6a947a4647192ff4d07 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Tue, 9 Aug 2016 01:50:31 +0300 Subject: [PATCH 127/130] Added Keystone v3 API --- wsgate/nova_token_auth.cpp | 152 ++++++++++++++++++++++++++++-------- wsgate/nova_token_auth.hpp | 6 +- wsgate/wsgate.ini.sample.in | 2 + wsgate/wsgateEHS.cpp | 8 +- wsgate/wsgateEHS.hpp | 1 + 5 files changed, 136 insertions(+), 33 deletions(-) diff --git a/wsgate/nova_token_auth.cpp b/wsgate/nova_token_auth.cpp index 5008e1e9..94958f66 100644 --- a/wsgate/nova_token_auth.cpp +++ b/wsgate/nova_token_auth.cpp @@ -27,36 +27,41 @@ using namespace web; using namespace wsgate; using namespace utility::conversions; - class nova_console_token_auth_impl : public nova_console_token_auth { private: - web::json::value execute_request_and_get_json_value( + web::http::http_response execute_request_and_get_response( web::http::client::http_client& client, web::http::http_request& request); - web::json::value get_auth_token_data(std::string osAuthUrl, - std::string osUserName, - std::string osPassword, - std::string osTenantName); + web::json::value get_json_from_response(web::http::http_response response); + + std::pair get_auth_token_data_v2(std::string osAuthUrl, + std::string osUserName, + std::string osPassword, + std::string osTenantName); + + std::pair get_auth_token_data_v3(std::string osAuthUrl, + std::string osUserName, + std::string osPassword, + std::string osTenantName); web::json::value get_console_token_data(std::string authToken, std::string novaUrl, std::string consoleToken); - utility::string_t get_nova_url(web::json::value token_data); - public: virtual nova_console_info get_console_info(std::string osAuthUrl, std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken); + std::string consoleToken, + std::string keystoneVersion); }; -json::value nova_console_token_auth_impl::execute_request_and_get_json_value( +http::http_response nova_console_token_auth_impl::execute_request_and_get_response( http::client::http_client& client, http::http_request& request) { @@ -69,13 +74,19 @@ json::value nova_console_token_auth_impl::execute_request_and_get_json_value( throw http_exception(response.status_code(), to_utf8string(response.reason_phrase())); } + return response; +} + +json::value nova_console_token_auth_impl::get_json_from_response( + http::http_response response) +{ auto json_task = response.extract_json(); json_task.wait(); return json_task.get(); } -json::value nova_console_token_auth_impl::get_auth_token_data( +std::pair nova_console_token_auth_impl::get_auth_token_data_v2( string osAuthUrl, string osUserName, string osPassword, string osTenantName) { @@ -94,7 +105,81 @@ json::value nova_console_token_auth_impl::get_auth_token_data( request.set_body(jsonRequestBody); http::client::http_client client(to_string_t(osAuthUrl)); - return execute_request_and_get_json_value(client, request); + auto response_json = get_json_from_response(execute_request_and_get_response(client, request)); + + utility::string_t authToken; + utility::string_t novaUrl; + //get the authentication token + authToken = response_json[U("access")][U("token")][U("id")].as_string(); + + //get the nova api endpoint + for (auto serviceCatalog : response_json[U("access")][U("serviceCatalog")].as_array()) + if (serviceCatalog[U("name")].as_string() == U("nova")) + novaUrl = serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + + return std::pair( + to_utf8string(authToken), + to_utf8string(novaUrl)); +} + +std::pair nova_console_token_auth_impl::get_auth_token_data_v3( + string osAuthUrl, string osUserName, + string osPassword, string osTenantName) +{ + auto jsonRequestBody = json::value::object(); + auto auth = json::value::object(); + auto identity = json::value::object(); + auto methods = json::value::array(); + methods[0] = json::value::string(to_string_t("password")); + + auto password = json::value::object(); + auto user = json::value::object(); + user[U("name")] = json::value::string(to_string_t(osUserName)); + user[U("password")] = json::value::string(to_string_t(osPassword)); + + auto domain = json::value::object(); + domain[U("id")] = json::value::string(to_string_t("default")); + + user[U("domain")] = domain; + password[U("user")] = user; + identity[U("methods")] = methods; + identity[U("password")] = password; + + auto scope = json::value::object(); + auto project = json::value::object(); + project[U("name")] = json::value::string(to_string_t(osTenantName)); + project[U("domain")] = domain; + scope[U("project")] = project; + + auth[U("identity")] = identity; + auth[U("scope")] = scope; + jsonRequestBody[U("auth")] = auth; + + http::http_request request(http::methods::POST); + request.set_request_uri(U("auth/tokens")); + request.headers().add(http::header_names::accept, U("application/json")); + request.headers().set_content_type(U("application/json")); + request.set_body(jsonRequestBody); + + http::client::http_client client(to_string_t(osAuthUrl)); + auto response = execute_request_and_get_response(client, request); + auto response_json = get_json_from_response(response); + + utility::string_t authToken; + utility::string_t novaUrl; + //get the authentication token + authToken = response.headers()[U("X-Subject-Token")]; + + //get the nova api endpoint + for (auto serviceCatalog : response_json[U("token")][U("catalog")].as_array()) + if (serviceCatalog[U("name")].as_string() == U("nova")) + for (auto endpoint : serviceCatalog[U("endpoints")].as_array()) + if (endpoint[U("interface")].as_string() == U("admin")) + novaUrl = endpoint[U("url")].as_string(); + + return std::pair( + to_utf8string(authToken), + to_utf8string(novaUrl)); } json::value nova_console_token_auth_impl::get_console_token_data( @@ -111,35 +196,40 @@ json::value nova_console_token_auth_impl::get_console_token_data( request.headers().add(http::header_names::accept, U("application/json")); request.headers().set_content_type(U("application/json")); - return execute_request_and_get_json_value(client, request); -} - -utility::string_t nova_console_token_auth_impl::get_nova_url(web::json::value token_data) -{ - for (auto serviceCatalog : token_data[U("access")][U("serviceCatalog")].as_array()) - if (serviceCatalog[U("name")].as_string() == U("nova")) - return serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + return get_json_from_response(execute_request_and_get_response(client, request)); } nova_console_info nova_console_token_auth_impl::get_console_info( std::string osAuthUrl, std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken) + std::string consoleToken, std::string keystoneVersion) { - auto token_data = get_auth_token_data(osAuthUrl, osUserName, - osPassword, osTenantName); - - auto novaUrl = get_nova_url(token_data); + std::string authToken; + std::string novaUrl; + + if (keystoneVersion == KEYSTONE_V2){ + std::tie(authToken, novaUrl) = get_auth_token_data_v2(osAuthUrl, + osUserName, + osPassword, + osTenantName); + } + else if (keystoneVersion == KEYSTONE_V3){ + std::tie(authToken, novaUrl) = get_auth_token_data_v3(osAuthUrl, + osUserName, + osPassword, + osTenantName); + } + else{ + throw std::invalid_argument("Unknown Keystone version"); + } - auto authToken = token_data[U("access")][U("token")] - [U("id")].as_string(); + nova_console_info info; - auto consoleTokenData = get_console_token_data(to_utf8string(authToken), - to_utf8string(novaUrl), + auto consoleTokenData = get_console_token_data( + authToken, + novaUrl, consoleToken); - nova_console_info info; - info.host = to_utf8string(consoleTokenData[U("console")][U("host")].as_string()); auto portValue = consoleTokenData[U("console")][U("port")]; diff --git a/wsgate/nova_token_auth.hpp b/wsgate/nova_token_auth.hpp index 45fd9c87..77111533 100644 --- a/wsgate/nova_token_auth.hpp +++ b/wsgate/nova_token_auth.hpp @@ -21,6 +21,9 @@ #include #include +#define KEYSTONE_V2 "v2.0" +#define KEYSTONE_V3 "v3" + namespace wsgate { class http_exception: public std::exception { @@ -66,7 +69,8 @@ namespace wsgate { std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken) = 0; + std::string consoleToken, + std::string keystoneVersion) = 0; }; diff --git a/wsgate/wsgate.ini.sample.in b/wsgate/wsgate.ini.sample.in index 8b9a80fc..11aca6ce 100644 --- a/wsgate/wsgate.ini.sample.in +++ b/wsgate/wsgate.ini.sample.in @@ -151,6 +151,8 @@ nofullwindowdrag = true [openstack] #authurl = http://10.0.0.1:5000/v2.0 +#Specify the version for keystone +#keystoneversion = v2.0 or v3 #username = admin #password = secret #tenantname = admin diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index fd4998c3..9e6030c2 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -287,7 +287,7 @@ namespace wsgate{ nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId); + tokenId, m_sOpenStackKeystoneVersion); log::info << "Host: " << info.host << " Port: " << info.port << " Internal access path: " << info.internal_access_path @@ -919,6 +919,12 @@ namespace wsgate{ } else { m_sOpenStackTenantName.clear(); } + if (pt.get_optional("openstack.keystoneversion")) { + m_sOpenStackKeystoneVersion.assign(pt.get("openstack.keystoneversion")); + } + else { + m_sOpenStackKeystoneVersion = KEYSTONE_V2; + } if (pt.get_optional("hyperv.hostusername")) { m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); } else { diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index ef72cefb..20924126 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -115,6 +115,7 @@ namespace wsgate{ string m_sOpenStackUsername; string m_sOpenStackPassword; string m_sOpenStackTenantName; + string m_sOpenStackKeystoneVersion; string m_sHyperVHostUsername; string m_sHyperVHostPassword; From e4492a23041aeb27f2031b9ce418a9205e9d8ea1 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Wed, 18 Jan 2017 17:15:11 +0200 Subject: [PATCH 128/130] Adds region for Openstack integration --- wsgate/nova_token_auth.cpp | 46 +++++++++++++++++++++++++++---------- wsgate/nova_token_auth.hpp | 3 ++- wsgate/wsgate.ini.sample.in | 1 + wsgate/wsgateEHS.cpp | 8 ++++++- wsgate/wsgateEHS.hpp | 1 + 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/wsgate/nova_token_auth.cpp b/wsgate/nova_token_auth.cpp index 94958f66..7c5cd061 100644 --- a/wsgate/nova_token_auth.cpp +++ b/wsgate/nova_token_auth.cpp @@ -20,6 +20,7 @@ #include #include "nova_token_auth.hpp" +#include using namespace pplx; using namespace std; @@ -39,12 +40,14 @@ class nova_console_token_auth_impl : public nova_console_token_auth std::pair get_auth_token_data_v2(std::string osAuthUrl, std::string osUserName, std::string osPassword, - std::string osTenantName); + std::string osTenantName, + std::string osRegion); std::pair get_auth_token_data_v3(std::string osAuthUrl, std::string osUserName, std::string osPassword, - std::string osTenantName); + std::string osTenantName, + std::string osRegion); web::json::value get_console_token_data(std::string authToken, std::string novaUrl, @@ -56,7 +59,8 @@ class nova_console_token_auth_impl : public nova_console_token_auth std::string osPassword, std::string osTenantName, std::string consoleToken, - std::string keystoneVersion); + std::string keystoneVersion, + std::string osRegion); }; @@ -88,7 +92,8 @@ json::value nova_console_token_auth_impl::get_json_from_response( std::pair nova_console_token_auth_impl::get_auth_token_data_v2( string osAuthUrl, string osUserName, - string osPassword, string osTenantName) + string osPassword, string osTenantName, + string osRegion) { auto jsonRequestBody = json::value::object(); auto auth = json::value::object(); @@ -114,8 +119,19 @@ std::pair nova_console_token_auth_impl::get_auth_token //get the nova api endpoint for (auto serviceCatalog : response_json[U("access")][U("serviceCatalog")].as_array()) - if (serviceCatalog[U("name")].as_string() == U("nova")) - novaUrl = serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + if (serviceCatalog[U("name")].as_string() == U("nova")){ + if (osRegion.empty()){ + novaUrl = serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + } + else{ + for (auto endpoint : serviceCatalog[U("endpoints")].as_array()){ + if (endpoint[U("region")].as_string() == to_string_t(osRegion)){ + novaUrl = endpoint[U("adminURL")].as_string(); + } + } + } + } + return std::pair( to_utf8string(authToken), @@ -124,7 +140,8 @@ std::pair nova_console_token_auth_impl::get_auth_token std::pair nova_console_token_auth_impl::get_auth_token_data_v3( string osAuthUrl, string osUserName, - string osPassword, string osTenantName) + string osPassword, string osTenantName, + string osRegion) { auto jsonRequestBody = json::value::object(); auto auth = json::value::object(); @@ -174,8 +191,10 @@ std::pair nova_console_token_auth_impl::get_auth_token for (auto serviceCatalog : response_json[U("token")][U("catalog")].as_array()) if (serviceCatalog[U("name")].as_string() == U("nova")) for (auto endpoint : serviceCatalog[U("endpoints")].as_array()) - if (endpoint[U("interface")].as_string() == U("admin")) - novaUrl = endpoint[U("url")].as_string(); + if (endpoint[U("interface")].as_string() == U("admin") && + (endpoint[U("region")].as_string() == to_string_t(osRegion) || osRegion.empty())){ + novaUrl = endpoint[U("url")].as_string(); + } return std::pair( to_utf8string(authToken), @@ -202,7 +221,8 @@ json::value nova_console_token_auth_impl::get_console_token_data( nova_console_info nova_console_token_auth_impl::get_console_info( std::string osAuthUrl, std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken, std::string keystoneVersion) + std::string consoleToken, std::string keystoneVersion, + std::string osRegion) { std::string authToken; std::string novaUrl; @@ -211,13 +231,15 @@ nova_console_info nova_console_token_auth_impl::get_console_info( std::tie(authToken, novaUrl) = get_auth_token_data_v2(osAuthUrl, osUserName, osPassword, - osTenantName); + osTenantName, + osRegion); } else if (keystoneVersion == KEYSTONE_V3){ std::tie(authToken, novaUrl) = get_auth_token_data_v3(osAuthUrl, osUserName, osPassword, - osTenantName); + osTenantName, + osRegion); } else{ throw std::invalid_argument("Unknown Keystone version"); diff --git a/wsgate/nova_token_auth.hpp b/wsgate/nova_token_auth.hpp index 77111533..d8f4332e 100644 --- a/wsgate/nova_token_auth.hpp +++ b/wsgate/nova_token_auth.hpp @@ -70,7 +70,8 @@ namespace wsgate { std::string osPassword, std::string osTenantName, std::string consoleToken, - std::string keystoneVersion) = 0; + std::string keystoneVersion, + std::string osRegion) = 0; }; diff --git a/wsgate/wsgate.ini.sample.in b/wsgate/wsgate.ini.sample.in index 11aca6ce..c4a9c938 100644 --- a/wsgate/wsgate.ini.sample.in +++ b/wsgate/wsgate.ini.sample.in @@ -156,6 +156,7 @@ nofullwindowdrag = true #username = admin #password = secret #tenantname = admin +#region = optional region [hyperv] diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index 9e6030c2..bd75806e 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -287,7 +287,7 @@ namespace wsgate{ nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId, m_sOpenStackKeystoneVersion); + tokenId, m_sOpenStackKeystoneVersion, m_sOpenStackRegion); log::info << "Host: " << info.host << " Port: " << info.port << " Internal access path: " << info.internal_access_path @@ -925,6 +925,12 @@ namespace wsgate{ else { m_sOpenStackKeystoneVersion = KEYSTONE_V2; } + if (pt.get_optional("openstack.region")) { + m_sOpenStackRegion.assign(pt.get("openstack.region")); + } + else { + m_sOpenStackRegion.clear(); + } if (pt.get_optional("hyperv.hostusername")) { m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); } else { diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index 20924126..27499e57 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -116,6 +116,7 @@ namespace wsgate{ string m_sOpenStackPassword; string m_sOpenStackTenantName; string m_sOpenStackKeystoneVersion; + string m_sOpenStackRegion; string m_sHyperVHostUsername; string m_sHyperVHostPassword; From 959d54a32020dc3862ffb196eb6ed01954eeb418 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Fri, 20 Jan 2017 16:04:21 +0200 Subject: [PATCH 129/130] Remove target properties --- wsgate/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/wsgate/CMakeLists.txt b/wsgate/CMakeLists.txt index a08fe020..976df770 100644 --- a/wsgate/CMakeLists.txt +++ b/wsgate/CMakeLists.txt @@ -626,6 +626,3 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/plugins) #build library for openstack add_library(pluginOpenstack SHARED ${PLUGINOPENSTACK_SOURCE}) target_link_libraries(pluginOpenstack ${LIBS}) -if(WIN32) - set_target_properties(pluginOpenstack PROPERTIES LINKER_LANGUAGE C++ COMPILE_FLAGS "${CMAKE_CXX_FLAGS}") -endif() From 6cb076a53dfbe9f74331129e9cdbe2c63c74e721 Mon Sep 17 00:00:00 2001 From: Cosmin Munteanu Date: Mon, 30 Jan 2017 17:10:54 +0200 Subject: [PATCH 130/130] Fixed bug where the HyperV credentials are read from config file --- wsgate/pluginOpenstack/pluginOpenstack.cpp | 21 ++++++++++++++++++++- wsgate/wsgateEHS.cpp | 10 ---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/wsgate/pluginOpenstack/pluginOpenstack.cpp b/wsgate/pluginOpenstack/pluginOpenstack.cpp index 3c4aacb4..0b8704ee 100644 --- a/wsgate/pluginOpenstack/pluginOpenstack.cpp +++ b/wsgate/pluginOpenstack/pluginOpenstack.cpp @@ -14,6 +14,7 @@ std::string m_sOpenStackUsername; std::string m_sOpenStackPassword; std::string m_sOpenStackTenantName; std::string m_sOpenStackKeystoneVersion; +std::string m_sOpenStackRegion; std::string m_sHyperVHostUsername; std::string m_sHyperVHostPassword; @@ -57,6 +58,24 @@ bool readConfigFile(std::map & result){ else { m_sOpenStackKeystoneVersion = KEYSTONE_V2; } + if (pt.get_optional("openstack.region")) { + m_sOpenStackRegion.assign(pt.get("openstack.region")); + } + else { + m_sOpenStackRegion.clear(); + } + if (pt.get_optional("hyperv.hostusername")) { + m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); + } + else { + m_sHyperVHostUsername.clear(); + } + if (pt.get_optional("hyperv.hostpassword")) { + m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); + } + else { + m_sHyperVHostPassword.clear(); + } returnValue = true; } catch (const std::exception & e) { @@ -95,7 +114,7 @@ bool entryPoint(std::map formValues, std::mapget_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId, m_sOpenStackKeystoneVersion); + tokenId, m_sOpenStackKeystoneVersion, m_sOpenStackRegion); debug << "Host: " << info.host << " Port: " << info.port << " Internal access path: " << info.internal_access_path diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index 0d4e44b0..58daa239 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -880,16 +880,6 @@ namespace wsgate{ } else { m_sHostname.clear(); } - if (pt.get_optional("hyperv.hostusername")) { - m_sHyperVHostUsername.assign(pt.get("hyperv.hostusername")); - } else { - m_sHyperVHostUsername.clear(); - } - if (pt.get_optional("hyperv.hostpassword")) { - m_sHyperVHostPassword.assign(pt.get("hyperv.hostpassword")); - } else { - m_sHyperVHostPassword.clear(); - } if (pt.get_optional("plugins.order")){ std::string str = pt.get("plugins.order");