The branch, master has been updated via ac2eeb5461e7f27cef3aaff705f690bf839bd8ce (commit) from af679ed1fd34a7a062902d8b3960efe0dcfd62f8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ac2eeb5461e7f27cef3aaff705f690bf839bd8ce Author: Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> Date: Sun Nov 11 15:51:36 2012 +0100 add classes for SSH Connection ----------------------------------------------------------------------- Summary of changes: sshconnection.cpp | 477 +++++++++++++++++++++++++++++++++++++++ sshconnection.h | 132 +++++++++++ sshconnectionguiinteraction.cpp | 170 ++++++++++++++ sshconnectionguiinteraction.h | 75 ++++++ workarea.cpp | 1 + x2goapplication.cpp | 2 + x2gobroker.cpp | 14 +- x2goclient2.pro | 4 + 8 files changed, 871 insertions(+), 4 deletions(-) create mode 100644 sshconnection.cpp create mode 100644 sshconnection.h create mode 100644 sshconnectionguiinteraction.cpp create mode 100644 sshconnectionguiinteraction.h The diff of changes is: diff --git a/sshconnection.cpp b/sshconnection.cpp new file mode 100644 index 0000000..878c66c --- /dev/null +++ b/sshconnection.cpp @@ -0,0 +1,477 @@ +/************************************************************************** +* Copyright (C) 2005-2012 by Oleksandr Shneyder * +* o.shneyder@phoca-gmbh.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "sshconnection.h" +#include "sshconnectionguiinteraction.h" + +#define PROXYTUNNELPORT 44444 + +#undef DEBUG +// #define DEBUG + +#undef SSH_DEBUG +// #define SSH_DEBUG + +#include <QDebug> +#include <QDir> +#include <QTemporaryFile> + + +#ifndef Q_OS_WIN +#include <arpa/inet.h> +#endif +#include <math.h> + +#ifndef Q_OS_WIN +#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */ +#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */ +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <qt4/QtNetwork/qabstractsocket.h> +#endif + + +bool SshConnection::isLibSshInited=false; +SshConnectionGuiInteraction* SshConnection::guiInteractor=0; + +SshConnection::SshConnection(QObject* parent, QString host, int port, bool acceptUnknownServers, + QString user, QString pass, QString key, bool autoLogin, bool krbLogin, + bool useProxy, SshConnection::ProxyType proxyType, QString proxyServer, + quint16 proxyPort, QString proxyLogin, QString proxyPassword, QString proxyKey, + bool proxyAutoLogin): QThread(parent) +{ +#if defined ( Q_OS_DARWIN ) + // Mac OS X provides only 512KB stack space for secondary threads. + // As we put a 512KB buffer on the stack later on, we need a bigger stack space. + setStackSize (sizeof (char) * 1024 * 1024 * 2); +#endif + tcpProxySocket = NULL; + tcpNetworkProxy = NULL; + sshProxy= NULL; + sshProxyReady=false; + nextPid=0; + my_ssh_session=0; + + breakLoop=false; + this->host=host; + this->port=port; + this->user=user; + this->pass=pass; + this->key=key; + this->autoLogin=autoLogin; + this->acceptUnknownServers=acceptUnknownServers; + this->useProxy=useProxy; + this->proxyType=proxyType; + this->proxyAutoLogin=proxyAutoLogin; + this->proxyKey=proxyKey; + this->proxyServer=proxyServer; + this->proxyPort=proxyPort; + this->proxyLogin=proxyLogin; + this->proxyPassword=proxyPassword; + reverseTunnel=false; + kerberos=krbLogin; + kerberos=false; + if(!guiInteractor) + { + guiInteractor=new SshConnectionGuiInteraction(parent); + } +} + +SshConnection::~SshConnection() +{ + if(my_ssh_session) + { + ssh_free(my_ssh_session); + } + qDebug()<<"ssh connection destructor"; +} + +void SshConnection::run() +{ + disconnectSessionFlag=false; + if ( !isLibSshInited ) + { + if ( ssh_init() !=0 ) + { + QString err=tr ( "Can not initialize libssh" ); + qDebug()<<err<<endl; + guiInteractor->critical(err, MessageBox::OK); + emit signalError ( CONNECTION, err ); + return; + } + isLibSshInited=true; + } + +#ifdef SSH_DEBUG + int verbosity=SSH_LOG_PACKET; +#else + int verbosity=SSH_LOG_NOLOG; +#endif + + long timeout = 60; + + my_ssh_session = ssh_new(); + if ( my_ssh_session == NULL ) + { + QString err=tr ( "Can not create ssh session" ); + qDebug()<<err<<endl; + guiInteractor->critical(err, MessageBox::OK); + emit signalError ( CONNECTION, err); + if ( reverseTunnel ) + emit signalIoError ( reverseTunnelCreator, err, "" ); + return; + } + +#ifdef Q_OS_WIN + ssh_options_set ( my_ssh_session, SSH_OPTIONS_SSH_DIR, (mainWnd->getHomeDirectory()+"/ssh").toAscii()); +#endif + ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + + ssh_options_set(my_ssh_session, SSH_OPTIONS_TIMEOUT, &timeout); + + if (useProxy && (proxyType == PROXYHTTP)) + { + socket_t proxysocket = SSH_INVALID_SOCKET; + + tcpNetworkProxy = new QNetworkProxy( QNetworkProxy::HttpProxy, + proxyServer, proxyPort, proxyLogin, proxyPassword); + tcpProxySocket = new QTcpSocket(); + tcpProxySocket->setProxy( *tcpNetworkProxy ); + tcpProxySocket->connectToHost(host, port); + proxysocket = tcpProxySocket->socketDescriptor(); + if (!tcpProxySocket->waitForConnected(30000)) + { + QString message=tr ( "Can not connect to proxy server" ); + qDebug()<<message<<endl; + guiInteractor->critical(message, MessageBox::OK); + emit signalError ( CONNECTION, message ); + ssh_free ( my_ssh_session ); + return; + } + ssh_options_set( my_ssh_session, SSH_OPTIONS_FD, &proxysocket); + ssh_set_fd_toread( my_ssh_session); + } + + if ( !sshConnect() ) + { + QString err=ssh_get_error ( my_ssh_session ); + QString message=tr ( "Can not connect to " ) +host+":"+QString::number ( port ); + message+=" - "+err; + qDebug()<<message; + guiInteractor->critical(message, MessageBox::OK); + emit signalError (CONNECTION, message); + if ( reverseTunnel ) + emit signalIoError ( reverseTunnelCreator, message, err); + ssh_free ( my_ssh_session ); + return; + } + QString errMsg; + int state=serverAuth ( errMsg ); + if ( state != SSH_SERVER_KNOWN_OK ) + { + guiInteractor->critical(errMsg, MessageBox::OK); + emit signalError (SERVERAUTH, errMsg); + ssh_disconnect ( my_ssh_session ); + ssh_free ( my_ssh_session ); + return; + } + + ssh_options_set ( my_ssh_session, SSH_OPTIONS_USER, user.toAscii() ); +#ifdef Q_OS_WIN + ssh_options_set ( my_ssh_session, SSH_OPTIONS_SSH_DIR, (QDir::homePath()+"/ssh").toAscii()); +#endif + if ( userAuth() ) + { + qDebug()<<"SSH session connected"; + emit signalConnectionOk(host); + } + else + { + QString err; + if (!kerberos) + err=ssh_get_error ( my_ssh_session ); + QString message=tr ( "Authentication failed" ); + guiInteractor->critical(message, MessageBox::OK); + message+=" - "+err+"\n"+authErrors.join ( "\n" ); + qDebug()<<message; + emit signalError (USERAUTH, message ); + if ( reverseTunnel ) + emit signalIoError ( reverseTunnelCreator,message,err ); + ssh_disconnect ( my_ssh_session ); + ssh_free ( my_ssh_session ); + return; + } + + +#ifndef Q_OS_WIN + const int y=1; +#else + const char y=1; +#endif + socket_t session_sock=ssh_get_fd(my_ssh_session); + setsockopt(session_sock, IPPROTO_TCP, TCP_NODELAY,&y, sizeof(int)); + + + if ( reverseTunnel ) + { + if ( channel_forward_listen ( my_ssh_session, NULL, reverseTunnelRemotePort, NULL ) !=SSH_OK ) + { + QString err=ssh_get_error ( my_ssh_session ); + QString message=tr ( "channel_forward_listen failed" ); + message+=" - "+err; + qDebug()<<message; + guiInteractor->critical(message, MessageBox::OK); + emit signalIoError ( reverseTunnelCreator, message, err ); + ssh_disconnect ( my_ssh_session ); + ssh_free ( my_ssh_session ); + return; + } + emit signalReverseListenOk ( reverseTunnelCreator ); + } + channelLoop(); +} + +void SshConnection::finalizeLibSsh() +{ + if ( !isLibSshInited ) + return; + ssh_finalize(); +} + + +bool SshConnection::sshConnect() +{ + int rc; + QByteArray tmpBA = host.toLocal8Bit(); + if(useProxy && proxyType==PROXYSSH) + { +#ifdef Q_OS_WIN + ssh_options_set ( my_ssh_session, SSH_OPTIONS_HOST, "127.0.0.1" ); +#else + ssh_options_set ( my_ssh_session, SSH_OPTIONS_HOST, "localhost" ); +#endif + ssh_options_set ( my_ssh_session, SSH_OPTIONS_PORT, &localProxyPort ); + } + else + { + ssh_options_set ( my_ssh_session, SSH_OPTIONS_HOST, tmpBA.data() ); + ssh_options_set ( my_ssh_session, SSH_OPTIONS_PORT, &port ); + } + rc = ssh_connect ( my_ssh_session ); + if ( rc != SSH_OK ) + { + return false; + } +//set values for remote host for proper server authentication + if(useProxy && proxyType==PROXYSSH) + { + ssh_options_set ( my_ssh_session, SSH_OPTIONS_HOST, tmpBA.data() ); + ssh_options_set ( my_ssh_session, SSH_OPTIONS_PORT, &port ); + + } + return true; +} + +int SshConnection::serverAuth(QString& errorMsg) +{ + int state, hlen; + unsigned char *hash = NULL; + char *hexa; + + state = ssh_is_server_known ( my_ssh_session ); + hlen = ssh_get_pubkey_hash ( my_ssh_session, &hash ); + + + if ( hlen < 0 ) + return SSH_SERVER_ERROR; + +#ifdef DEBUG + x2goDebug<<"state: "<<state<<endl; +#endif + + switch ( state ) + { + case SSH_SERVER_KNOWN_OK: + break; /* ok */ + + case SSH_SERVER_KNOWN_CHANGED: + hexa = ssh_get_hexa ( hash, hlen ); + errorMsg=tr ( "Host key for server ")+host+":"+QString::number(port)+tr(" changed.\nIt is now: " ) +hexa+"\n"+ + tr ( "For security reasons, connection will be stopped" ); + free ( hexa ); + break; + case SSH_SERVER_FOUND_OTHER: + errorMsg=tr ( "The host key for server ")+ host+":"+QString::number(port) +tr(" was not found but an other" + "type of key exists.An attacker might change the default server key to" + "confuse your client into thinking the key does not exist" ); + + break; + case SSH_SERVER_FILE_NOT_FOUND: + case SSH_SERVER_NOT_KNOWN: + if ( !acceptUnknownServers ) + { + hexa = ssh_get_hexa ( hash, hlen ); + errorMsg= tr ( "The server is unknown: ")+ host+":"+QString::number(port)+"\n"+ + tr("Do you trust the host key?\nPublic key hash: " )+ " - "+hexa; + free ( hexa ); + if(guiInteractor->warning(errorMsg, MessageBox::YES| MessageBox::NO) != MessageBox::YES) + { + errorMsg=tr ( "Host key verification failed" ); + break; + } + } + ssh_write_knownhost ( my_ssh_session ); + state=SSH_SERVER_KNOWN_OK; + break; + case SSH_SERVER_ERROR: + errorMsg=host+":"+QString::number(port)+" - "+ssh_get_error ( my_ssh_session ); + break; + } + free ( hash ); + return state; +} + +bool SshConnection::userAuth() +{ + if(user.length()<=0) + if (guiInteractor->input(tr("Enter user name"),tr("User:"),user,QLineEdit::Password)!=MessageBox::OK) + return false; + if ( autoLogin ) + if ( userAuthAuto() ) + return true; + if ( key!="" ) + { + if ( userAuthWithKey() ) + return true; + } + return userAuthWithPass(); +} + +bool SshConnection::userAuthAuto() +{ + int rc = ssh_userauth_autopubkey ( my_ssh_session, "" ); + while(rc != SSH_AUTH_SUCCESS) + { + if(guiInteractor->input(tr("Enter passphrase to decrypt a key"),tr("Passphrase:"), keyPhrase,QLineEdit::Password)!=MessageBox::OK) + return false; + rc = ssh_userauth_autopubkey ( my_ssh_session, keyPhrase.toAscii() ); + } + if ( rc != SSH_AUTH_SUCCESS ) + { + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; + return false; + } + return true; +} + +bool SshConnection::userAuthWithKey() +{ + QString keyName=key; + bool autoRemove=false; + if ( key.indexOf ( "PRIVATE KEY" ) !=-1 ) + { + QDir dr; + QString keyPath=QDir::homePath() +"/.x2go/ssh/gen"; + dr.mkpath ( keyPath ); + QTemporaryFile fl ( keyPath+"/key" ); + fl.open(); + keyName=fl.fileName(); + fl.setAutoRemove ( false ); + QTextStream out ( &fl ); + out<<key; + fl.close(); + autoRemove=true; + } + ssh_private_key prkey=privatekey_from_file(my_ssh_session, keyName.toAscii(), 0,""); + while(!prkey) + { + if(guiInteractor->input(tr("Enter passphrase to decrypt a key"),tr("Passphrase:"), keyPhrase, QLineEdit::Password)!=MessageBox::OK) + break; + prkey=privatekey_from_file(my_ssh_session, keyName.toAscii(), 0,keyPhrase.toAscii()); + } + if (!prkey) + { + if ( autoRemove ) + QFile::remove ( keyName ); + return false; + } + ssh_public_key pubkey=publickey_from_privatekey(prkey); + if (!prkey) + { + privatekey_free(prkey); + if ( autoRemove ) + QFile::remove ( keyName ); + return false; + } + + ssh_string pubkeyStr=publickey_to_string(pubkey); + publickey_free(pubkey); + + //not implemented before libssh 0.5 + /* int rc = ssh_userauth_privatekey_file ( my_ssh_session,NULL, + keyName.toAscii(), + pass.toAscii() );*/ + + int rc=ssh_userauth_pubkey(my_ssh_session, NULL, pubkeyStr, prkey); + privatekey_free(prkey); + string_free(pubkeyStr); + if ( autoRemove ) + QFile::remove ( keyName ); + if ( rc != SSH_AUTH_SUCCESS ) + { + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; + return false; + } + return true; +} + +bool SshConnection::userAuthWithPass() +{ + if(pass.length()<=0) + if(guiInteractor->input(tr("Enter password"),tr("Password:"), pass, QLineEdit::Password)!=MessageBox::OK) + return false; + + int rc = ssh_userauth_password ( my_ssh_session, NULL, pass.toAscii() ); + while ( rc != SSH_AUTH_SUCCESS ) + { + if(guiInteractor->input(tr("Enter password"),tr("Password:"), pass, QLineEdit::Password)!=MessageBox::OK) + { + + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; + return false; + } + rc = ssh_userauth_password ( my_ssh_session, NULL, pass.toAscii() ); + } + return true; + +} + +void SshConnection::channelLoop() +{ + +} + +void SshConnection::finalize(int arg1) +{ + +} diff --git a/sshconnection.h b/sshconnection.h new file mode 100644 index 0000000..abb08e7 --- /dev/null +++ b/sshconnection.h @@ -0,0 +1,132 @@ +/************************************************************************** +* Copyright (C) 2005-2012 by Oleksandr Shneyder * +* o.shneyder@phoca-gmbh.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#ifndef SSHCONNECTION_H +#define SSHCONNECTION_H + +#include <libssh/libssh.h> +#include <QString> +#include <QList> +#include <QMutex> +#include <QThread> +#include <QStringList> +#include <QTcpSocket> +#include <QNetworkProxy> + +#include "x2goapplication.h" + +class SshProcess; +class SshConnectionGuiInteraction; + +struct ChannelConnection +{ + ssh_channel channel; + int sock; + SshProcess* creator; + int forwardPort; + int localPort; + QString forwardHost; + QString localHost; + QString command; + bool operator==(ChannelConnection& t) + { + return (channel==t.channel); + } +}; + +struct CopyRequest +{ + SshProcess* creator; + QString src; + QString dst; +}; + +class SshConnection: public QThread +{ + Q_OBJECT +public: + enum ProxyType {PROXYSSH, PROXYHTTP}; + enum Error {CONNECTION, SERVERAUTH, USERAUTH}; + SshConnection(QObject* parent, QString host, int port, bool acceptUnknownServers, QString user, + QString pass, QString key, bool autoLogin, bool krbLogin=false, + bool useProxy=false, ProxyType proxyType=PROXYSSH, QString proxyServer=QString::null, quint16 proxyPort=0, + QString proxyLogin=QString::null, QString proxyPassword=QString::null, QString proxyKey=QString::null, + bool proxyAutoLogin=false); + ~SshConnection(); + static void finalizeLibSsh(); +private: + ssh_session my_ssh_session; + QList<ChannelConnection> channelConnections; + QList<CopyRequest> copyRequests; + QList<SshConnection*> reverseTunnelConnections; + int nextPid; + QList<SshProcess*> processes; + QStringList authErrors; + QString keyPhrase; + QString host; + int port; + QString user; + QString pass; + QString key; + bool useProxy; + QString proxyServer; + quint16 proxyPort; + QString proxyLogin; + QString proxyPassword; + ProxyType proxyType; + bool proxyAutoLogin; + QString proxyKey; + bool autoLogin; + bool disconnectSessionFlag; + bool reverseTunnel; + int reverseTunnelRemotePort; + int localProxyPort; + int reverseTunnelLocalPort; + bool acceptUnknownServers; + QString reverseTunnelLocalHost; + SshProcess* reverseTunnelCreator; + bool kerberos; + QTcpSocket *tcpProxySocket; + QNetworkProxy *tcpNetworkProxy; + SshConnection* sshProxy; + bool sshProxyReady; + bool breakLoop; + static bool isLibSshInited; + static SshConnectionGuiInteraction* guiInteractor; +private: + bool sshConnect(); + bool userAuthWithPass(); + bool userAuthAuto(); + bool userAuthWithKey(); + bool userAuth(); + void channelLoop(); + void finalize(int arg1); + int serverAuth(QString& errorMsg); +protected: + void run(); +signals: + void signalError(Error, QString); + void signalIoError(SshProcess* caller, QString error, QString lastSessionError); + + void signalConnectionOk( QString host); + void signalReverseListenOk(SshProcess* creator); +}; + +#endif // SSHCONNECTION_H diff --git a/sshconnectionguiinteraction.cpp b/sshconnectionguiinteraction.cpp new file mode 100644 index 0000000..d70d166 --- /dev/null +++ b/sshconnectionguiinteraction.cpp @@ -0,0 +1,170 @@ +/************************************************************************** +* Copyright (C) 2005-2012 by Oleksandr Shneyder * +* o.shneyder@phoca-gmbh.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "sshconnectionguiinteraction.h" +#include <QTimer> +#include <QThread> +#include <QDebug> + +SshConnectionGuiInteraction::SshConnectionGuiInteraction(QObject* parent): QThread(parent) +{ + currentId=0; + QTimer::singleShot(100, this, SLOT(slotCheckRequests())); +} + +SshConnectionGuiInteraction::~SshConnectionGuiInteraction() +{ + +} + +MessageBox::Buttons SshConnectionGuiInteraction::critical(QString text, int buttons) +{ + unsigned long int id=addRequest(CRITICAL, text, buttons); + QString input; + return result(id, input); +} + +MessageBox::Buttons SshConnectionGuiInteraction::information(QString text, int buttons) +{ + unsigned long int id=addRequest(INFORMATION, text, buttons); + QString input; + return result(id, input); +} + +MessageBox::Buttons SshConnectionGuiInteraction::warning(QString text, int buttons) +{ + unsigned long int id= addRequest(WARNING, text, buttons); + QString input; + return result(id, input); +} + + +MessageBox::Buttons SshConnectionGuiInteraction::input(QString text, QString inputLabel, QString& input, + QLineEdit::EchoMode echoMode, QString pixPath) +{ + unsigned long int id= addRequest(INPUT, text, MessageBox::OK| MessageBox::CANCEL, inputLabel, input, echoMode, pixPath); + return result(id, input); +} + +long unsigned int SshConnectionGuiInteraction::addRequest(SshConnectionGuiInteraction::BoxType type, + QString text, int buttons, QString inputLabel, + QString input, QLineEdit::EchoMode echoMode, + QString pixPath) +{ + InteractionRequest req; + req.processed=false; + req.boxType=type; + req.text=text; + req.buttons=buttons; + req.inputLabel=inputLabel; + req.input=input; + req.echoMode=echoMode; + req.pixPath=pixPath; + req.id=currentId++; + mutex.lock(); + requests<<req; + mutex.unlock(); + return req.id; +} + +MessageBox::Buttons SshConnectionGuiInteraction::result(long unsigned int id, QString& input) +{ + InteractionRequest req; + req.id=id; + bool ok=false; + MessageBox::Buttons button; + while(!ok) + { + mutex.lock(); + int index=requests.indexOf(req); + if(index!=-1) + { + ok=requests[index].processed; + if(ok) + { + button=(MessageBox::Buttons)requests[index].buttons; + input=requests[index].input; + requests.removeAt(index); + } + } + mutex.unlock(); + if(!ok) + QThread::msleep(100); + } + return button; +} + +void SshConnectionGuiInteraction::slotCheckRequests() +{ + bool haveReq=false; + BoxType boxType; + int buttons; + QString text; + QString inputLabel; + QString input; + QLineEdit::EchoMode echoMode; + QString pixPath; + unsigned long int id; + mutex.lock(); + foreach (InteractionRequest req, requests) + { + haveReq=true; + boxType=req.boxType; + buttons=req.buttons; + text=req.text; + inputLabel=req.inputLabel; + input=req.input; + echoMode=req.echoMode; + pixPath=req.pixPath; + id=req.id; + break; + } + mutex.unlock(); + if(haveReq) + { + switch(boxType) + { + case INFORMATION: + buttons=MessageBox::information(text, buttons); + break; + case WARNING: + buttons=MessageBox::warning(text, buttons); + break; + case CRITICAL: + buttons=MessageBox::critical(text, buttons); + break; + case INPUT: + buttons=MessageBox::input(text, inputLabel, input, echoMode, pixPath); + break; + } + mutex.lock(); + InteractionRequest req; + req.id=id; + int index=requests.indexOf(req); + if(index!=-1) + { + requests[index].buttons=buttons; + requests[index].input=input; + requests[index].processed=true; + } + mutex.unlock(); + } + QTimer::singleShot(100, this, SLOT(slotCheckRequests())); +} diff --git a/sshconnectionguiinteraction.h b/sshconnectionguiinteraction.h new file mode 100644 index 0000000..df462c9 --- /dev/null +++ b/sshconnectionguiinteraction.h @@ -0,0 +1,75 @@ +/************************************************************************** +* Copyright (C) 2005-2012 by Oleksandr Shneyder * +* o.shneyder@phoca-gmbh.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +/*This class provide interaction with user for SshConnection objects, which running not in +GUI thread and can not use GUI elements +*/ + +#ifndef SSHCONNECTIONGUIINTERACTION_H +#define SSHCONNECTIONGUIINTERACTION_H +#include <QObject> +#include "messagebox.h" +#include <QMutex> +#include <QTimer> +#include <QThread> + +class SshConnectionGuiInteraction: public QThread +{ + Q_OBJECT +public: + explicit SshConnectionGuiInteraction(QObject* parent = 0); + virtual ~SshConnectionGuiInteraction(); + MessageBox::Buttons critical(QString text, int buttons); + MessageBox::Buttons warning(QString text, int buttons); + MessageBox::Buttons information(QString text, int buttons); + MessageBox::Buttons input(QString text, QString inputLabel, QString& input, + QLineEdit::EchoMode echoMode=QLineEdit::Normal, QString pixPath=QString::null); +private: + enum BoxType {WARNING, CRITICAL, INFORMATION, INPUT}; + struct InteractionRequest + { + bool processed; + BoxType boxType; + int buttons; + QString text; + QString inputLabel; + QString input; + QLineEdit::EchoMode echoMode; + QString pixPath; + unsigned long int id; + bool operator==(InteractionRequest t) + { + return (id==t.id); + } + }; + QList<InteractionRequest> requests; + unsigned long int currentId; + QMutex mutex; +private: + unsigned long int addRequest(BoxType type, QString text, int buttons, QString inputLabel=QString::null, + QString input=QString::null, + QLineEdit::EchoMode echoMode=QLineEdit::Normal, + QString pixPath=QString::null); + MessageBox::Buttons result(unsigned long id, QString& input); + +private slots: + void slotCheckRequests(); +}; + +#endif // SSHCONNECTIONGUIINTERACTION_H diff --git a/workarea.cpp b/workarea.cpp index eb23c8b..dc619b7 100644 --- a/workarea.cpp +++ b/workarea.cpp @@ -61,6 +61,7 @@ WorkArea::WorkArea(QWidget* parent, Qt::WindowFlags f): QWidget( parent, f) QTimer::singleShot(100, this, SLOT(slotResizeChildForms())); formToScroll=profileForm; + sessionForm->hide(); } WorkArea::~WorkArea() diff --git a/x2goapplication.cpp b/x2goapplication.cpp index 1fd8881..817f571 100644 --- a/x2goapplication.cpp +++ b/x2goapplication.cpp @@ -34,6 +34,7 @@ #include "mainwindow.h" #include "x2gobroker.h" #include "profilesettingsform.h" +#include "sshconnection.h" X2GoApplication::X2GoApplication(int& argc, char** argv, int flags): QApplication(argc, argv, flags) { @@ -63,6 +64,7 @@ X2GoApplication::~X2GoApplication() delete sessionSettings; if(broker) delete broker; + SshConnection::finalizeLibSsh(); qDebug()<<"X2Go Application exited"; } diff --git a/x2gobroker.cpp b/x2gobroker.cpp index 0cd2152..cca32a7 100644 --- a/x2gobroker.cpp +++ b/x2gobroker.cpp @@ -26,6 +26,7 @@ #include "x2goapplication.h" #include "x2goclientconfig.h" #include "messagebox.h" +#include "sshconnection.h" X2GoBroker::X2GoBroker(QObject* parent): QObject(parent) { @@ -38,9 +39,18 @@ X2GoBroker::X2GoBroker(QObject* parent): QObject(parent) url = QUrl( urlString); if(url.userName().length()>0) user=url.userName(); + if(!cfg->get_defaultNoBrockerAuth().get_value().toBool()) + { + getLoginData(); + } if(urlString.indexOf("ssh://")==0) { brokerType=SSH; +#warning search for default key hier + SshConnection* con=new SshConnection(this, url.host(), url.port(), cfg->get_autoAddToKnownHosts().get_value().toBool(), + user, pass, QString::null, + cfg->get_defaultAutoLogin().get_value().toBool()); + con->start(); } else { @@ -69,10 +79,6 @@ X2GoBroker::X2GoBroker(QObject* parent): QObject(parent) QTextStream in(&file); authId = in.readLine(); } - if(!cfg->get_defaultNoBrockerAuth().get_value().toBool()) - { - getLoginData(); - } } X2GoBroker::~X2GoBroker() diff --git a/x2goclient2.pro b/x2goclient2.pro index ea126d0..5f02ec9 100755 --- a/x2goclient2.pro +++ b/x2goclient2.pro @@ -56,6 +56,8 @@ SOURCES += main.cpp \ x2gosettings.cpp \ helpdialog.cpp \ x2gobroker.cpp \ + sshconnection.cpp \ + sshconnectionguiinteraction.cpp \ profile.cpp HEADERS += mainwindow.h \ @@ -84,6 +86,8 @@ HEADERS += mainwindow.h \ x2gosettings.h \ helpdialog.h \ x2gobroker.h \ + sshconnection.h \ + sshconnectionguiinteraction.h \ profile.h LIBS += -lssh hooks/post-receive -- x2goclient2.git (X2Go Client 2 (rewrite of x2goclient.git)) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "x2goclient2.git" (X2Go Client 2 (rewrite of x2goclient.git)).