[X2go-Commits] x2goclient.git - master (branch) updated: 3.99.2.2-59-g3258eb1

X2Go dev team git-admin at x2go.org
Fri Sep 28 11:34:23 CEST 2012


The branch, master has been updated
       via  3258eb19640dcf041d58da25c7c016788136cecf (commit)
      from  dd0bb5c56aab629a2476e7d3890382da462f25d7 (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 3258eb19640dcf041d58da25c7c016788136cecf
Author: Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
Date:   Fri Sep 28 11:34:15 2012 +0200

    support for SSH broker. --broker-user removed, use username in broker url instead

-----------------------------------------------------------------------

Summary of changes:
 debian/changelog     |    1 +
 httpbrokerclient.cpp |  458 +++++++++++++++++++++++++++++++++++++++-----------
 httpbrokerclient.h   |   18 +-
 onmainwindow.cpp     |   14 +-
 onmainwindow.h       |    3 +
 5 files changed, 394 insertions(+), 100 deletions(-)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 3193042..cefa5ac 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -67,6 +67,7 @@ x2goclient (3.99.3.0-0~x2go1) UNRELEASED; urgency=low
     - improve brocker code
       add support for "usebrockerpass" config variable to use brocker pass for ssh auth on X2Go server 
     - commandline options --broker-user and --broker-noauth
+    - support for SSH broker. --broker-user removed, use username in broker url instead 
 
   [ Ricardo Diaz ]
   * New upstream version (3.99.3.0):
diff --git a/httpbrokerclient.cpp b/httpbrokerclient.cpp
index 36d3e1b..f84f95e 100644
--- a/httpbrokerclient.cpp
+++ b/httpbrokerclient.cpp
@@ -25,25 +25,42 @@
 #include "SVGFrame.h"
 #include "onmainwindow.h"
 #include <QTemporaryFile>
+#include <QInputDialog>
+#include <sshprocess.h>
 
 HttpBrokerClient::HttpBrokerClient ( ONMainWindow* wnd, ConfigFile* cfg )
 {
     config=cfg;
     mainWindow=wnd;
+    sshConnection=0;
     QUrl lurl ( config->brokerurl );
-    http=new QHttp ( this );
-
-    if ( config->brokerurl.indexOf ( "https://" ) !=-1 )
-        http->setHost ( lurl.host(),QHttp::ConnectionModeHttps,
-                        lurl.port ( 443 ) );
+    if(lurl.userName().length()>0)
+        config->brokerUser=lurl.userName();
+    if(config->brokerurl.indexOf("ssh://")==0)
+    {
+        sshBroker=true;
+        x2goDebug<<"host:"<<lurl.host();
+        x2goDebug<<"port:"<<lurl.port(22);
+        x2goDebug<<"uname:"<<lurl.userName();
+        x2goDebug<<"path:"<<lurl.path();
+        config->sshBrokerBin=lurl.path();
+    }
     else
-        http->setHost ( lurl.host(),QHttp::ConnectionModeHttp,
-                        lurl.port ( 80 ) );
-
-    connect ( http,SIGNAL ( requestFinished ( int,bool ) ),this,
-              SLOT ( slotRequestFinished ( int,bool ) ) );
-    connect ( http,SIGNAL ( sslErrors ( const QList<QSslError>& ) ),this,
-              SLOT ( slotSslErrors ( const QList<QSslError>& ) ) );
+    {
+        sshBroker=false;
+        http=new QHttp ( this );
+        if ( config->brokerurl.indexOf ( "https://" ) ==0 )
+            http->setHost ( lurl.host(),QHttp::ConnectionModeHttps,
+                            lurl.port ( 443 ) );
+        else
+            http->setHost ( lurl.host(),QHttp::ConnectionModeHttp,
+                            lurl.port ( 80 ) );
+
+        connect ( http,SIGNAL ( requestFinished ( int,bool ) ),this,
+                  SLOT ( slotRequestFinished ( int,bool ) ) );
+        connect ( http,SIGNAL ( sslErrors ( const QList<QSslError>& ) ),this,
+                  SLOT ( slotSslErrors ( const QList<QSslError>& ) ) );
+    }
 }
 
 
@@ -51,67 +68,254 @@ HttpBrokerClient::~HttpBrokerClient()
 {
 }
 
-void HttpBrokerClient::getUserSessions()
+void HttpBrokerClient::createSshConnection()
 {
-    QString req;
-    QTextStream ( &req ) <<
-                         "task=listsessions&"<<
-                         "user="<<config->brokerUser<<"&"<<
-                         "password="<<config->brokerPass<<"&"<<
-                         "authid="<<config->brokerUserId;
     QUrl lurl ( config->brokerurl );
-    httpSessionAnswer.close();
-    httpSessionAnswer.setData ( 0,0 );
-    sessionsRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
-    config->sessiondata=QString::null;
+    sshConnection=new SshMasterConnection (this, lurl.host(), lurl.port(22),false,
+                                           config->brokerUser, config->brokerPass,config->brokerSshKey,config->brokerAutologin, false,false);
+
+    connect ( sshConnection, SIGNAL ( connectionOk(QString)), this, SLOT ( slotSshConnectionOk() ) );
+    connect ( sshConnection, SIGNAL ( serverAuthError ( int,QString, SshMasterConnection* ) ),this,
+              SLOT ( slotSshServerAuthError ( int,QString, SshMasterConnection* ) ) );
+    connect ( sshConnection, SIGNAL ( needPassPhrase(SshMasterConnection*)),this,
+              SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*)) );
+    connect ( sshConnection, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshUserAuthError ( QString ) ) );
+    connect ( sshConnection, SIGNAL ( connectionError(QString,QString)), this,
+              SLOT ( slotSshConnectionError ( QString,QString ) ) );
+    sshConnection->start();
+
+}
+
+void HttpBrokerClient::slotSshConnectionError(QString message, QString lastSessionError)
+{
+    if ( sshConnection )
+    {
+        sshConnection->wait();
+        delete sshConnection;
+        sshConnection=0l;
+    }
+
+    QMessageBox::critical ( 0l,message,lastSessionError,
+                            QMessageBox::Ok,
+                            QMessageBox::NoButton );
+}
+
+void HttpBrokerClient::slotSshConnectionOk()
+{
+    getUserSessions();
+}
+
+void HttpBrokerClient::slotSshServerAuthError(int error, QString sshMessage, SshMasterConnection* connection)
+{
+    QString errMsg;
+    switch ( error )
+    {
+    case SSH_SERVER_KNOWN_CHANGED:
+        errMsg=tr ( "Host key for server changed.\nIt is now: " ) +sshMessage+"\n"+
+               tr ( "For security reasons, connection will be stopped" );
+        connection->writeKnownHosts(false);
+        connection->wait();
+        if(sshConnection && sshConnection !=connection)
+        {
+            sshConnection->wait();
+            delete sshConnection;
+        }
+        sshConnection=0;
+        slotSshUserAuthError ( errMsg );
+        return;
+
+    case SSH_SERVER_FOUND_OTHER:
+        errMsg=tr ( "The host key for this server 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" );
+        connection->writeKnownHosts(false);
+        connection->wait();
+        if(sshConnection && sshConnection !=connection)
+        {
+            sshConnection->wait();
+            delete sshConnection;
+        }
+        sshConnection=0;
+        slotSshUserAuthError ( errMsg );
+        return ;
+
+    case SSH_SERVER_ERROR:
+        connection->writeKnownHosts(false);
+        connection->wait();
+        if(sshConnection && sshConnection !=connection)
+        {
+            sshConnection->wait();
+            delete sshConnection;
+        }
+        sshConnection=0;
+        slotSshUserAuthError ( sshMessage );
+        return ;
+    case SSH_SERVER_FILE_NOT_FOUND:
+        errMsg=tr ( "Could not find known host file."
+                    "If you accept the host key here, the file will be automatically created" );
+        break;
+
+    case SSH_SERVER_NOT_KNOWN:
+        errMsg=tr ( "The server is unknown. Do you trust the host key?\nPublic key hash: " ) +sshMessage;
+        break;
+    }
+
+    if ( QMessageBox::warning ( 0, tr ( "Host key verification failed" ),errMsg,tr ( "Yes" ), tr ( "No" ) ) !=0 )
+    {
+        connection->writeKnownHosts(false);
+        connection->wait();
+        if(sshConnection && sshConnection !=connection)
+        {
+            sshConnection->wait();
+            delete sshConnection;
+        }
+        sshConnection=0;
+        slotSshUserAuthError ( tr ( "Host key verification failed" ) );
+        return;
+    }
+    connection->writeKnownHosts(true);
+    connection->wait();
+    connection->start();
 
 }
 
