[X2Go-Commits] [libx2goclient] 04/08: src/x2goclient-network-ssh.c: implement FQDN/alias socket parsing.

git-admin at x2go.org git-admin at x2go.org
Sat Aug 3 12:36:33 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 309c0119a6fbb539401f37f2221d0c2406aef96a
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Wed Jul 31 21:28:08 2019 +0200

    src/x2goclient-network-ssh.c: implement FQDN/alias socket parsing.
---
 src/x2goclient-network-ssh.c | 123 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 1 deletion(-)

diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c
index 3bb1285..768b974 100644
--- a/src/x2goclient-network-ssh.c
+++ b/src/x2goclient-network-ssh.c
@@ -55,7 +55,8 @@
 enum {
   X2GOCLIENT_NETWORK_SSH_ERROR_PORT_CONV = 0,
   X2GOCLIENT_NETWORK_SSH_ERROR_IPV6_CONV,
-  X2GOCLIENT_NETWORK_SSH_ERROR_IPV4_CONV
+  X2GOCLIENT_NETWORK_SSH_ERROR_IPV4_CONV,
+  X2GOCLIENT_NETWORK_SSH_ERROR_ALIAS_CONV
 };
 
 
@@ -77,6 +78,19 @@ static void x2goclient_network_options_ssh_init (X2GoClientNetworkOptionsSSH *se
 }
 
 
+/*
+ * Custom sockaddr structure used to represent socket endpoints based on a FQDN
+ * or ssh_config-specific host alias.
+ */
+typedef struct sockaddr_ho {
+  sa_family_t sho_family;
+  in_port_t   sho_port;
+  char        sho_addr[256];
+} sockaddr_ho;
+
+#define AF_HOST 33
+
+
 struct _X2GoClientNetworkSSH {
   X2GoClientNetwork parent_class;
 };
@@ -168,6 +182,18 @@ static guint16 x2goclient_network_ssh_parse_sockspec_port (const GString *portsp
   return (ret);
 }
 
+static GString* x2goclient_network_ssh_sanitize_sockspec (const GString *sockspec) {
+  GString *ret = NULL;
+
+  gchar *sanitize_sockspec = g_strdup (sockspec->str);
+  g_strstrip (sanitize_sockspec);
+  ret = g_string_new (g_strstrip (sanitize_sockspec));
+  g_free (sanitize_sockspec);
+  sanitize_sockspec = NULL;
+
+  return (ret);
+}
+
 static GSocketAddress* x2goclient_network_ssh_parse_sockspec_ip (const GString *sockspec, const gboolean want_v6, GError **err) {
   GSocketAddress *ret = NULL;
 
@@ -340,6 +366,85 @@ static GSocketAddress* x2goclient_network_ssh_parse_sockspec_ip (const GString *
   return (ret);
 }
 
+static GSocketAddress* x2goclient_network_ssh_parse_sockspec_alias (const GString *sockspec, GError **err) {
+  GSocketAddress *ret = NULL;
+
+  g_return_val_if_fail (err == NULL || *err == NULL, ret);
+
+  /* We're free to sanitize the string now. */
+  GString *work_sockspec = x2goclient_network_ssh_sanitize_sockspec (sockspec);
+
+  gchar *tmp_start = work_sockspec->str,
+        *tmp_end = NULL;
+  GString *address = NULL;
+  guint16 port = 0;
+
+  /*
+   * For FQDN or alias addresses (like for IPv4 addresses), we'll accept any
+   * input of the form address:port.
+   */
+  tmp_end = g_strstr_len (tmp_start, -1, ":");
+
+  if (tmp_end) {
+    --tmp_end;
+
+    address = g_string_new_len (tmp_start, tmp_end - tmp_start);
+  }
+  else {
+    address = g_string_new_len (tmp_start, work_sockspec->len);
+  }
+
+  /*
+   * Check validity.
+   *
+   * FIXME: for now only the size, but maybe we should do extra checks on the
+   *        name.
+   */
+  const gsize max_len = (sizeof (((struct sockaddr_ho*)(NULL))->sho_addr) - 1);
+  if (max_len < address->len) {
+    g_set_error (err, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_ALIAS_CONV, "Unable to parse FQDN or alias pseudo-address: name too long, expected at most %" G_GSIZE_FORMAT " bytes, got %" G_GSIZE_FORMAT " bytes.", max_len, address->len);
+  }
+
+  if (!err) {
+    if (tmp_end) {
+      /*
+       * No encapsulation whatsoever, so the colon must be at the next
+       * position.
+       */
+      GString *portspec = g_string_new (tmp_end + 1);
+
+      GError *tmp_err = NULL;
+      port = x2goclient_network_ssh_parse_sockspec_port (portspec, &tmp_err);
+      g_string_free (portspec, TRUE);
+      portspec = NULL;
+
+      if (tmp_err) {
+        g_set_error (err, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_ALIAS_CONV, "Unable to parse FQDN or alias pseudo-address: %s", tmp_err->message);
+        g_clear_error (&tmp_err);
+      }
+    }
+  }
+
+  if (!err) {
+    /*
+     * Parsed everything successfully so far, so create native socket address
+     * object.
+     */
+    struct sockaddr_ho tmp_sockaddr = { AF_HOST, };
+    g_strlcpy (tmp_sockaddr.sho_addr, address->str, max_len + 1);
+    tmp_sockaddr.sho_port = port;
+    ret = g_native_socket_address_new (&tmp_sockaddr, sizeof (struct sockaddr_ho));
+  }
+
+  g_string_free (work_sockspec, TRUE);
+  work_sockspec = NULL;
+
+  g_string_free (address, TRUE);
+  address = NULL;
+
+  return (ret);
+}
+
 static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetworkSSH *self, const GString *sockspec) {
   GSocketAddress *ret = NULL;
 
@@ -378,6 +483,22 @@ static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetworkS
         g_clear_error (&tmp_err);
       }
     }
+
+    if (!ret) {
+      g_log (NULL, G_LOG_LEVEL_INFO, "Failed to parse socket specification as IPv4 socket.\n"
+                                     "Continuing with FQDN/alias parsing.");
+
+      GError *tmp_err = NULL;
+      ret = x2goclient_network_ssh_parse_sockspec_alias (sockspec, &tmp_err);
+
+      if (tmp_err) {
+        g_assert (!ret);
+
+        g_log (NULL, G_LOG_LEVEL_WARNING, "Socket specification looked like a FQDN or alias socket, but parsing as such failed: %s", tmp_err->message);
+
+        g_clear_error (&tmp_err);
+      }
+    }
   }
 
   return ret;

--
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