[X2Go-Commits] [x2goclient] 03/07: src/sshmasterconnection: refactor some of the channel loop and fix channel/session closes.

git-admin at x2go.org git-admin at x2go.org
Wed May 20 09:41:12 CEST 2020


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository x2goclient.

commit 221899d12c302f517384d28351019bc19d203007
Author: Melroy van den Berg <melroy at melroy.org>
Date:   Wed May 20 09:14:04 2020 +0200

    src/sshmasterconnection: refactor some of the channel loop and fix channel/session closes.
---
 debian/changelog            |   2 +
 src/sshmasterconnection.cpp | 268 +++++++++++++++++++++++++-------------------
 2 files changed, 153 insertions(+), 117 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 98ff8ed..e4342a7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,6 +20,8 @@ x2goclient (4.1.2.3-0x2go1) UNRELEASED; urgency=medium
     - src/sshmasterconnection: send EOF before closing channel.
     - src/sshmasterconnection: return false if login check remote command
       execution failed.
+    - src/sshmasterconnection: refactor some of the channel loop and fix
+      channel/session closes.
 
  -- X2Go Release Manager <git-admin at x2go.org>  Thu, 13 Feb 2020 12:31:20 +0100
 
diff --git a/src/sshmasterconnection.cpp b/src/sshmasterconnection.cpp
index 30f9a10..68d6047 100644
--- a/src/sshmasterconnection.cpp
+++ b/src/sshmasterconnection.cpp
@@ -58,6 +58,9 @@ const QString SshMasterConnection::challenge_auth_code_prompts_[] = {
 };
 
 
+static bool SshMasterConnection::createChannelConnection (int i, int &maxsock, fd_set &rfds, ssh_channel *read_chan);
+
+
 #ifdef Q_OS_WIN
 #include <QSettings>
 // parse known_hosts file from libssh and export keys in registry to use with plink.exe
@@ -555,6 +558,7 @@ void SshMasterConnection::run()
 #endif
     }
 
+    /* Set time-out to 1 min. */
     long timeout = 60;
 
     my_ssh_session = ssh_new();
@@ -857,6 +861,7 @@ bool SshMasterConnection::sshConnect()
 
                 work_port = inferred_port & 0xFFFF;
 
+                ssh_disconnect (tmp_session);
                 ssh_free (tmp_session);
             }
         }