+void HttpBrokerClient::slotSshServerAuthPassphrase(SshMasterConnection* connection)
+{
+    bool ok;
+    QString phrase=QInputDialog::getText(0,connection->getUser()+"@"+connection->getHost()+":"+QString::number(connection->getPort()),
+                                         tr("Enter passphrase to decrypt a key"),QLineEdit::Password,QString::null, &ok);
+    if(!ok)
+    {
+        phrase=QString::null;
+    }
+    else
+    {
+        if(phrase==QString::null)
+            phrase="";
+    }
+    connection->setKeyPhrase(phrase);
+
+}
+
+void HttpBrokerClient::slotSshUserAuthError(QString error)
+{
+    if ( sshConnection )
+    {
+        sshConnection->wait();
+        delete sshConnection;
+        sshConnection=0l;
+    }
+
+    QMessageBox::critical ( 0l,tr ( "Authentication failed" ),error,
+                            QMessageBox::Ok,
+                            QMessageBox::NoButton );
+    emit authFailed();
+    return;
+}
+
+void HttpBrokerClient::getUserSessions()
+{
+    config->sessiondata=QString::null;
+    if(!sshBroker)
+    {
+        QString req;
+        QTextStream ( &req ) <<
+                             "task=listsessions&"<<
+                             "user="<<config->brokerUser<<"&"<<
+                             "password="<<config->brokerPass<<"&"<<
+                             "authid="<<config->brokerUserId;
+        QUrl lurl ( config->brokerurl );
+        httpSessionAnswer.close();
+        httpSessionAnswer.setData ( 0,0 );
+        sessionsRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    }
+    else
+    {
+        if(!sshConnection)
+        {
+            createSshConnection();
+            return;
+        }
+        SshProcess* proc=new SshProcess ( sshConnection, this );
+        connect ( proc,SIGNAL ( sshFinished ( bool,QString,SshProcess* ) ),
+                  this,SLOT ( slotListSessions ( bool, QString,
+                              SshProcess* ) ) );
+        proc->startNormal ( config->sshBrokerBin+" --authid "+config->brokerUserId+ " --task listsessions" );
+    }
+}
+
 void HttpBrokerClient::selectUserSession(const QString& session)
 {
-//     x2goDebug<<"selected sid: "<<session;
-    QString req;
-    QTextStream ( &req ) <<
-                         "task=selectsession&"<<
-                         "sid="<<session<<"&"<<
-                         "user="<<config->brokerUser<<"&"<<
-                         "password="<<config->brokerPass<<"&"<<
-                         "authid="<<config->brokerUserId;
-    QUrl lurl ( config->brokerurl );
-    httpSessionAnswer.close();
-    httpSessionAnswer.setData ( 0,0 );
-    selSessRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    if(!sshBroker)
+    {
+        QString req;
+        QTextStream ( &req ) <<
+                             "task=selectsession&"<<
+                             "sid="<<session<<"&"<<
+                             "user="<<config->brokerUser<<"&"<<
+                             "password="<<config->brokerPass<<"&"<<
+                             "authid="<<config->brokerUserId;
+        QUrl lurl ( config->brokerurl );
+        httpSessionAnswer.close();
+        httpSessionAnswer.setData ( 0,0 );
+        selSessRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    }
+    else
+    {
+        SshProcess* proc=new SshProcess ( sshConnection, this );
+        connect ( proc,SIGNAL ( sshFinished ( bool,QString,SshProcess* ) ),
+                  this,SLOT ( slotSelectSession(bool,QString,SshProcess*)));
+        proc->startNormal ( config->sshBrokerBin+" --authid "+config->brokerUserId+ " --task selectsession --sid "+session );
+    }
 
 }
 
 void HttpBrokerClient::changePassword(QString newPass)
 {
     newBrokerPass=newPass;
-    QString req;
-    QTextStream ( &req ) <<
-                         "task=setpass&"<<
-                         "newpass="<<newPass<<"&"<<
-                         "user="<<config->brokerUser<<"&"<<
-                         "password="<<config->brokerPass<<"&"<<
-                         "authid="<<config->brokerUserId;
-    QUrl lurl ( config->brokerurl );
-    httpSessionAnswer.close();
-    httpSessionAnswer.setData ( 0,0 );
-    chPassRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
-
+    if(!sshBroker)
+    {
+        QString req;
+        QTextStream ( &req ) <<
+                             "task=setpass&"<<
+                             "newpass="<<newPass<<"&"<<
+                             "user="<<config->brokerUser<<"&"<<
+                             "password="<<config->brokerPass<<"&"<<
+                             "authid="<<config->brokerUserId;
+        QUrl lurl ( config->brokerurl );
+        httpSessionAnswer.close();
+        httpSessionAnswer.setData ( 0,0 );
+        chPassRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    }
+    else
+    {
+        SshProcess* proc=new SshProcess ( sshConnection, this );
+        connect ( proc,SIGNAL ( sshFinished ( bool,QString,SshProcess* ) ),
+                  this,SLOT ( slotPassChanged(bool,QString,SshProcess*)));
+        proc->startNormal ( config->sshBrokerBin+" --authid "+config->brokerUserId+ " --task setpass --newpass "+newPass );
+    }
 }
 
 void HttpBrokerClient::testConnection()
 {
-    QString req;
-    QTextStream ( &req ) <<
-                         "task=testcon";
-
-    QUrl lurl ( config->brokerurl );
-    httpSessionAnswer.close();
-    httpSessionAnswer.setData ( 0,0 );
-    requestTime.start();
-    testConRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    if(!sshBroker)
+    {
+        QString req;
+        QTextStream ( &req ) <<
+                             "task=testcon";
+        QUrl lurl ( config->brokerurl );
+        httpSessionAnswer.close();
+        httpSessionAnswer.setData ( 0,0 );
+        requestTime.start();
+        testConRequest=http->post ( lurl.path(),req.toUtf8(),&httpSessionAnswer );
+    }
+    else
+    {
+        SshProcess* proc=new SshProcess ( sshConnection, this );
+        connect ( proc,SIGNAL ( sshFinished ( bool,QString,SshProcess* ) ),
+                  this,SLOT ( slotSelectSession(bool,QString,SshProcess*)));
+        proc->startNormal ( config->sshBrokerBin+" --authid "+config->brokerUserId+ " --task testcon" );
+    }
 }
 
 
