Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--config.h.in1
-rw-r--r--remmina/src/remmina_ssh.c60
3 files changed, 59 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c38ed5e0..56b1d943d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,6 +84,7 @@ check_include_files(sys/param.h HAVE_SYS_PARAM_H)
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_files(arpa/inet.h HAVE_ARPA_INET_H)
check_include_files(netinet/in.h HAVE_NETINET_IN_H)
+check_include_files(netinet/tcp.h HAVE_NETINET_TCP_H)
check_include_files(termios.h HAVE_TERMIOS_H)
check_include_files(netdb.h HAVE_NETDB_H)
check_include_files(fcntl.h HAVE_FCNTL_H)
diff --git a/config.h.in b/config.h.in
index e75364419..769295740 100644
--- a/config.h.in
+++ b/config.h.in
@@ -5,6 +5,7 @@
#cmakedefine HAVE_SYS_SOCKET_H
#cmakedefine HAVE_ARPA_INET_H
#cmakedefine HAVE_NETINET_IN_H
+#cmakedefine HAVE_NETINET_TCP_H
#cmakedefine HAVE_TERMIOS_H
#cmakedefine HAVE_NETDB_H
#cmakedefine HAVE_FCNTL_H
diff --git a/remmina/src/remmina_ssh.c b/remmina/src/remmina_ssh.c
index fd0aa1ab7..22247a0b6 100644
--- a/remmina/src/remmina_ssh.c
+++ b/remmina/src/remmina_ssh.c
@@ -77,6 +77,16 @@
#include "remmina_pref.h"
#include "remmina/remmina_trace_calls.h"
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#define SSH_SOCKET_TCP_KEEPIDLE 5
+#define SSH_SOCKET_TCP_KEEPCNT 3
+#define SSH_SOCKET_TCP_KEEPINTVL 3
+/* Remember to lower SSH_SOCKET_TCP_USER_TIMEOUT to 4 when kernel bug 108191 will be fixed */
+#define SSH_SOCKET_TCP_USER_TIMEOUT 9
+#endif
+
+
/*-----------------------------------------------------------------------------*
* SSH Base *
*-----------------------------------------------------------------------------*/
@@ -401,22 +411,29 @@ remmina_ssh_init_session (RemminaSSH *ssh)
{
TRACE_CALL("remmina_ssh_init_session");
gint verbosity;
+#ifdef HAVE_NETINET_TCP_H
+ socket_t sshsock;
+ gint optval;
+#endif
ssh->callback = g_new0 (struct ssh_callbacks_struct, 1);
- ssh->callback->userdata = ssh;
/* Init & startup the SSH session */
ssh->session = ssh_new ();
ssh_options_set (ssh->session, SSH_OPTIONS_HOST, ssh->server);
ssh_options_set (ssh->session, SSH_OPTIONS_PORT, &ssh->port);
ssh_options_set (ssh->session, SSH_OPTIONS_USER, ssh->user);
+
+ ssh_callbacks_init(ssh->callback);
if (remmina_log_running ())
{
verbosity = remmina_pref.ssh_loglevel;
ssh_options_set (ssh->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh->callback->log_function = remmina_ssh_log_callback;
+ /* Reset libssh legacy userdata. This is a workaround for a libssh bug */
+ ssh_set_log_userdata(ssh->session);
}
- ssh_callbacks_init (ssh->callback);
+ ssh->callback->userdata = ssh;
ssh_set_callbacks(ssh->session, ssh->callback);
/* As the latest parse the ~/.ssh/config file */
@@ -430,6 +447,34 @@ remmina_ssh_init_session (RemminaSSH *ssh)
return FALSE;
}
+#ifdef HAVE_NETINET_TCP_H
+ /* Set keepalive on ssh socket, so we can keep firewalls awaken and detect
+ * when we loss the tunnel */
+ sshsock = ssh_get_fd(ssh->session);
+ if (sshsock >= 0) {
+ optval = 1;
+ if(setsockopt (sshsock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval)) < 0){
+ remmina_log_printf ("[SSH] TCP KeepAlive not set\n");
+ }
+ optval = SSH_SOCKET_TCP_KEEPIDLE;
+ if (setsockopt(sshsock, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof (optval)) < 0) {
+ remmina_log_printf ("[SSH] TCP_KEEPIDLE not set\n");
+ }
+ optval = SSH_SOCKET_TCP_KEEPCNT;
+ if (setsockopt(sshsock, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof (optval)) < 0) {
+ remmina_log_printf ("[SSH] TCP_KEEPCNT not set\n");
+ }
+ optval = SSH_SOCKET_TCP_KEEPINTVL;
+ if (setsockopt(sshsock, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof (optval)) < 0) {
+ remmina_log_printf ("[SSH] TCP_KEEPINTVL not set\n");
+ }
+ optval = SSH_SOCKET_TCP_USER_TIMEOUT;
+ if (setsockopt(sshsock, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, sizeof (optval)) < 0) {
+ remmina_log_printf ("[SSH] TCP_USER_TIMEOUT not set\n");
+ }
+ }
+#endif
+
/* Try the "none" authentication */
if (ssh_userauth_none (ssh->session, NULL) == SSH_AUTH_SUCCESS)
{
@@ -1028,14 +1073,19 @@ remmina_ssh_tunnel_main_thread_proc (gpointer data)
if (lenw <= 0)
{
disconnected = TRUE;
+ remmina_ssh_set_error (REMMINA_SSH (tunnel), "ssh_channel_write() returned an error: %s");
break;
}
}
}
- if (len == 0) disconnected = TRUE;
+ if (len == 0) {
+ remmina_ssh_set_error (REMMINA_SSH (tunnel), "read on tunnel listening socket returned an error: %s");
+ disconnected = TRUE;
+ }
}
if (disconnected)
{
+ remmina_log_printf("[SSH] tunnel has been disconnected. Reason: %s\n", REMMINA_SSH(tunnel)->error);
remmina_ssh_tunnel_remove_channel (tunnel, i);
continue;
}
@@ -1053,6 +1103,7 @@ remmina_ssh_tunnel_main_thread_proc (gpointer data)
len = ssh_channel_poll (tunnel->channels[i], 0);
if (len == SSH_ERROR || len == SSH_EOF)
{
+ remmina_ssh_set_error (REMMINA_SSH (tunnel), "ssh_channel_poll() returned an error : %s");
disconnected = TRUE;
}
else if (len > 0)
@@ -1061,6 +1112,7 @@ remmina_ssh_tunnel_main_thread_proc (gpointer data)
len = ssh_channel_read_nonblocking (tunnel->channels[i], tunnel->socketbuffers[i]->data, len, 0);
if (len <= 0)
{
+ remmina_ssh_set_error (REMMINA_SSH (tunnel), "ssh_channel_read_nonblocking() returned an error : %s");
disconnected = TRUE;
}
else
@@ -1085,6 +1137,7 @@ remmina_ssh_tunnel_main_thread_proc (gpointer data)
}
if (lenw <= 0)
{
+ remmina_ssh_set_error (REMMINA_SSH (tunnel), "write on tunnel listening socket returned an error: %s");
disconnected = TRUE;
break;
}
@@ -1098,6 +1151,7 @@ remmina_ssh_tunnel_main_thread_proc (gpointer data)
if (disconnected)
{
+ remmina_log_printf("[SSH] tunnel has been disconnected. Reason: %s\n", REMMINA_SSH(tunnel)->error);
remmina_ssh_tunnel_remove_channel (tunnel, i);
continue;
}