[X2Go-Commits] [libx2goclient] 02/02: src/x2goclient-network-ssh.c: continue implementation of x2goclient_network_ssh_parse_sockspec().

git-admin at x2go.org git-admin at x2go.org
Sat Jul 27 13:52:10 CEST 2019


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

x2go pushed a commit to branch master
in repository libx2goclient.

commit 89dff4d6f8c3966724287c4efb986876d6dd925f
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Sat Jul 27 13:51:54 2019 +0200

    src/x2goclient-network-ssh.c: continue implementation of x2goclient_network_ssh_parse_sockspec().
    
    Additionally, start splitting the function up, because it's getting pretty complicated.
---
 src/x2goclient-network-ssh.c | 167 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 135 insertions(+), 32 deletions(-)

diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c
index 4b95b6d..702f279 100644
--- a/src/x2goclient-network-ssh.c
+++ b/src/x2goclient-network-ssh.c
@@ -24,12 +24,20 @@
 
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib/gprintf.h>
+#include <glib/gstdio.h>
 #include <gmodule.h>
 #include <gio/gio.h>
+#include <gio/gunixsocketaddress.h>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -57,36 +65,87 @@ struct _X2GoClientNetworkSSH {
 
 G_DEFINE_TYPE (X2GoClientNetworkSSH, x2goclient_network_ssh, X2GOCLIENT_TYPE_NETWORK);
 