@@ -130,6 +334,95 @@ void HttpBrokerClient::createIniFile(const QString& content)
 }
 
 
+bool HttpBrokerClient::checkAccess(QString answer )
+{
+    if (answer.indexOf("Access granted")==-1)
+    {
+        QMessageBox::critical (
+            0,tr ( "Error" ),
+            tr ( "Login failed!<br>"
+                 "Please try again" ) );
+        emit authFailed();
+        return false;
+    }
+    config->brokerAuthenticated=true;
+    return true;
+}
+
+
+void HttpBrokerClient::slotConnectionTest(bool success, QString answer, SshProcess* proc)
+{
+    if(proc)
+        delete proc;
+    if(!success)
+    {
+        x2goDebug<<answer;
+        QMessageBox::critical(0,tr("Error"),answer);
+        emit fatalHttpError();
+        return;
+    }
+    if(!checkAccess(answer))
+        return;
+    if(!sshBroker)
+    {
+        x2goDebug<<"elapsed: "<<requestTime.elapsed()<<"received:"<<httpSessionAnswer.size()<<endl;
+        emit connectionTime(requestTime.elapsed(),httpSessionAnswer.size());
+    }
+    return;
+
+}
+
+void HttpBrokerClient::slotListSessions(bool success, QString answer, SshProcess* proc)
+{
+    if(proc)
+        delete proc;
+    if(!success)
+    {
+        x2goDebug<<answer;
+        QMessageBox::critical(0,tr("Error"),answer);
+        emit fatalHttpError();
+        return;
+    }
+    if(!checkAccess(answer))
+        return;
+    createIniFile(answer);
+    emit sessionsLoaded();
+}
+
+void HttpBrokerClient::slotPassChanged(bool success, QString answer, SshProcess* proc)
+{
+    if(proc)
+        delete proc;
+    if(!success)
+    {
+        x2goDebug<<answer;
+        QMessageBox::critical(0,tr("Error"),answer);
+        emit fatalHttpError();
+        return;
+    }
+    if(!checkAccess(answer))
+        return;
+
+}
+
+void HttpBrokerClient::slotSelectSession(bool success, QString answer, SshProcess* proc)
+{
+    if(proc)
+        delete proc;
+    if(!success)
+    {
+        x2goDebug<<answer;
+        QMessageBox::critical(0,tr("Error"),answer);
+        emit fatalHttpError();
+        return;
+    }
+    if(!checkAccess(answer))
+        return;
+    x2goDebug<<"parsing "<<answer;
+    parseSession(answer);
+}
+
+
 void HttpBrokerClient::slotRequestFinished ( int id, bool error )
 {
 //   	x2goDebug<<"http request "<<id<<", finished with: "<<error;
@@ -142,50 +435,23 @@ void HttpBrokerClient::slotRequestFinished ( int id, bool error )
         return;
     }
 