@@ -1970,124 +1975,13 @@ void SshMasterConnection::channelLoop()
 
         for ( int i=0; i<channelConnections.size(); ++i )
         {
-            int tcpSocket=channelConnections.at ( i ).sock;
-            if ( tcpSocket>0 )
-                FD_SET ( tcpSocket, &rfds );
-            if ( channelConnections.at ( i ).channel==0l )
-            {
-                x2goDebug<<"Creating new channel."<<endl;
-                ssh_channel channel = ssh_channel_new ( my_ssh_session );
-
-                if (!channel) {
-                    QString err = ssh_get_error (my_ssh_session);
-                    /*: Argument in this context will be a function name. */
-                    QString error_msg = tr ("%1 failed.").arg ("ssh_channel_new");
-                    emit ioErr (channelConnections[i].creator, error_msg, err);
-
-                    x2goDebug << error_msg.left (error_msg.size () - 1) << ": " << err << endl;
-
-                    continue;
-                }
-                x2goDebug<<"New channel:"<<channel<<endl;
-                channelConnections[i].channel=channel;
-                if ( tcpSocket>0 )
-                {
-                    x2goDebug << "Forwarding parameters: from remote (" << channelConnections.at (i).forwardHost << ":"
-                              << channelConnections.at (i).forwardPort << ") to local ("
-                              << channelConnections.at (i).localHost << ":" << channelConnections.at (i).localPort
-                              << ")";
-
-                    /*
-                     * Cannot support config file parsing here with pre-0.6.0 libssh versions.
-                     * There's just no way to get the inferred host and port values.
-                     */
-#if LIBSSH_VERSION_INT >= SSH_VERSION_INT (0, 6, 0)
-                    ssh_session tmp_session = ssh_new ();
-
-                    if (!tmp_session) {
-                        QString error_msg = tr ("Cannot create SSH session.");
-                        x2goDebug << error_msg;
-                        emit ioErr (channelConnections[i].creator, error_msg, "");
-                    }
-                    else {
-                        QByteArray tmp_BA = channelConnections.at (i).forwardHost.toLocal8Bit ();
-                        const int tmp_port = channelConnections.at (i).forwardPort;
-
-                        ssh_options_set (tmp_session, SSH_OPTIONS_HOST, tmp_BA.data ());
-
-                        if (tmp_port) {
-                            ssh_options_set (tmp_session, SSH_OPTIONS_PORT, &tmp_port);
-                        }
-
-                        /* The host and port might be a shorthand and zero, so fetch the actual data. */
-                        if (ssh_options_parse_config (tmp_session, NULL) < 0) {
-                            x2goDebug << "Warning: unable to parse the SSH config file.";
-                        }
-
-                        unsigned int inferred_port = 0;
-                        ssh_options_get_port (tmp_session, &inferred_port);
-                        x2goDebug << "Temporary session port after config file parse: " << inferred_port;
-
-                        char *inferred_host = NULL;
-                        ssh_options_get (tmp_session, SSH_OPTIONS_HOST, &inferred_host);
-                        x2goDebug << "Temporary session host after config file parse: " << inferred_host;
-
-                        channelConnections[i].forwardHost = QString (inferred_host);
-                        channelConnections[i].forwardPort = static_cast<int> (inferred_port);
-
-                        ssh_string_free_char (inferred_host);
-                        ssh_free (tmp_session);
-                    }
-#endif
-
-                    {
-                        QByteArray tmp_BA_forward = channelConnections.at (i).forwardHost.toLocal8Bit ();
-                        QByteArray tmp_BA_local = channelConnections.at (i).localHost.toLocal8Bit ();
-
-                        if ( ssh_channel_open_forward ( channel,
-                                                        tmp_BA_forward.data (),
-                                                        channelConnections.at ( i ).forwardPort,
-                                                        tmp_BA_local.data (),
-                                                        channelConnections.at ( i ).localPort ) != SSH_OK )
-                        {
-                            QString err=ssh_get_error ( my_ssh_session );
-                            QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_open_forward");
-                            emit ioErr ( channelConnections[i].creator, errorMsg, err );
-                            x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
-                        }
-                        else
-                        {
-                            x2goDebug<<"New channel forwarded."<<endl;
-                        }
-                    }
-                }
-                else
-                {
-                    x2goDebug<<"Executing remote: "<<channelConnections.at ( i ).command<<endl;
-                    if ( ssh_channel_open_session ( channel ) !=SSH_OK )
-                    {
-                        QString err=ssh_get_error ( my_ssh_session );
-                        QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_open_session");
-                        emit ioErr ( channelConnections[i].creator, errorMsg, err );
-                        x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
-                    }
-                    else if ( ssh_channel_request_exec ( channel, channelConnections[i].command.toLatin1() ) != SSH_OK )
-                    {
-                        QString err=ssh_get_error ( my_ssh_session );
-                        QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_request_exec");
-                        emit ioErr ( channelConnections[i].creator, errorMsg, err );
-                        x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
-                    }
-                    else
-                    {
-                        x2goDebug<<"New exec channel created."<<endl;
-                    }
-                }
-
+            // Try to make a channel connection
+            // TODO: Mabye a retry?
+            bool res = createChannelConnection (i, maxsock, rfds, read_chan);
+            if (!(res)) {
+                x2goDebug << "Connection to channel went wrong.";
+                continue;
             }
-            read_chan[i]=channelConnections.at ( i ).channel;
-            if ( tcpSocket>maxsock )
-                maxsock=tcpSocket;
         }
         channelConnectionsMutex.unlock();
         retval=ssh_select ( read_chan,out_chan,maxsock+1,&rfds,&tv );
@@ -2213,6 +2107,146 @@ void SshMasterConnection::channelLoop()
     }
 }
 
