This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch revtunnel in repository x2goclient. commit 33e81a459c191b1ce06383c4e8195bb29920fced Author: Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> Date: Fri Jan 17 15:06:45 2014 +0100 Revrite SSH Classes to support libssh fix --- debian/changelog | 1 + onmainwindow.cpp | 28 +-- sshmasterconnection.cpp | 344 ++++++++++++--------------- sshmasterconnection.h | 32 ++- sshprocess.cpp | 23 +- sshprocess.cpp.bc | 598 ----------------------------------------------- sshprocess.h | 1 + sshprocess.h.bc | 92 -------- 8 files changed, 190 insertions(+), 929 deletions(-) diff --git a/debian/changelog b/debian/changelog index c11e6a9..2ba3cdc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,7 @@ x2goclient (4.0.1.3-0x2go1) UNRELEASED; urgency=low - Enables forwarding (delegation) of GSSAPI credentials to the server. - Make GSSAPI delegation configurable. - Update Russian translation file. + - Revrite SSH Classes to support libssh fix [ Orion Poplawski ] * New upstream version (4.0.1.3): diff --git a/onmainwindow.cpp b/onmainwindow.cpp index 4efd91f..ae3eefa 100644 --- a/onmainwindow.cpp +++ b/onmainwindow.cpp @@ -5033,25 +5033,25 @@ void ONMainWindow::slotRetResumeSess ( bool result, scmd="echo \"default-server=`echo " "$SSH_CLIENT | awk '{print $1}'`:"+ sndPort+ - "\"> ~/.x2go/C-"+ + "\"> $HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf" ";echo \"cookie-file=.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"+ - "\">> ~/.x2go/C-"+ + "\">> $HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf"; else scmd="echo \"default-server=localhost:"+ resumingSession.sndPort+ - "\"> ~/.x2go/C-"+ + "\"> $HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf" ";echo \"cookie-file=.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"+ - "\">> ~/.x2go/C-"+ + "\">> $HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf"; @@ -5105,7 +5105,7 @@ void ONMainWindow::slotRetResumeSess ( bool result, { sshConnection->copyFile( pulsecookie_filename, - "~/.x2go/C-"+ + "$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int ))); } @@ -5122,7 +5122,7 @@ void ONMainWindow::slotRetResumeSess ( bool result, if ( pulsecookie_filename.length() > 0 ) { sshConnection->copyFile(pulsecookie_filename, - "~/.x2go/C-"+ + "$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int ))); } @@ -5130,7 +5130,7 @@ void ONMainWindow::slotRetResumeSess ( bool result, QString cooFile= wapiShortFileName ( homeDir ) + "/.x2go/pulse/.pulse-cookie"; - QString destFile="~/.x2go/C-"+ + QString destFile="$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"; sshConnection->copyFile(cooFile, @@ -5143,12 +5143,12 @@ void ONMainWindow::slotRetResumeSess ( bool result, { #ifndef Q_OS_WIN sshConnection->copyFile(homeDir+"/.esd_auth", - "~/.esd_auth" ); + "$HOME/.esd_auth" ); #else QString cooFile= wapiShortFileName ( homeDir ) + "/.x2go/pulse/.esd_auth"; - QString destFile="~/.esd_auth"; + QString destFile="$HOME/.esd_auth"; sshConnection->copyFile(cooFile, destFile ); @@ -6202,7 +6202,7 @@ void ONMainWindow::runCommand() if(sshConnection->useKerberos() && sshConnection->get_kerberosDelegation()) { krbFwString="KRB5CCNAME=`echo $KRB5CCNAME |sed 's/FILE://g'` \ - KRBFL=~/.x2go/C-"+resumingSession.sessionId+"/krb5cc ;\ + KRBFL=$HOME/.x2go/C-"+resumingSession.sessionId+"/krb5cc ;\ cp -a $KRB5CCNAME $KRBFL;KRB5CCNAME=$KRBFL "; } @@ -6215,9 +6215,9 @@ void ONMainWindow::runCommand() sessionType +" 1> /dev/null 2>/dev/null & exit"; if ( startSessSndSystem ==PULSE ) { - cmd="PULSE_CLIENTCONFIG=~/.x2go/C-"+ + cmd="export PULSE_CLIENTCONFIG=$HOME/.x2go/C-"+ resumingSession.sessionId+ - "/.pulse-client.conf "+cmd; + "/.pulse-client.conf;"+cmd; } } else @@ -6261,7 +6261,7 @@ void ONMainWindow::runCommand() void ONMainWindow::runApplication(QString exec) { - sshConnection->executeCommand ("PULSE_CLIENTCONFIG=~/.x2go/C-"+ + sshConnection->executeCommand ("PULSE_CLIENTCONFIG=$HOME/.x2go/C-"+ resumingSession.sessionId+"/.pulse-client.conf DISPLAY=:"+ resumingSession.display+ " setsid "+exec+" 1> /dev/null 2>/dev/null & exit"); @@ -9891,7 +9891,7 @@ void ONMainWindow::slotConfigXinerama() foreach (QRect disp, xineramaScreens) screens<<QString::number(disp.x())+" "+QString::number(disp.y())+" "+QString::number(disp.width())+ " "+QString::number(disp.height()); - QString cmd="export DISPLAY=:"+resumingSession.display+";printf '"+screens.join("\\\\n")+"' > ~/.x2go/C-"+ + QString cmd="export DISPLAY=:"+resumingSession.display+";printf '"+screens.join("\\\\n")+"' > $HOME/.x2go/C-"+ resumingSession.sessionId+"/xinerama.conf"; sshConnection->executeCommand(cmd, this, SLOT(slotXineramaConfigured())); diff --git a/sshmasterconnection.cpp b/sshmasterconnection.cpp index 8355611..c161ab3 100755 --- a/sshmasterconnection.cpp +++ b/sshmasterconnection.cpp @@ -182,7 +182,6 @@ SshMasterConnection::SshMasterConnection (QObject* parent, QString host, int por this->proxylogin=proxylogin; this->proxypassword=proxypassword; this->proxyKrbLogin=proxyKrbLogin; - reverseTunnel=false; mainWnd=(ONMainWindow*) parent; kerberos=krblogin; challengeAuthVerificationCode=QString::null; @@ -209,49 +208,6 @@ SshMasterConnection::SshMasterConnection (QObject* parent, QString host, int por #endif } -SshMasterConnection::SshMasterConnection (QObject* parent, ONMainWindow* mwd, QString host, int port, bool acceptUnknownServers, - QString user, QString pass, QString key,bool autologin, - int remotePort, QString localHost, int localPort, SshProcess* creator, - bool useproxy, ProxyType type, QString proxyserver, quint16 proxyport, - QString proxylogin, QString proxypassword, QString proxykey, - bool proxyautologin, bool proxyKrbLogin, int localProxyPort) : QThread ( parent ) -{ -#if defined ( Q_OS_DARWIN ) - setStackSize (sizeof (char) * 1024 * 1024 * 2); -#endif - tcpProxySocket = NULL; - tcpNetworkProxy = NULL; - sshProxy= NULL; - sshProxyReady=false; - kerberosDelegation=false; - 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->proxyserver=proxyserver; - this->proxyport=proxyport; - this->proxylogin=proxylogin; - this->proxypassword=proxypassword; - this->proxytype=type; - this->proxyautologin=proxyautologin; - this->proxyKrbLogin=proxyKrbLogin; - this->proxykey=proxykey; - this->localProxyPort=localProxyPort; - reverseTunnelLocalHost=localHost; - reverseTunnelLocalPort=localPort; - reverseTunnelCreator=creator; - reverseTunnel=true; - reverseTunnelRemotePort=remotePort; - mainWnd=mwd; -#ifdef DEBUG - x2goDebug<<"SshMasterConnection, instance "<<this<<" created (reverse tunnel)"; -#endif -} void SshMasterConnection::slotSshProxyConnectionOk() { @@ -306,6 +262,106 @@ QString SshMasterConnection::getSourceFile(int pid) } +void SshMasterConnection::addReverseTunnelConnections() +{ + reverseTunnelRequestMutex.lock(); + for(int i=0; i<reverseTunnelRequest.count(); ++i) + { + if(!reverseTunnelRequest[i].listen) + { + reverseTunnelRequest[i].listen=true; + int rc=ssh_forward_listen(my_ssh_session, NULL, reverseTunnelRequest[i].forwardPort, NULL); + if(rc==SSH_OK) + { + emit reverseTunnelOk(reverseTunnelRequest[i].creator); +#ifdef DEBUG + x2goDebug<<"Listening for TCP/IP connections on "<<reverseTunnelRequest[i].forwardPort; +#endif + } + if(rc==SSH_ERROR) + { + QString err=ssh_get_error(my_ssh_session); +#ifdef DEBUG + x2goDebug<<"Forward port "<<reverseTunnelRequest[i].forwardPort<<" failed:"<<err; +#endif + emit reverseTunnelFailed(reverseTunnelRequest[i].creator, err); + } + } + } + reverseTunnelRequestMutex.unlock(); +} + +void SshMasterConnection::checkReverseTunnelConnections() +{ + int port; + ssh_channel chan=ssh_channel_accept_forward(my_ssh_session, 0, &port); + if(chan) + { +#ifdef DEBUG + x2goDebug<<"New reverse connection on port "<<port; +#endif + + reverseTunnelRequestMutex.lock(); + for(int i=0; i<reverseTunnelRequest.count(); ++i) + { + ReverseTunnelRequest req=reverseTunnelRequest[i]; + if(req.forwardPort==port) + { +#ifdef DEBUG + x2goDebug<<"Creating new channel for reverse tunnel "<<port; +#endif + int sock=socket ( AF_INET, SOCK_STREAM,0 ); +#ifndef Q_OS_WIN + const int y=1; +#else + const char y=1; +#endif + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,&y, sizeof(int)); + + struct sockaddr_in address; + address.sin_family=AF_INET; + address.sin_port=htons ( req.localPort ); +#ifdef DEBUG + x2goDebug<<"connecting to "<<req.localHost<<":"<<req.localPort<<endl; +#endif +#ifndef Q_OS_WIN + inet_aton ( req.localHost.toAscii(), &address.sin_addr ); +#else + address.sin_addr.s_addr=inet_addr ( + req.localHost.toAscii() ); +#endif + + if ( ::connect ( sock, ( struct sockaddr * ) &address,sizeof ( address ) ) !=0 ) + { + QString errMsg=tr ( "can not connect to " ) + + req.localHost+":"+QString::number ( req.localPort ); +#ifdef DEBUG + x2goDebug<<errMsg<<endl; +#endif + emit ioErr ( req.creator, errMsg, "" ); + break; + } + + ChannelConnection con; + con.channel=chan; + con.sock=sock; + con.creator=req.creator; + channelConnectionsMutex.lock(); + channelConnections<<con; + channelConnectionsMutex.unlock(); +#ifdef DEBUG + x2goDebug<<"New channel created"; +#endif + break; + } + } + reverseTunnelRequestMutex.unlock(); + + + } +} + + int SshMasterConnection::startTunnel(const QString& forwardHost, uint forwardPort, const QString& localHost, uint localPort, bool reverse, QObject* receiver, const char* slotTunnelOk, const char* slotFinished) { @@ -319,6 +375,23 @@ int SshMasterConnection::startTunnel(const QString& forwardHost, uint forwardPor connect(proc, SIGNAL(sshTunnelOk(int)), receiver, slotTunnelOk); } proc->startTunnel(forwardHost, forwardPort, localHost, localPort, reverse); + if(reverse && !kerberos) + { + connect(this, SIGNAL(reverseTunnelOk(SshProcess*)), proc, SLOT(slotReverseTunnelOk(SshProcess*))); + connect(this, SIGNAL(reverseTunnelFailed(SshProcess*,QString)), proc, SLOT(slotReverseTunnelFailed(SshProcess*,QString))); + ReverseTunnelRequest req; + req.creator=proc; + req.localPort=localPort; + req.localHost=localHost; + req.forwardPort=forwardPort; + req.listen=false; +#ifdef DEBUG + x2goDebug<<"Requesting reverse tunnel from port "<<forwardPort<< " to "<<localPort; +#endif + reverseTunnelRequestMutex.lock(); + reverseTunnelRequest<<req; + reverseTunnelRequestMutex.unlock(); + } processes<<proc; return proc->pid; } @@ -358,30 +431,6 @@ void SshMasterConnection::slotSshProxyTunnelFailed(bool , QString output, } -SshMasterConnection* SshMasterConnection::reverseTunnelConnection ( SshProcess* creator, - int remotePort, QString localHost, int localPort ) -{ - SshMasterConnection* con=new SshMasterConnection (this, mainWnd, host,port,acceptUnknownServers,user,pass, - key,autologin, remotePort,localHost, - localPort,creator, useproxy, proxytype, proxyserver, proxyport, proxylogin, - proxypassword, proxykey, proxyautologin, proxyKrbLogin, localProxyPort ); - con->kerberos=kerberos; - - con->setVerficationCode(challengeAuthVerificationCode); - - connect ( con,SIGNAL ( ioErr ( SshProcess*,QString,QString ) ),this,SIGNAL ( ioErr ( SshProcess*,QString,QString ) ) ); - connect ( con,SIGNAL ( stdErr ( SshProcess*,QByteArray ) ),this,SIGNAL ( stdErr ( SshProcess*,QByteArray ) ) ); - connect ( con,SIGNAL ( reverseListenOk ( SshProcess* ) ), this, SIGNAL ( reverseListenOk ( SshProcess* ) ) ); - connect ( con,SIGNAL ( needPassPhrase(SshMasterConnection*, bool)), this, SIGNAL (needPassPhrase(SshMasterConnection*, bool))); - - con->keyPhrase=keyPhrase; - con->keyPhraseReady=true; - con->start(); - reverseTunnelConnectionsMutex.lock(); - reverseTunnelConnections.append ( con ); - reverseTunnelConnectionsMutex.unlock(); - return con; -} void SshMasterConnection::slotSshProxyServerAuthAborted() { @@ -393,7 +442,7 @@ void SshMasterConnection::run() #ifdef DEBUG x2goDebug<<"SshMasterConnection, instance "<<this<<" entering thread"; #endif - if(useproxy && proxytype==PROXYSSH && !reverseTunnel) + if(useproxy && proxytype==PROXYSSH) { sshProxy=new SshMasterConnection (0, proxyserver, proxyport,acceptUnknownServers, @@ -464,8 +513,6 @@ void SshMasterConnection::run() x2goDebug<<err<<endl; #endif emit connectionError ( err,"" ); - if ( reverseTunnel ) - emit ioErr ( reverseTunnelCreator,err,"" ); quit(); return; } @@ -529,8 +576,6 @@ void SshMasterConnection::run() x2goDebug<<message<<" - "<<err; #endif emit connectionError ( message, err ); - if ( reverseTunnel ) - emit ioErr ( reverseTunnelCreator,message,err ); ssh_free ( my_ssh_session ); quit(); return; @@ -626,8 +671,6 @@ void SshMasterConnection::run() x2goDebug<<message<<" - "<<err; #endif emit userAuthError ( authErrors.join ( "\n" ) ); - if ( reverseTunnel ) - emit ioErr ( reverseTunnelCreator,message,err ); ssh_disconnect ( my_ssh_session ); ssh_free ( my_ssh_session ); quit(); @@ -644,34 +687,6 @@ void SshMasterConnection::run() setsockopt(session_sock, IPPROTO_TCP, TCP_NODELAY,&y, sizeof(int)); - if ( reverseTunnel ) - { - if ( channel_forward_listen ( my_ssh_session, NULL, reverseTunnelRemotePort, NULL ) !=SSH_OK ) - { - if(disconnectSessionFlag) - { -#ifdef DEBUG - x2goDebug<<"session already disconnected, exiting"<<endl; -#endif - return; - } - QString err=ssh_get_error ( my_ssh_session ); - QString message=tr ( "channel_forward_listen failed" ); -#ifdef DEBUG - x2goDebug<<message<<" - "<<err; -#endif - emit ioErr ( reverseTunnelCreator, message, err ); - ssh_disconnect ( my_ssh_session ); - ssh_free ( my_ssh_session ); - quit(); - return; - } - emit reverseListenOk ( reverseTunnelCreator ); - -#ifdef DEBUG - x2goDebug<<"channel_forward_listen ok\n "; -#endif - } channelLoop(); } @@ -685,10 +700,7 @@ SshMasterConnection::~SshMasterConnection() #ifdef DEBUG x2goDebug<<"SshMasterConnection, instance "<<this<<" waiting for thread to finish"; #endif - if(!reverseTunnel) - wait(15000); - else - wait(5000); + wait(15000); #ifdef DEBUG x2goDebug<<"SshMasterConnection, instance "<<this<<" thread finished"; #endif @@ -963,21 +975,18 @@ bool SshMasterConnection::userAuthAuto() int i=0; while(rc != SSH_AUTH_SUCCESS) { - if(!reverseTunnel) + keyPhraseReady=false; + emit needPassPhrase(this, false); + for(;;) { - keyPhraseReady=false; - emit needPassPhrase(this, false); - for(;;) - { - bool ready=false; - this->usleep(200); - keyPhraseMutex.lock(); - if(keyPhraseReady) - ready=true; - keyPhraseMutex.unlock(); - if(ready) - break; - } + bool ready=false; + this->usleep(200); + keyPhraseMutex.lock(); + if(keyPhraseReady) + ready=true; + keyPhraseMutex.unlock(); + if(ready) + break; } if(keyPhrase==QString::null) break; @@ -1038,21 +1047,18 @@ bool SshMasterConnection::userAuthWithKey() int i=0; while(!prkey) { - if(!reverseTunnel) + keyPhraseReady=false; + emit needPassPhrase(this, false); + for(;;) { - keyPhraseReady=false; - emit needPassPhrase(this, false); - for(;;) - { - bool ready=false; - this->usleep(200); - keyPhraseMutex.lock(); - if(keyPhraseReady) - ready=true; - keyPhraseMutex.unlock(); - if(ready) - break; - } + bool ready=false; + this->usleep(200); + keyPhraseMutex.lock(); + if(keyPhraseReady) + ready=true; + keyPhraseMutex.unlock(); + if(ready) + break; } if(keyPhrase==QString::null) break; @@ -1254,7 +1260,7 @@ void SshMasterConnection::copy() lst.removeLast(); QString dstPath=lst.join ( "/" ); #ifdef DEBUG - x2goDebug<<"dst path:"<<dstPath<<" file:"<<dstFile<<endl; + x2goDebug<<"SSH Master Connection copy - dst path:"<<dstPath<<" file:"<<dstFile<<endl; #endif ssh_scp scp=ssh_scp_new ( my_ssh_session, SSH_SCP_WRITE|SSH_SCP_RECURSIVE, dstPath.toAscii() ); if ( scp == NULL ) @@ -1343,16 +1349,6 @@ void SshMasterConnection::channelLoop() sshProxy=0; } - reverseTunnelConnectionsMutex.lock(); -#ifdef DEBUG - x2goDebug<<"Deleting reverse tunnel connections"<<endl; -#endif - for ( int i=reverseTunnelConnections.size()-1; i>=0; --i) - { - delete reverseTunnelConnections[i]; - } - reverseTunnelConnectionsMutex.unlock(); - channelConnectionsMutex.lock(); #ifdef DEBUG x2goDebug<<"Deleting channel connections"<<endl; @@ -1376,67 +1372,17 @@ void SshMasterConnection::channelLoop() if (tcpNetworkProxy != NULL) delete tcpNetworkProxy; #ifdef DEBUG - if ( !reverseTunnel ) - x2goDebug<<"All channels closed, session disconnected, quiting session loop"<<endl; + x2goDebug<<"All channels closed, session disconnected, quiting session loop"<<endl; #endif quit(); return; } + addReverseTunnelConnections(); + checkReverseTunnelConnections(); copyRequestMutex.lock(); if ( copyRequests.size() >0 ) copy(); copyRequestMutex.unlock(); - if ( reverseTunnel ) - { - ssh_channel newChan=channel_forward_accept ( my_ssh_session,0 ); - if ( newChan ) - { -#ifdef DEBUG - x2goDebug<<"new forward connection"<<endl; -#endif - int sock=socket ( AF_INET, SOCK_STREAM,0 ); -#ifndef Q_OS_WIN - const int y=1; -#else - const char y=1; -#endif - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,&y, sizeof(int)); - - struct sockaddr_in address; - address.sin_family=AF_INET; - address.sin_port=htons ( reverseTunnelLocalPort ); -#ifdef DEBUG - x2goDebug<<"connecting to "<<reverseTunnelLocalHost<<":"<<reverseTunnelLocalPort<<endl; -#endif -#ifndef Q_OS_WIN - inet_aton ( reverseTunnelLocalHost.toAscii(), &address.sin_addr ); -#else - address.sin_addr.s_addr=inet_addr ( - reverseTunnelLocalHost.toAscii() ); -#endif - - if ( ::connect ( sock, ( struct sockaddr * ) &address,sizeof ( address ) ) !=0 ) - { - QString errMsg=tr ( "can not connect to " ) + - reverseTunnelLocalHost+":"+QString::number ( reverseTunnelLocalPort ); -#ifdef DEBUG - x2goDebug<<errMsg<<endl; -#endif - emit ioErr ( reverseTunnelCreator, errMsg, "" ); - continue; - } -#ifdef DEBUG - x2goDebug<<"creating new channel connection"<<endl; -#endif - ChannelConnection con; - con.channel=newChan; - con.sock=sock; - con.creator=reverseTunnelCreator; - channelConnectionsMutex.lock(); - channelConnections<<con; - channelConnectionsMutex.unlock(); - } - } char buffer[1024*512]; //512K buffer int nbytes; diff --git a/sshmasterconnection.h b/sshmasterconnection.h index f05825f..1f8c4ea 100644 --- a/sshmasterconnection.h +++ b/sshmasterconnection.h @@ -52,6 +52,15 @@ struct ChannelConnection } }; +struct ReverseTunnelRequest +{ + uint localPort; + uint forwardPort; + QString localHost; + SshProcess* creator; + bool listen; +}; + struct CopyRequest { SshProcess* creator; @@ -90,8 +99,6 @@ public: { acceptUnknownServers=accept; } - SshMasterConnection* reverseTunnelConnection(SshProcess* creator, int remotePort, - QString localHost, int localPort); QString getHost() { return host; @@ -110,12 +117,6 @@ public: }; private: - SshMasterConnection(QObject* parent, ONMainWindow* parWnd, QString host, int port, bool acceptUnknownServers, - QString user, QString pass, QString key,bool autologin, - int remotePort, QString localHost, int localPort, SshProcess* creator, - bool useproxy=false, ProxyType type=PROXYSSH, QString proxyserver=QString::null, quint16 proxyport=0, - QString proxylogin=QString::null, QString proxypassword=QString::null, QString proxyKey=QString::null, - bool proxyAutologin=false, bool proxyKrbLogin=false, int localProxyPort=0); bool sshConnect(); bool userAuthWithPass(); bool userAuthAuto(); @@ -128,6 +129,8 @@ private: void copy(); int serverAuth(QString& errorMsg); void setVerficationCode(QString code); + void checkReverseTunnelConnections(); + void addReverseTunnelConnections(); #ifdef Q_OS_WIN void parseKnownHosts(); #endif @@ -149,12 +152,12 @@ private: ssh_session my_ssh_session; QList<ChannelConnection> channelConnections; QList<CopyRequest> copyRequests; - QList<SshMasterConnection*> reverseTunnelConnections; + QList<ReverseTunnelRequest> reverseTunnelRequest; QMutex channelConnectionsMutex; QMutex copyRequestMutex; QMutex disconnectFlagMutex; - QMutex reverseTunnelConnectionsMutex; QMutex writeHostKeyMutex; + QMutex reverseTunnelRequestMutex; bool writeHostKey; bool writeHostKeyReady; int nextPid; @@ -181,13 +184,8 @@ private: QStringList authErrors; bool autologin; bool disconnectSessionFlag; - bool reverseTunnel; - int reverseTunnelRemotePort; int localProxyPort; - int reverseTunnelLocalPort; bool acceptUnknownServers; - QString reverseTunnelLocalHost; - SshProcess* reverseTunnelCreator; ONMainWindow* mainWnd; bool kerberos; QString sshProcErrString; @@ -207,14 +205,14 @@ signals: void copyErr(SshProcess* caller, QString error, QString lastSessionError); void copyOk(SshProcess* caller); void channelClosed(SshProcess* caller, QString uuid); + void reverseTunnelOk(SshProcess* caller); + void reverseTunnelFailed(SshProcess* caller, QString error); void connectionError(QString message, QString lastSessionError); void serverAuthError(int errCode, QString lastSessionError, SshMasterConnection*); void serverAuthAborted(); void userAuthError(QString error); - void newReverceTunnelConnection(SshProcess* creator, void* newChannel); - void reverseListenOk(SshProcess* creator); void connectionOk( QString host); void needPassPhrase(SshMasterConnection*, bool verificationCode); diff --git a/sshprocess.cpp b/sshprocess.cpp index dca196d..93a388c 100755 --- a/sshprocess.cpp +++ b/sshprocess.cpp @@ -227,7 +227,7 @@ void SshProcess::startNormal(const QString& cmd) procUuid=uuidStr; proc->start(sshString); - if (!proc->waitForStarted(5000)) + if (!proc->waitForStarted(15000)) { stdErrString=proc->errorString(); #ifdef DEBUG @@ -274,7 +274,7 @@ void SshProcess::start_cp(QString src, QString dst) #endif proc->start(sshString); - if (!proc->waitForStarted(5000)) + if (!proc->waitForStarted(15000)) { stdErrString=proc->errorString(); #ifdef DEBUG @@ -304,11 +304,6 @@ void SshProcess::startTunnel(const QString& forwardHost, uint forwardPort, const this->localPort=localPort; if (!reverse) tunnelLoop(); - else - { - connect(masterCon, SIGNAL(reverseListenOk(SshProcess*)), this, SLOT(slotReverseTunnelOk(SshProcess*))); - tunnelConnection=masterCon->reverseTunnelConnection(this, forwardPort, localHost, localPort); - } } else { @@ -327,7 +322,7 @@ void SshProcess::startTunnel(const QString& forwardHost, uint forwardPort, const sshString+=" -R "+ QString::number(forwardPort)+":"+forwardHost+":"+QString::number(localPort); #ifdef DEBUG - x2goDebug<<"running ssh:" <<sshString<<endl; + x2goDebug<<"TUNNEL: running ssh:" <<sshString<<endl; #endif proc->start(sshString); @@ -352,7 +347,7 @@ void SshProcess::slotStdErr(SshProcess* creator, QByteArray data) if (creator!=this) return; #ifdef DEBUG - x2goDebug<<"new err data:"<<data<<endl; +// x2goDebug<<"new err data:"<<data<<endl; #endif stdErrString+=data; @@ -365,6 +360,9 @@ void SshProcess::slotStdErr(SshProcess* creator, QByteArray data) #endif { tunnelOkEmited=true; +#ifdef DEBUG + x2goDebug<<"Tunnel OK"<<endl; +#endif emit sshTunnelOk(pid); } } @@ -409,6 +407,13 @@ void SshProcess::slotReverseTunnelOk(SshProcess* creator) emit sshTunnelOk(pid); } +void SshProcess::slotReverseTunnelFailed(SshProcess* creator, QString error) +{ + if (creator==this) + emit sshFinished(false,error,pid); + +} + void SshProcess::slotChannelClosed(SshProcess* creator, QString uuid) { diff --git a/sshprocess.cpp.bc b/sshprocess.cpp.bc deleted file mode 100644 index 9f5fa56..0000000 --- a/sshprocess.cpp.bc +++ /dev/null @@ -1,598 +0,0 @@ -// -// C++ Implementation: sshprocess -// -// Description: -// -// -// Author: Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de>, (C) 2006 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "x2goclientconfig.h" -#include "sshprocess.h" -#include <QDir> -#include "x2gologdebug.h" -#include <QMessageBox> -#include <QTemporaryFile> -#include <QApplication> -#include <QLocalServer> -#include <QLocalSocket> -#include <QTimer> -#ifdef Q_OS_WIN -#include "wapi.h" -#endif -#include "onmainwindow.h" -sshProcess::sshProcess ( QObject* parent, - const SshProxy* proxy, - const QString& user, - const QString& host,const QString& pt, - const QString& cmd,const QString& pass, - const QString& key, bool acc ) - : QProcess ( parent ) -{ - sudoErr=false; - QString root=((ONMainWindow*)parent)->getHomeDirectory() +"/.x2go"; - isTunnel=false; - isCopy=false; - fwX=false; - sshPort=pt; - localSocket=0l; - serverSocket=0l; - this->user=user; - this->host=host; - command=cmd; - this->pass=pass; - this->key=key; - autoAccept=acc; - env = QProcess::systemEnvironment(); - cleanEnv ( true ); -#ifdef Q_OS_DARWIN - //run x2goclient from bundle - QDir dir ( QApplication::applicationDirPath() ); - dir.cdUp(); - dir.cd ( "MacOS" ); - QString askpass_var="SSH_ASKPASS="; - askpass_var+=dir.absolutePath() +"/x2goclient"; - env.insert ( 0, askpass_var ); -#else - env.insert ( 0, "SSH_ASKPASS=x2goclient" ); -#endif - askpass=root+"/ssh"; - QDir dr ( askpass ); - if ( !dr.exists() ) - if ( !dr.mkpath ( askpass ) ) - { - QString message=tr ( "Unable to create: " ); - message+=askpass; - throw message; - } -#ifdef Q_OS_WIN - env.insert ( 0, "DISPLAY=localhost:0" ); - //don't care if real display is not 0 - //we need it only to start askpass - //which is not X application - askpass=wapiShortFileName ( askpass ); - extraOptions=" -o UserKnownHostsFile=\""+ - askpass +"/known_hosts\" -o ServerAliveInterval=300 "; -#else - extraOptions=" -o ServerAliveInterval=300 "; -#endif - if ( proxy->use ) - { - extraOptions+=" -o ProxyCommand=\""+proxy->bin+" "+ - user+"@"+proxy->host+" -p "+proxy->port+"\" "; - } - askpass+="/socaskpass-XXXXXX"; - QTemporaryFile fl ( askpass ); - if ( !fl.open() ) - { - QMessageBox::critical ( 0l,tr ( "Error" ), - tr ( "Cannot create temporary file" ) ); - } - askpass=fl.fileName(); - fl.setAutoRemove ( false ); - fl.close(); - QFile::remove ( askpass ); - env.insert ( 0, "X2GO_PSOCKET="+askpass ); - setEnvironment ( env ); -} - - -sshProcess::~sshProcess() -{ - QFile::remove - ( askpass ); - QFile::remove - ( askpass+".log" ); - if ( state() ==QProcess::Running ) - kill(); - if ( serverSocket ) - { - serverSocket->close(); - delete serverSocket; - } -} - - -void sshProcess::slot_error ( QProcess::ProcessError ) -{} - - -void sshProcess::slot_finished ( int exitCode, QProcess::ExitStatus status ) -{ - hidePass(); -/* x2goDebug<<outputString<<endl; - x2goDebug<<errorString<<endl; - x2goDebug<<"exitCode: "<<exitCode<<" status:"<<status<<endl;*/ - if ( ( exitCode!=0&&exitCode!=1 ) || status !=0 ) - { - QString resp=getResponce(); - - if ( (errorString.indexOf ( - "POSSIBLE DNS SPOOFING DETECTED" ) !=-1 )|| - ((errorString.indexOf ( - "REMOTE HOST IDENTIFICATION HAS CHANGED" ) !=-1 ))) - { - emit sshFinished ( false,host+":\n"+ - errorString+"\n"+ - outputString,this ); - return; - } - if ( errorString.indexOf ( - "Host key verification failed" ) !=-1 ) - { - int res; - if ( !autoAccept ) - res=QMessageBox::warning ( - 0l, - tr ( "Host key verification failed" ), - resp, - tr ( "Yes" ), - tr ( "No" ) ); - else - res=0; - if ( res==0 ) - { - if ( isTunnel ) - startTunnel ( tunnelHost,localPort, - remotePort,reverse,true ); - else if ( isCopy ) - start_cp ( source,destination,true ); - else - startNormal ( true ); - } - else - emit sshFinished ( false,host+":\n"+ - errorString+"\n"+ - outputString,this ); - } - else - { - if ( isTunnel ) - { - x2goDebug<<"stdout:"<<outputString<<endl; - x2goDebug<<"stderr:"<<errorString<<endl; - errorString="Can't start ssh tunnel"; - outputString=QString::null; - } - emit sshFinished ( false,host+":\n"+ - errorString+"\n"+ - outputString,this ); - } - } - else - emit sshFinished ( true,outputString,this ); -} - - -void sshProcess::slot_stderr() -{ - QString reserr ( readAllStandardError() ); - errorString+=reserr; -// x2goDebug<<reserr<<endl; - if ( reserr.indexOf ( - "Permission denied (publickey,keyboard-interactive)" ) !=-1 - ) - { - needPass=true; - kill(); - } - if ( reserr.indexOf ( "Authentication succeeded" ) !=-1 ) - { - hidePass(); - emit sshTunnelOk(); - } - if ( ( reserr.indexOf ( "Password:" ) !=-1 ) || - ( reserr.indexOf ( "[sudo] password for" ) !=-1 ) ) - { - sudoErr=true; - emit sudoConfigError ( errorString, this ); - } -} - - -void sshProcess::slot_stdout() -{ - if ( isTunnel ) - { - QString resout ( readAllStandardOutput() ); - } - else - { - QString reserr ( readAllStandardOutput() ); - outputString+=reserr; -// x2goDebug<<reserr<<endl; - - } -} - -void sshProcess::startNormal ( bool accept ) -{ - /* x2goDebug<<"normal"<<endl; - x2goDebug<<command<<endl; - x2goDebug<<"host:"<<host<<endl;*/ - errorString=""; - needPass=false; - disconnect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - disconnect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - disconnect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - disconnect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - connect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - connect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - connect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - connect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - QString cmX; - if ( fwX ) - { - cmX=" -X "; - } - if ( key!=QString::null && key!="" ) - { - printKey ( accept ); -#ifndef Q_OS_WIN - - start ( setsid() +" ssh "+cmX+"-i \""+key+"\" -p "+ - sshPort+extraOptions+" "+ - user+"@"+host+" \""+command+"\"" ); -#else - start ( "ssh "+cmX+"-i \""+key+"\" -p "+sshPort+ - extraOptions+" "+user+"@"+ - host+" \""+command+"\"" ); -#endif - } - else - { - printPass ( accept ); -#ifndef Q_OS_WIN - - start ( setsid() +" ssh " +cmX+" -p "+sshPort+ - extraOptions+" "+user+"@"+host+ - " \""+command+"\"" ); -#else - - start ( "ssh "+cmX+"-p "+sshPort+ - extraOptions+" "+user+"@"+host+" \""+ - command+"\"" ); -#endif - - } -} - - -void sshProcess::printPass ( bool accept ) -{ - if ( serverSocket ) - delete serverSocket; - serverSocket=new QLocalServer(); - QFile::remove ( askpass ); - if ( serverSocket->listen ( askpass ) ) - { - QFile fl ( askpass ); - fl.setPermissions ( - QFile::ReadOwner|QFile::WriteOwner ); - cleanEnv(); - passcookie=cookie(); - env.insert ( 0, "X2GO_PCOOKIE="+passcookie ); - if ( accept ) - env.insert ( 0, "X2GO_PACCEPT=yes" ); - else - env.insert ( 0, "X2GO_PACCEPT=no" ); - setEnvironment ( env ); - connect ( serverSocket,SIGNAL ( newConnection() ), - this,SLOT ( slot_pass_connection() ) ); - } - else - { - x2goDebug<<"listen server socket error!!: "<<askpass<<endl; - } -} - -void sshProcess::printKey ( bool accept ) -{ - if ( pass!="" && pass!=QString::null ) - { - printPass ( accept ); - return; - } - cleanEnv(); - env.insert ( 0, "X2GO_PCOOKIE=X2GO_RSA_DSA_KEY_USED" ); - if ( accept ) - env.insert ( 0, "X2GO_PACCEPT=yes" ); - else - env.insert ( 0, "X2GO_PACCEPT=no" ); - setEnvironment ( env ); -} - -QString sshProcess::getResponce() -{ - QFile fl ( askpass+".log" ); - if ( !fl.open ( QIODevice::ReadOnly | QIODevice::Text ) ) - { - return QString::null; - } - QTextStream in ( &fl ); - return in.readAll(); -} - -void sshProcess::hidePass() -{ - if ( serverSocket ) - { - serverSocket->close(); - delete serverSocket; - serverSocket=0l; - } - if ( QFile::exists ( askpass ) ) - QFile::remove ( askpass ); -} - -void sshProcess::startTunnel ( QString h,QString lp, - QString rp,bool rev,bool accept ) -{ - if(!rev) - x2goDebug<<"tunnel :"<<h<<":"<<lp<<":"<<rp<<endl; - else - x2goDebug<<"reverse tunnel :"<<h<<":"<<lp<<":"<<rp<<endl; - isTunnel=true; - errorString=""; - needPass=false; - - tunnelHost=h; - localPort=lp; - remotePort=rp; - reverse=rev; - - disconnect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - disconnect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - disconnect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - disconnect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - connect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - connect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - connect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - connect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - QString params=" -N "; - if ( reverse ) - params+=" -R "; - else - params+=" -L "; - params+=localPort+":"+tunnelHost+":"+remotePort; - if ( key!=QString::null && key!="" ) - { - printKey ( accept ); -#ifndef Q_OS_WIN - - start ( setsid() +" ssh -c blowfish -v -i \""+key+"\" -p "+ - sshPort+extraOptions+" "+user+"@"+host+params ); -#else - - start ( "ssh -c blowfish -v -i \""+key+"\" -p "+sshPort+ - extraOptions+" "+ - user+"@"+host+params ); -#endif - - } - else - { - printPass ( accept ); -#ifndef Q_OS_WIN - - /* x2goDebug<<setsid() +" ssh -c blowfish -v "+user+"@"+host+params+ - " -p "+sshPort+ - extraOptions;*/ - start ( setsid() +" ssh -c blowfish -v "+user+"@"+host+params+ - " -p "+sshPort+ - extraOptions ); -#else - - start ( "ssh -c blowfish -v "+user+"@"+host+params+" -p "+ - sshPort+ - extraOptions ); -#endif - - } -} - -void sshProcess::start_cp ( QString src, QString dst, bool accept ) -{ -// x2goDebug<<"copy"<<endl; - isCopy=true; - errorString=""; - needPass=false; - source=src; - destination=dst; - disconnect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - disconnect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - disconnect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - disconnect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - connect ( this,SIGNAL ( error ( QProcess::ProcessError ) ),this, - SLOT ( slot_error ( QProcess::ProcessError ) ) ); - connect ( this,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, - SLOT ( slot_finished ( int,QProcess::ExitStatus ) ) ); - connect ( this,SIGNAL ( readyReadStandardError() ),this, - SLOT ( slot_stderr() ) ); - connect ( this,SIGNAL ( readyReadStandardOutput() ),this, - SLOT ( slot_stdout() ) ); - - if ( key!=QString::null && key!="" ) - { - printKey ( accept ); -#ifndef Q_OS_WIN - - start ( setsid() +" scp -i \""+key+"\" -P "+sshPort+ - extraOptions+" "+" \""+ - src+"\" "+user+"@"+host+":"+dst ); -#else - - start ( "scp -i \""+key+"\" -P "+sshPort+ - extraOptions+" "+" \""+ - ONMainWindow::cygwinPath ( src ) +"\" "+ - user+"@"+host+":"+dst ); - -#endif - - } - else - { - printPass ( accept ); -#ifndef Q_OS_WIN - - start ( setsid() +" scp -P "+sshPort+extraOptions+" \""+ - src+"\" "+user+"@"+ - host+":"+dst ); -#else - - start ( "scp -P "+sshPort+extraOptions+" \""+ - ONMainWindow::cygwinPath ( src ) +"\" "+ - user+"@"+host+ - ":"+dst ); -#endif - } -} - - -QString sshProcess::setsid() -{ -#ifdef Q_OS_DARWIN - //run setsid from bundle - QDir dir ( QApplication::applicationDirPath() ); - dir.cdUp(); - dir.cd ( "exe" ); - return "\""+dir.absolutePath() +"/setsid\""; -#else -#ifdef Q_WS_HILDON - return "/usr/lib/x2go/setsid"; -#endif - return "setsid"; -#endif -} - -void sshProcess::setErrorString ( const QString& str ) -{ - if ( sudoErr ) - errorString=str; -} - -QString sshProcess::cookie() -{ - QString res; - for ( uint i=0;i<16;++i ) - { - QString hex; - hex.sprintf ( "%02X",qrand() ); - res+=hex; - } - return res; -} - - -void sshProcess::cleanEnv ( bool all ) -{ - for ( int i=env.count()-1;i>=0;--i ) - { - if ( all ) - { - if ( ( env[i].indexOf ( "X2GO_PCOOKIE" ) !=-1 ) || - ( env[i].indexOf ( "X2GO_PACCEPT" ) !=-1 ) || - ( env[i].indexOf ( "GPG_AGENT_INFO" ) !=-1 ) || - ( env[i].indexOf ( "SSH_AUTH_SOCK" ) !=-1 ) || - ( env[i].indexOf ( "SSH_AGENT_PID" ) !=-1 ) ) - { - env.removeAt ( i ); - } - } - else - { - if ( ( env[i].indexOf ( "X2GO_PCOOKIE" ) !=-1 ) || - ( env[i].indexOf ( "X2GO_PACCEPT" ) !=-1 ) ) - { - env.removeAt ( i ); - } - } - } -} - -void sshProcess::slot_pass_connection() -{ - if ( localSocket ) - delete localSocket; - localSocket=serverSocket->nextPendingConnection (); - if ( localSocket ) - { - connect ( localSocket,SIGNAL ( readyRead() ),this, - SLOT ( slot_read_cookie_from_socket() ) ); - } -} - -void sshProcess::slot_read_cookie_from_socket() -{ - char buffer[140]; - int read=localSocket->read ( buffer,139 ); - if ( read<=0 ) - { - QString message="Cannot get cookie from askpass program"; - throw message; - } - buffer[read]=0; - QString cookie ( buffer ); - if ( cookie!=passcookie ) - { - QString message="Got wrong cookie from askpass program"; - throw message; - } - localSocket->write ( pass.toAscii().data(),pass.toAscii().length() ); - QTimer::singleShot ( 100, this, SLOT ( hidePass() ) ); -} - - - -void sshProcess::setEnvironment ( QStringList newEnv ) -{ - env+=newEnv; - QProcess::setEnvironment ( env ); -} diff --git a/sshprocess.h b/sshprocess.h index 2bc4238..09acd71 100644 --- a/sshprocess.h +++ b/sshprocess.h @@ -86,6 +86,7 @@ private slots: void slotIOerr(SshProcess* creator,QString message, QString sshSessionErr); void slotChannelClosed(SshProcess* creator, QString uuid); void slotReverseTunnelOk(SshProcess* creator); + void slotReverseTunnelFailed(SshProcess* creator, QString error); void slotCopyOk(SshProcess* creator); void slotCopyErr(SshProcess* creator,QString message, QString sshSessionErr); //krb stuff diff --git a/sshprocess.h.bc b/sshprocess.h.bc deleted file mode 100644 index 3f12bae..0000000 --- a/sshprocess.h.bc +++ /dev/null @@ -1,92 +0,0 @@ -// -// C++ Interface: sshprocess -// -// Description: -// -// -// Author: Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de>, (C) 2006 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "x2goclientconfig.h" -#ifndef SSHPROCESS_H -#define SSHPROCESS_H - -#include <QProcess> - -/** - @author Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de> -*/ -class QLocalServer; -class QLocalSocket; -struct SshProxy; -class sshProcess : public QProcess -{ - Q_OBJECT - public: - sshProcess ( QObject* parent, const SshProxy* proxy, - const QString& user, - const QString& host,const QString& pt, - const QString& cmd, const QString& pass, - const QString& key=QString::null, - bool acc=false ); - virtual ~sshProcess(); - void startNormal ( bool accept=false ); - QString getResponce(); - void startTunnel ( QString host,QString localPort,QString remotePort, - bool reverse=false,bool accept=false ); - void start_cp ( QString src, QString dst, bool accept=false ); - QString getSource() {return source;} - QString setsid(); - void setErrorString ( const QString& str ); - void setFwX ( bool s ) {fwX=s;} - virtual void setEnvironment ( QStringList newEnv ); - private: - QString askpass; - QString user; - QString host; - QString command; - QString pass; - QString key; - QString errorString; - QString outputString; - QString passcookie; - QLocalServer* serverSocket; - QLocalSocket* localSocket; - bool needPass; - bool autoAccept; - bool isTunnel; - bool isCopy; - QString sshPort; - QString tunnelHost; - QString localPort; - QString source; - QString destination; - QString remotePort; - QStringList env; - bool reverse; - bool fwX; - bool sudoErr; - QString extraOptions; - - private slots: - void slot_error ( QProcess::ProcessError ); - void slot_finished ( int, QProcess::ExitStatus ); - void slot_stderr(); - void slot_stdout(); - void hidePass(); - void slot_pass_connection(); - void slot_read_cookie_from_socket(); - private: - void printPass ( bool accept=false ); - void printKey ( bool accept=false ); - QString cookie(); - void cleanEnv ( bool all=false ); - signals: - void sshFinished ( bool,QString,sshProcess* ); - void sudoConfigError ( QString,sshProcess* ); - void sshTunnelOk(); -}; - -#endif -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/x2goclient.git