-static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetworkSSH *self, const GString *sockspec) {
+static GSocketAddress* x2goclient_network_ssh_parse_sockspec_unix_socket (const GString *sockspec) {
   GSocketAddress *ret = NULL;
 
-  if (sockspec) {
+  /*
+   * N.B.: do *not* sanitize the string, since UNIX sockets are allowed to
+   *       start and end on whitespace.
+   */
+  gboolean is_socket = FALSE;
+  GUnixSocketAddressType socket_type = G_UNIX_SOCKET_ADDRESS_PATH;
+
+      /* Max. path len without terminating NULL byte */
+  if ((sizeof (((struct sockaddr_un*)(NULL))->sun_path) - 1) >= sockspec->len) {
+    /* Smells like a UNIX socket so far. */
+    if (0 == sockspec->str[0]) {
+      /*
+       * Abstract UNIX sockets are specified with a preceding NULL byte.
+       * We can't check for them, since they have no equivalent on the file
+       * system.
+       *
+       * Encountering this means that we have to trust the socket exists.
+       */
+      is_socket = TRUE;
+      socket_type = G_UNIX_SOCKET_ADDRESS_ABSTRACT;
+    }
+    else {
+      /* Check if such a file exists on the file system. */
+      GStatBuf tmp_stat_buf = { 0 };
+      if (0 == g_stat (sockspec->str, &tmp_stat_buf)) {
+        /* File exists, let's check if this is a socket. */
+        if ((tmp_stat_buf.st_mode & S_IFMT) == S_IFSOCK) {
+          is_socket = TRUE;
+        }
+      }
+    }
+
+    if (is_socket) {
+      ret = g_unix_socket_address_new_with_type (sockspec->str, sockspec->len, socket_type);
+    }
+  }
+
+  return (ret);
+}
+
+static gint32 x2goclient_network_ssh_parse_sockspec_port (const GString *portspec) {
+  gint32 ret = -1;
+
+  if (':' == portspec->str[0]) {
     /*
-     * Check if it's possibly a UNIX socket.
-     *
-     * N.B.: do *not* sanitize the string, since UNIX sockets are allowed to
-     *       start and end on whitespace.
+     * In the worst case, portspec->str[1] will point to a terminating NULL
+     * character, but that's non-critical.
      */
-    gboolean is_abstract = FALSE;
-
-        /* Max. path len without terminating NULL byte */
-    if ((sizeof (((struct sockaddr_un*)(NULL))->sun_path) - 1) >= sockspec->len) {
-      /* Smells like a UNIX socket so far. */
-      if (0 == sockspec->str[0]) {
-        /*
-         * Abstract UNIX sockets are specified with a preceding NULL byte.
-         * We can't check for them, since they have no equivalent on the file
-         * system.
-         *
-         * Encountering this means that we have to trust the socket exists.
-         */
-        is_abstract = TRUE;
-      }
-      else {
-        /* Check if such a file exists on the file system. */
-        ... /* Parse error is fine here. */
-      }
+    errno = 0;
+    long long conv = strtoll (portspec->str + 1, NULL, 10);
+
+    if (0 != errno) {
+      g_log (NULL, G_LOG_LEVEL_WARNING, "Unable to convert port specifier, invalid input.");
     }
+    else if ((1 << 16) <= conv)  {
+      g_log (NULL, G_LOG_LEVEL_WARNING, "Port specifier out of range (too big), invalid input.");
+    }
+    else if (0 >= conv) {
+      g_log (NULL, G_LOG_LEVEL_WARNING, "Port specifier out of range (negative or zero), invalid input.");
+    }
+    else {
+      ret = conv;
+    }
+  }
+  else {
+    /* No specifier found, assume default port. */
+    ret = 0;
+  }
+
+  return (ret);
+}
+
+static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetworkSSH *self, const GString *sockspec) {
+  GSocketAddress *ret = NULL;
+
+  if (sockspec) {
+    /* Check if it's possibly a UNIX socket. */
+    ret = x2goclient_network_ssh_parse_sockspec_unix_socket (sockspec);
 
     if (!ret) {
       /* Must be not a UNIX socket, continue checking for IPv6 addresses. */
@@ -94,20 +153,64 @@ static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetworkS
       /* We're free to sanitize the string now. */
       g_strstrip (sockspec->str);
 
+      gboolean could_be_v6 = FALSE;
       gboolean is_v6 = FALSE;
-      gchar *v6_end = NULL;
+      gchar *tmp_start = sockspec->str;
+      gchar *tmp_end = NULL;
+      GString *v6_address = NULL;
+      GString *address = NULL;
+      guint16 port = 0;
 
       /*
-       * As a very common convention, IPv6 address have to be encapsulated in
-       * brackets, check for that.
+       * As a very common convention, IPv6 addresses have to be encapsulated in
+       * brackets if an additional port is specified, check for that.
        */
-      if ('[' == sockspec->str[0]) {
-        v6_end = g_strstr_len (sockspec->str, -1, "]");
+      if ('[' == tmp_start[0]) {
+        tmp_end = g_strstr_len (tmp_start, -1, "]");
+
+        if (tmp_end) {
+          /*
+           * Looks like a bracket-encapsulated IPv6 address so far.
+           * See if that checks out.
+           */
+          could_be_v6 = TRUE;
+          ++tmp_start;
+          --tmp_end;
+
+          v6_address = g_string_new_len (tmp_start, tmp_end - tmp_start);
+        }
+      }
+      else {
+        v6_address = g_string_new_len (tmp_start, sockspec->len);
+      }
 
-        if (v6_end) {
-          is_v6 = TRUE;
+      /* Check for an IPv6 address first. */
+      char binary_rep[128] = { 0 };
+      is_v6 = (1 == inet_pton (AF_INET6, v6_address->str, &binary_rep));
+
+      if (is_v6) {
+        /* Passed a valid IPv6 address. */
+        if (tmp_end) {
+          /*
+           * Specification in brackets, so check if there's a port specifier.
+           *
+           * tmp_end points to the last part of the address, so tmp_end + 1
+           * will point to the terminating bracket. tmp_end + 2 can, in the
+           * worst case, point to the terminating NULL character, which is
+           * fine.
+           */
+          GString *portspec = g_string_new (tmp_end + 2);
+          gint32 port_parse = x2goclient_network_ssh_parse_sockspec_port (portspec);
+          g_string_free (portspec, TRUE);
+          portspec = NULL;
+        }
+        else {
+          address = g_string_new (v6_address->str);
         }
       }
+      else {
+        /*  */
+      }
     }
   }
 

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


More information about the x2go-commits mailing list