[X2Go-Commits] [libx2goclient] 03/03: src/x2goclient-network-ssh.{c, h}: implement x2goclient_network_ssh_fetch_openssh_version ().
git-admin at x2go.org
git-admin at x2go.org
Thu May 14 22:28:28 CEST 2020
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 at 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
More information about the x2go-commits
mailing list