+/**
+ * Create SSH channel connection (used within a loop of channels)
+ */
+static bool SshMasterConnection::createChannelConnection (int i, int &maxsock, fd_set &rfds, ssh_channel *read_chan) {
+    int tcpSocket=channelConnections.at ( i ).sock;
+    if ( tcpSocket>0 )
+        FD_SET ( tcpSocket, &rfds );
+    if ( channelConnections.at ( i ).channel==0l )
+    {
+        x2goDebug<<"Creating new channel."<<endl;
+        ssh_channel channel = ssh_channel_new ( my_ssh_session );
+
+        if (!channel) {
+            QString err = ssh_get_error (my_ssh_session);
+            /*: Argument in this context will be a function name. */
+            QString error_msg = tr ("%1 failed.").arg ("ssh_channel_new");
+            emit ioErr (channelConnections[i].creator, error_msg, err);
+
+            x2goDebug << error_msg.left (error_msg.size () - 1) << ": " << err << endl;
+
+            return (false);
+        }
+        x2goDebug<<"New channel:"<<channel<<endl;
+        channelConnections[i].channel=channel;
+        if ( tcpSocket>0 )
+        {
+            x2goDebug << "Forwarding parameters: from remote (" << channelConnections.at (i).forwardHost << ":"
+                      << channelConnections.at (i).forwardPort << ") to local ("
+                      << channelConnections.at (i).localHost << ":" << channelConnections.at (i).localPort
+                      << ")";
+
+            /*
+             * Cannot support config file parsing here with pre-0.6.0 libssh versions.
+             * There's just no way to get the inferred host and port values.
+             */
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT (0, 6, 0)
+            ssh_session tmp_session = ssh_new ();
+
+            if (!tmp_session) {
+                QString error_msg = tr ("Cannot create SSH session.");
+                x2goDebug << error_msg;
+                emit ioErr (channelConnections[i].creator, error_msg, "");
+            }
+            else {
+                QByteArray tmp_BA = channelConnections.at (i).forwardHost.toLocal8Bit ();
+                const int tmp_port = channelConnections.at (i).forwardPort;
+
+                ssh_options_set (tmp_session, SSH_OPTIONS_HOST, tmp_BA.data ());
+
+                if (tmp_port) {
+                    ssh_options_set (tmp_session, SSH_OPTIONS_PORT, &tmp_port);
+                }
+
+                /* The host and port might be a shorthand and zero, so fetch the actual data. */
+                if (ssh_options_parse_config (tmp_session, NULL) < 0) {
+                    x2goDebug << "Warning: unable to parse the SSH config file.";
+                }
+
+                unsigned int inferred_port = 0;
+                ssh_options_get_port (tmp_session, &inferred_port);
+                x2goDebug << "Temporary session port after config file parse: " << inferred_port;
+
+                char *inferred_host = NULL;
+                ssh_options_get (tmp_session, SSH_OPTIONS_HOST, &inferred_host);
+                x2goDebug << "Temporary session host after config file parse: " << inferred_host;
+
+                channelConnections[i].forwardHost = QString (inferred_host);
+                channelConnections[i].forwardPort = static_cast<int> (inferred_port);
+
+                ssh_string_free_char (inferred_host);
+                ssh_free (tmp_session);
+            }
+#endif
+
+            {
+                QByteArray tmp_BA_forward = channelConnections.at (i).forwardHost.toLocal8Bit ();
+                QByteArray tmp_BA_local = channelConnections.at (i).localHost.toLocal8Bit ();
+
+                if ( ssh_channel_open_forward ( channel,
+                                                tmp_BA_forward.data (),
+                                                channelConnections.at ( i ).forwardPort,
+                                                tmp_BA_local.data (),
+                                                channelConnections.at ( i ).localPort ) != SSH_OK )
+                {
+                    QString err=ssh_get_error ( my_ssh_session );
+                    QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_open_forward");
+                    emit ioErr ( channelConnections[i].creator, errorMsg, err );
+                    x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
+                }
+                else
+                {
+                    x2goDebug<<"New channel forwarded."<<endl;
+                }
+            }
+        }
+        else
+        {
+            x2goDebug<<"Executing remote: "<<channelConnections.at ( i ).command<<endl;
+            if ( ssh_channel_open_session ( channel ) !=SSH_OK )
+            {
+                QString err=ssh_get_error ( my_ssh_session );
+                QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_open_session");
+
+                /* Free channel. */
+                ssh_channel_free (channel);
+
+                emit ioErr ( channelConnections[i].creator, errorMsg, err );
+                x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
+
+                return (false);
+            }
+            else if ( ssh_channel_request_exec ( channel, channelConnections[i].command.toLatin1() ) != SSH_OK )
+            {
+                QString err=ssh_get_error ( my_ssh_session );
+                QString errorMsg=tr ( "%1 failed." ).arg ("ssh_channel_request_exec");
+
+                /* Close connection and free channel. */
+                ssh_channel_close (channel);
+                ssh_channel_free (channel);
+
+                emit ioErr ( channelConnections[i].creator, errorMsg, err );
+                x2goDebug<<errorMsg.left (errorMsg.size () - 1)<<": "<<err<<endl;
+
+                return (false);
+            }
+            else
+            {
+                /* Everything is OK. */
+                x2goDebug<<"New exec channel created."<<endl;
+            }
+        }
+    }
+
+    read_chan[i]=channelConnections.at ( i ).channel;
+    if ( tcpSocket>maxsock )
+        maxsock=tcpSocket;
+
+    return (true);
+}
+
 void SshMasterConnection::finalize ( int item )
 {
     int tcpSocket=channelConnections.at ( item ).sock;

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2goclient.git


More information about the x2go-commits mailing list