This is an automated email from the git hooks/post-receive script. x2go pushed a change to branch master in repository libx2goclient. from c2c779f src/x2goclient-network-ssh.c: fix comment regarding wait call to subprocess. new 02816aa src/x2goclient-openssh-version.{c,h}: rework x2goclient_openssh_version_parse () to return _Bool. new 7b0c49d src/x2goclient-network-ssh.c: make openssh-version property read-only. new 6c8255e src/x2goclient-network-ssh.{c,h}: implement x2goclient_network_ssh_fetch_openssh_version (). The 3 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Summary of changes: src/x2goclient-network-ssh.c | 178 ++++++++++++++++++++++++++++++++++++++- src/x2goclient-network-ssh.h | 2 + src/x2goclient-openssh-version.c | 16 +++- src/x2goclient-openssh-version.h | 4 +- 4 files changed, 194 insertions(+), 6 deletions(-) -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository libx2goclient. commit 02816aa91a796c267d141ca158ccae718a76846c Author: Mihai Moldovan <ionic@ionic.de> Date: Thu May 14 19:45:51 2020 +0200 src/x2goclient-openssh-version.{c,h}: rework x2goclient_openssh_version_parse () to return _Bool. GError is typically optional and passing NULL to it is a valid way to ignore *the specifics* of errors. This said, we still need to have a way to determine whether an error happened or not - and hence, if the parsing was successful. --- src/x2goclient-openssh-version.c | 16 ++++++++++++---- src/x2goclient-openssh-version.h | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/x2goclient-openssh-version.c b/src/x2goclient-openssh-version.c index a071938..7f4479a 100644 --- a/src/x2goclient-openssh-version.c +++ b/src/x2goclient-openssh-version.c @@ -115,16 +115,18 @@ G_DEFINE_BOXED_TYPE (X2GoClientOpenSSHVersion, x2goclient_openssh_version, &x2go }\ } while (0) -void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr) { +_Bool x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr) { + _Bool ret = FALSE; + /* Basic sanity checks on struct and string. */ if (!(openssh_version)) { g_set_error_literal (gerr, ERROR_QUARK, X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_STRUCT, "No version struct passed, cannot store extracted information."); - return; + return (ret); } if (!(version_string)) { g_set_error_literal (gerr, ERROR_QUARK, X2GOCLIENT_OPENSSH_VERSION_ERROR_INVALID_VERSION_STRING, "No version string passed, cannot extract information."); - return; + return (ret); } X2GoClientOpenSSHVersion *struct_work_copy = x2goclient_openssh_version_copy (openssh_version); @@ -142,7 +144,7 @@ void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version x2goclient_openssh_version_free (struct_work_copy); struct_work_copy = NULL; - return; + return (ret); } /* Skip preamble. */ @@ -307,8 +309,12 @@ void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version if (vers_err) { x2goclient_openssh_version_free (struct_work_copy); struct_work_copy = NULL; + + return (ret); } + ret = TRUE; + /* Scan for a comma which should follow any additional version data. */ const gchar *end = g_strstr_len (tmp, -1, ","); if (!(end)) { @@ -340,4 +346,6 @@ void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version /* Lastly, free data. */ x2goclient_openssh_version_free (struct_work_copy); struct_work_copy = NULL; + + return (ret); } diff --git a/src/x2goclient-openssh-version.h b/src/x2goclient-openssh-version.h index 47f65b4..9c434d3 100644 --- a/src/x2goclient-openssh-version.h +++ b/src/x2goclient-openssh-version.h @@ -25,6 +25,8 @@ #ifndef x2goclient_openssh_version_h #define x2goclient_openssh_version_h +#include <stdbool.h> + #include <glib-object.h> G_BEGIN_DECLS @@ -76,7 +78,7 @@ enum { }; -void x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr); +_Bool x2goclient_openssh_version_parse (X2GoClientOpenSSHVersion *openssh_version, const gchar *version_string, GError **gerr); G_END_DECLS -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository libx2goclient. commit 7b0c49dac74ff649c107a5c4266daa1d492bb09d Author: Mihai Moldovan <ionic@ionic.de> Date: Thu May 14 20:17:29 2020 +0200 src/x2goclient-network-ssh.c: make openssh-version property read-only. --- src/x2goclient-network-ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c index 9a4557f..04c03ed 100644 --- a/src/x2goclient-network-ssh.c +++ b/src/x2goclient-network-ssh.c @@ -137,7 +137,7 @@ static void x2goclient_network_ssh_class_init (X2GoClientNetworkSSHClass *klass) _("The OpenSSH client version number, parsed in a custom " "structure."), X2GOCLIENT_TYPE_OPENSSH_VERSION, - G_PARAM_WRITABLE); + G_PARAM_READABLE); g_object_class_install_properties (object_class, X2GO_NET_SSH_N_PROPERTIES, net_ssh_obj_properties); -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository libx2goclient. commit 6c8255efdea2f7bb3b80758ed44691ba5ff429e8 Author: Mihai Moldovan <ionic@ionic.de> Date: Thu May 14 22:27:01 2020 +0200 src/x2goclient-network-ssh.{c,h}: implement x2goclient_network_ssh_fetch_openssh_version (). --- src/x2goclient-network-ssh.c | 176 +++++++++++++++++++++++++++++++++++++++++++ src/x2goclient-network-ssh.h | 2 + 2 files changed, 178 insertions(+) diff --git a/src/x2goclient-network-ssh.c b/src/x2goclient-network-ssh.c index 04c03ed..0029d2c 100644 --- a/src/x2goclient-network-ssh.c +++ b/src/x2goclient-network-ssh.c @@ -30,6 +30,7 @@ #include <arpa/inet.h> #include <stdlib.h> #include <errno.h> +#include <limits.h> #include <glib.h> #include <glib/gi18n.h> @@ -122,6 +123,7 @@ static GSocketAddress* x2goclient_network_ssh_parse_sockspec_alias (const GStrin static GSocketAddress* x2goclient_network_ssh_parse_sockspec (X2GoClientNetwork *parent, const GString *sockspec); static gboolean x2goclient_network_ssh_kill_subprocesses (X2GoClientNetworkSSH *self); static gboolean x2goclient_network_ssh_parent_connect (X2GoClientNetwork *parent, GError **gerr); +static gboolean x2goclient_network_ssh_fetch_openssh_version (X2GoClientNetworkSSH *self, GError **gerr); static void x2goclient_network_ssh_class_init (X2GoClientNetworkSSHClass *klass) { @@ -920,3 +922,177 @@ static gboolean x2goclient_network_ssh_parent_connect (X2GoClientNetwork *parent return (ret); } + +static gboolean x2goclient_network_ssh_fetch_openssh_version (X2GoClientNetworkSSH *self, GError **gerr) { + gboolean ret = FALSE; + + g_return_val_if_fail (X2GOCLIENT_IS_NETWORK_SSH (self), ret); + g_return_val_if_fail (((gerr == NULL) || (*gerr == NULL)), ret); + + GPtrArray *ssh_cmd = g_ptr_array_new_with_free_func (&x2goclient_clear_strings); + g_ptr_array_add (ssh_cmd, g_strdup ("ssh")); + g_ptr_array_add (ssh_cmd, g_strdup ("-V")); + g_ptr_array_add (ssh_cmd, NULL); + + { + gchar *tmp = NULL; + for (gsize i = 0; i < ssh_cmd->len; ++i) { + gchar *tmp_old = tmp; + + if (tmp) { + tmp = g_strdup_printf ("%s [%s]", tmp_old, (gchar *)g_ptr_array_index (ssh_cmd, i)); + } + else { + tmp = g_strdup_printf ("[%s]", (gchar *)g_ptr_array_index (ssh_cmd, i)); + } + + g_free (tmp_old); + tmp_old = NULL; + } + + g_log (NULL, G_LOG_LEVEL_DEBUG, "Fetching OpenSSH version via: %s", tmp); + + g_free (tmp); + tmp = NULL; + } + + GError *ssh_err = NULL; + GSubprocess *ssh_proc = g_subprocess_newv ((const gchar* const*)(ssh_cmd->pdata), G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, &ssh_err); + + ret = (ssh_proc != NULL); + + if (ret) { + g_log (NULL, G_LOG_LEVEL_DEBUG, "OpenSSH version fetching process started/executed successfully!"); + + if (ssh_err) { + g_log (NULL, G_LOG_LEVEL_DEBUG, "Successful execution, but ssh_err set? Weird, here's the message: %s", ssh_err->message); + } + + GCancellable *ssh_proc_comm_cancel = g_cancellable_new (); + g_clear_error (&ssh_err); + + GBytes *ssh_stdout = NULL, *ssh_stderr = NULL; + if (!(g_subprocess_communicate (ssh_proc, NULL, ssh_proc_comm_cancel, &ssh_stdout, &ssh_stderr, &ssh_err))) { + g_propagate_prefixed_error (gerr, ssh_err, "Communication with OpenSSH version fetching subprocess failed: "); + } + else { + gsize ssh_stdout_size = 0, ssh_stderr_size = 0; + const gchar *ssh_stdout_str = g_bytes_get_data (ssh_stdout, &ssh_stdout_size), + *ssh_stderr_str = g_bytes_get_data (ssh_stderr, &ssh_stderr_size); + int ssh_stdout_size_sanitized = 0, ssh_stderr_size_sanitized = 0; + gchar *ssh_stdout_str_sanitized = 0, *ssh_stderr_str_sanitized = NULL; + + /* Sanity check on output size. */ + if (INT_MAX < ssh_stdout_size) { + g_log (NULL, G_LOG_LEVEL_WARNING, "OpenSSH returned more than %d bytes on stdout, this is unusual and will be truncated.", INT_MAX); + + ssh_stdout_size_sanitized = INT_MAX; + } + else { + ssh_stdout_size_sanitized = ssh_stdout_size; + } + + if (ssh_stdout_str) { + /* + * Do NOT use g_strndup () here. + * + * It might sound exactly like what we want, but really isn't. + * + * The issue is that g_strndup () will always allocate an n-bytes-sized + * buffer and optionally pad the string with NULL bytes. + * + * That's not really a problem if the string actually is to be + * truncated, since in that case the result will be smaller than the + * original string anyway, but a huge problem if the string small. + * + * In the latter case, we don't want to create a useless 2 GiB string. + * + * Interestingly, POSIX describes strndup as allocating memory "as if + * by using malloc ()", but doesn't mention the actual resulting size. + * In the informal section, buffer sizes are described as either + * (size + 1) or ((strnlen (s, size)) + 1), which, again, could lead + * to the same problem. + */ + ssh_stdout_str_sanitized = g_strdup_printf ("%.*s", ssh_stdout_size_sanitized, ssh_stdout_str); + } + else { + ssh_stderr_size_sanitized = ssh_stderr_size; + } + + if (INT_MAX < ssh_stderr_size) { + g_log (NULL, G_LOG_LEVEL_WARNING, "OpenSSH returned more than %d bytes on stderr, this is unusual and will be truncated.", INT_MAX); + + ssh_stderr_size_sanitized = INT_MAX; + } + + if (ssh_stderr_str) { + ssh_stderr_str_sanitized = g_strdup_printf ("%.*s", ssh_stderr_size_sanitized, ssh_stderr_str); + } + + g_log (NULL, G_LOG_LEVEL_DEBUG, "Stdout:\n>>>%.*s<<<\nStderr:\n>>>%.*s<<<", ssh_stdout_size_sanitized, ssh_stdout_str_sanitized, ssh_stderr_size_sanitized, ssh_stderr_str_sanitized); + + if (ssh_stdout_size_sanitized) { + g_log (NULL, G_LOG_LEVEL_WARNING, "OpenSSH version command wrote data on stdout, this is unexpected and will be ignored.\nData: %*.s", ssh_stdout_size_sanitized, ssh_stdout_str_sanitized); + } + + if (!(ssh_stderr_size_sanitized)) { + g_set_error_literal (gerr, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_OPENSSH_VERSION_NO_STDERR, "OpenSSH version command wrote nothing to stderr, this is unexpected. Can't parse version string."); + ret = FALSE; + } + else { + X2GoClientOpenSSHVersion *version = x2goclient_openssh_version_new (); + + if (!(version)) { + g_set_error_literal (gerr, X2GOCLIENT_NETWORK_SSH_ERROR, X2GOCLIENT_NETWORK_SSH_ERROR_OPENSSH_VERSION_ALLOCATE, "Unable to allocate buffe for OpenSSH version structure - memory issues?"); + ret = FALSE; + } + else { + /* gerr is supposed to be empty at that point. */ + g_assert ((gerr == NULL) || (*gerr == NULL)); + + ret = x2goclient_openssh_version_parse (version, ssh_stderr_str_sanitized, gerr); + + if (ret) { + /* Everything went well, copy to the property. + * + * ... unfortunately, the actual property is read-only (which + * totally makes sense because we only want this class to handle + * it), so we'll have to duplicate a bit of code and can't use the + * GObject property setter directly. + */ + x2goclient_openssh_version_free (self->openssh_version); + self->openssh_version = version; + } + else { + /* Get rid of the version struct. It's bogus anyway. */ + x2goclient_openssh_version_free (version); + } + + version = NULL; + } + } + + g_free (ssh_stdout_str_sanitized); + g_free (ssh_stderr_str_sanitized); + + g_bytes_unref (ssh_stdout); + g_bytes_unref (ssh_stderr); + } + + g_clear_object (&ssh_proc_comm_cancel); + ssh_proc_comm_cancel = NULL; + } + else { + g_propagate_prefixed_error (gerr, ssh_err, "OpenSSH vesion fetching process didn't execute/start successfully! Error: "); + } + + g_clear_error (&ssh_err); + + g_clear_object (&ssh_proc); + ssh_proc = NULL; + + g_ptr_array_unref (ssh_cmd); + ssh_cmd = NULL; + + return (ret); +} diff --git a/src/x2goclient-network-ssh.h b/src/x2goclient-network-ssh.h index cd3f99f..3e5ce29 100644 --- a/src/x2goclient-network-ssh.h +++ b/src/x2goclient-network-ssh.h @@ -66,6 +66,8 @@ enum { X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_INET_ADDR_NULL, X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_NATIVE_FETCH, X2GOCLIENT_NETWORK_SSH_ERROR_CONNECT_SOCK_ADDR_UNKNOWN, + X2GOCLIENT_NETWORK_SSH_ERROR_OPENSSH_VERSION_NO_STDERR, + X2GOCLIENT_NETWORK_SSH_ERROR_OPENSSH_VERSION_ALLOCATE, }; -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/libx2goclient.git