+    QString answer ( httpSessionAnswer.data() );
+    x2goDebug<<"cmd request answer: "<<answer;
     if (id==testConRequest)
     {
-
-        //x2goDebug<<"cmd request answer: "<<answer;
-        x2goDebug<<"elapsed: "<<requestTime.elapsed()<<"received:"<<httpSessionAnswer.size()<<endl;
-        emit connectionTime(requestTime.elapsed(),httpSessionAnswer.size());
-        return;
+        slotConnectionTest(true,answer,0);
     }
-    if ( id== sessionsRequest || id == selSessRequest || id==chPassRequest)
+    if (id == sessionsRequest)
     {
-        QString answer ( httpSessionAnswer.data() );
-        x2goDebug<<"cmd request answer: "<<answer;
-        if (answer.indexOf("Access granted")==-1)
-        {
-            QMessageBox::critical (
-                0,tr ( "Error" ),
-                tr ( "Login failed!<br>"
-                     "Please try again" ) );
-            emit authFailed();
-            return;
-        }
-        config->brokerAuthenticated=true;
-        if (id == sessionsRequest)
-        {
-            createIniFile(answer);
-            emit sessionsLoaded();
-        }
-        if (id == selSessRequest)
-        {
-            parseSession(answer);
-
-        }
-        if ( id == chPassRequest)
-        {
-            if (answer.indexOf("CHANGING PASS OK")!=-1)
-            {
-                emit passwordChanged(newBrokerPass);
-            }
-            else
-            {
-                emit passwordChanged(QString::null);
-            }
-
-        }
+        slotListSessions(true, answer,0);
+    }
+    if (id == selSessRequest)
+    {
+        slotSelectSession(true,answer,0);
+    }
+    if ( id == chPassRequest)
+    {
+        slotPassChanged(true,answer,0);
     }
 }
 
