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