diff --git a/httpbrokerclient.h b/httpbrokerclient.h
index e7b3b57..02f5d3d 100644
--- a/httpbrokerclient.h
+++ b/httpbrokerclient.h
@@ -16,6 +16,7 @@
 #include <QBuffer>
 #include <QObject>
 #include <QDateTime>
+#include "sshmasterconnection.h"
 /**
 	@author Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
 */
@@ -43,14 +44,29 @@ private:
     QString newBrokerPass;
     ConfigFile* config;
     ONMainWindow* mainWindow;
+    QTime requestTime;
+    bool sshBroker;
+    SshMasterConnection* sshConnection;
+private:
     void createIniFile(const QString& content);
     void parseSession(QString sInfo);
-    QTime requestTime;
+    void createSshConnection();
+    bool checkAccess(QString answer);
 
 private slots:
     void slotRequestFinished ( int id, bool error );
     void slotSslErrors ( const QList<QSslError> & errors ) ;
     QString getHexVal ( const QByteArray& ba );
+    void slotSshConnectionError ( QString message, QString lastSessionError );
+    void slotSshServerAuthError ( int error, QString sshMessage, SshMasterConnection* connection );
+    void slotSshServerAuthPassphrase ( SshMasterConnection* connection );
+    void slotSshUserAuthError ( QString error );
+    void slotSshConnectionOk();
+    void slotListSessions ( bool success, QString answer, SshProcess* proc);
+    void slotSelectSession ( bool success, QString answer, SshProcess* proc);
+    void slotPassChanged ( bool success, QString answer, SshProcess* proc);
+    void slotConnectionTest( bool success, QString answer, SshProcess* proc);
+
 public slots:
     void getUserSessions();
 
diff --git a/onmainwindow.cpp b/onmainwindow.cpp
index 2825e38..89e2964 100644
--- a/onmainwindow.cpp
+++ b/onmainwindow.cpp
@@ -969,13 +969,15 @@ void ONMainWindow::slotGetBrokerAuth()
     nameLabel->setText ( text );
     slotShowPassForm();
     config.brokerAuthenticated=false;
-    if(config.brokerUser.length()>=0)
+    if(config.brokerUser.length()>0)
     {
         login->setText(config.brokerUser);
         pass->setFocus();
     }
     if(config.brokerNoAuth)
         slotSessEnter();
+    if(config.brokerurl.indexOf("ssh://")==0 && (config.brokerAutologin || config.brokerSshKey.length()>0))
+        slotSessEnter();
 }
 
 
@@ -6210,6 +6212,12 @@ bool ONMainWindow::parseParameter ( QString param )
         return true;
     }
 
+    if ( param == "--broker-autologin")
+    {
+        config.brokerAutologin=true;
+        return true;
+    }
+
     if ( param == "--broker-noauth")
     {
         config.brokerNoAuth=true;
@@ -6339,9 +6347,9 @@ bool ONMainWindow::parseParameter ( QString param )
         config.brokerurl=value;
         return true;
     }
-    if ( setting == "--broker-user")
+    if ( setting == "--broker-ssh-key")
     {
-        config.brokerUser=value;
+        config.brokerSshKey=value;
         return true;
     }
     if ( setting == "--ssh-key")
diff --git a/onmainwindow.h b/onmainwindow.h
index 831599a..5e8ec6e 100644
--- a/onmainwindow.h
+++ b/onmainwindow.h
@@ -165,8 +165,11 @@ struct ConfigFile
     QString brokerPass;
     QString brokerUserId;
     QString brokerName;
+    QString sshBrokerBin;
     bool brokerAuthenticated;
     bool brokerNoAuth;
+    bool brokerAutologin;
+    QString brokerSshKey;
     QString iniFile;
     QString server;
     QString serverIp;//Can be different from server (use for loadballancing)


hooks/post-receive
-- 
x2goclient.git (X2Go Client)

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 "x2goclient.git" (X2Go Client).




More information about the x2go-commits mailing list