Exemplo n.º 1
0
void
remmina_ssh_tunnel_free (RemminaSSHTunnel* tunnel)
{
	pthread_t thread;

	thread = tunnel->thread;
	if (thread != 0)
	{
		tunnel->running = FALSE;
		pthread_cancel (thread);
		pthread_join (thread, NULL);
		tunnel->thread = 0;
	}

	if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_XPORT && tunnel->remotedisplay > 0)
	{
		channel_forward_cancel (REMMINA_SSH (tunnel)->session,
				NULL, 6000 + tunnel->remotedisplay);
	}
	if (tunnel->server_sock >= 0)
	{
		close (tunnel->server_sock);
		tunnel->server_sock = -1;
	}
	remmina_ssh_tunnel_close_all_channels (tunnel);

	g_free(tunnel->buffer);
	g_free(tunnel->channels_out);
	g_free(tunnel->dest);
	g_free(tunnel->localdisplay);

	remmina_ssh_free (REMMINA_SSH (tunnel));
}
Exemplo n.º 2
0
gboolean
remmina_ssh_tunnel_open (RemminaSSHTunnel* tunnel, const gchar *host, gint port, gint local_port)
{
	gint sock;
	gint sockopt = 1;
	struct sockaddr_in sin;

	tunnel->tunnel_type = REMMINA_SSH_TUNNEL_OPEN;
	tunnel->dest = g_strdup (host);
	tunnel->port = port;
	if (tunnel->port == 0)
	{
		REMMINA_SSH (tunnel)->error = g_strdup ("Destination port has not been assigned");
		return FALSE;
	}

	/* Create the server socket that listens on the local port */
	sock = socket (AF_INET, SOCK_STREAM, 0);
	if (sock < 0)
	{
		REMMINA_SSH (tunnel)->error = g_strdup ("Failed to create socket.");
		return FALSE;
	}
	setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof (sockopt));

	sin.sin_family = AF_INET;
	sin.sin_port = htons (local_port);
	sin.sin_addr.s_addr = inet_addr ("127.0.0.1");

	if (bind (sock, (struct sockaddr *) &sin, sizeof(sin)))
	{
		REMMINA_SSH (tunnel)->error = g_strdup ("Failed to bind on local port.");
		close (sock);
		return FALSE;
	}

	if (listen (sock, 1))
	{
		REMMINA_SSH (tunnel)->error = g_strdup ("Failed to listen on local port.");
		close (sock);
		return FALSE;
	}

	tunnel->server_sock = sock;
	tunnel->running = TRUE;

	if (pthread_create (&tunnel->thread, NULL, remmina_ssh_tunnel_main_thread, tunnel))
	{
		remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "Failed to initialize pthread.");
		tunnel->thread = 0;
		return FALSE;
	}
	return TRUE;
}
Exemplo n.º 3
0
RemminaSSHTunnel*
remmina_ssh_tunnel_new_from_file (RemminaFile *remminafile)
{
	RemminaSSHTunnel *tunnel;

	tunnel = g_new (RemminaSSHTunnel, 1);

	remmina_ssh_init_from_file (REMMINA_SSH (tunnel), remminafile);

	tunnel->tunnel_type = -1;
	tunnel->channels = NULL;
	tunnel->sockets = NULL;
	tunnel->socketbuffers = NULL;
	tunnel->num_channels = 0;
	tunnel->max_channels = 0;
	tunnel->x11_channel = NULL;
	tunnel->thread = 0;
	tunnel->running = FALSE;
	tunnel->server_sock = -1;
	tunnel->dest = NULL;
	tunnel->port = 0;
	tunnel->buffer = NULL;
	tunnel->buffer_len = 0;
	tunnel->channels_out = NULL;
	tunnel->remotedisplay = 0;
	tunnel->localdisplay = NULL;
	tunnel->init_func = NULL;
	tunnel->connect_func = NULL;
	tunnel->disconnect_func = NULL;
	tunnel->callback_data = NULL;

	return tunnel;
}
Exemplo n.º 4
0
gboolean
remmina_sftp_open (RemminaSFTP *sftp)
{
	sftp->sftp_sess = sftp_new (sftp->ssh.session);
	if (!sftp->sftp_sess)
	{
		remmina_ssh_set_error (REMMINA_SSH (sftp), _("Failed to create sftp session: %s"));
		return FALSE;
	}
	if (sftp_init (sftp->sftp_sess))
	{
		remmina_ssh_set_error (REMMINA_SSH (sftp), _("Failed to initialize sftp session: %s"));
		return FALSE;
	}
	return TRUE;
}
Exemplo n.º 5
0
void
remmina_sftp_free (RemminaSFTP *sftp)
{
	if (sftp->sftp_sess)
	{
		sftp_free (sftp->sftp_sess);
		sftp->sftp_sess = NULL;
	}
	remmina_ssh_free (REMMINA_SSH (sftp));
}
Exemplo n.º 6
0
RemminaSFTP*
remmina_sftp_new_from_ssh (RemminaSSH *ssh)
{
	RemminaSFTP *sftp;

	sftp = g_new (RemminaSFTP, 1);

	remmina_ssh_init_from_ssh (REMMINA_SSH (sftp), ssh);

	sftp->sftp_sess = NULL;

	return sftp;
}
Exemplo n.º 7
0
RemminaSFTP*
remmina_sftp_new_from_file (RemminaFile *remminafile)
{
	RemminaSFTP *sftp;

	sftp = g_new (RemminaSFTP, 1);

	remmina_ssh_init_from_file (REMMINA_SSH (sftp), remminafile);

	sftp->sftp_sess = NULL;

	return sftp;
}
Exemplo n.º 8
0
RemminaSSHShell*
remmina_ssh_shell_new_from_ssh (RemminaSSH *ssh)
{
	RemminaSSHShell *shell;

	shell = g_new0 (RemminaSSHShell, 1);

	remmina_ssh_init_from_ssh (REMMINA_SSH (shell), ssh);

	shell->master = -1;
	shell->slave = -1;

	return shell;
}
Exemplo n.º 9
0
RemminaSSHShell*
remmina_ssh_shell_new_from_file (RemminaFile *remminafile)
{
	RemminaSSHShell *shell;

	shell = g_new0 (RemminaSSHShell, 1);

	remmina_ssh_init_from_file (REMMINA_SSH (shell), remminafile);

	shell->master = -1;
	shell->slave = -1;
	shell->exec = g_strdup (remmina_file_get_string (remminafile, "exec"));

	return shell;
}
Exemplo n.º 10
0
gboolean
remmina_ssh_tunnel_xport (RemminaSSHTunnel *tunnel, gboolean bindlocalhost)
{
	tunnel->tunnel_type = REMMINA_SSH_TUNNEL_XPORT;
	tunnel->bindlocalhost = bindlocalhost;
	tunnel->running = TRUE;

	if (pthread_create (&tunnel->thread, NULL, remmina_ssh_tunnel_main_thread, tunnel))
	{
		remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "Failed to initialize pthread.");
		tunnel->thread = 0;
		return FALSE;
	}
	return TRUE;
}
Exemplo n.º 11
0
gboolean
remmina_ssh_tunnel_x11 (RemminaSSHTunnel *tunnel, const gchar *cmd)
{
	tunnel->tunnel_type = REMMINA_SSH_TUNNEL_X11;
	tunnel->dest = g_strdup (cmd);
	tunnel->running = TRUE;

	if (pthread_create (&tunnel->thread, NULL, remmina_ssh_tunnel_main_thread, tunnel))
	{
		remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "Failed to initialize pthread.");
		tunnel->thread = 0;
		return FALSE;
	}
	return TRUE;
}
Exemplo n.º 12
0
gboolean
remmina_ssh_tunnel_reverse (RemminaSSHTunnel *tunnel, gint port, gint local_port)
{
	tunnel->tunnel_type = REMMINA_SSH_TUNNEL_REVERSE;
	tunnel->port = port;
	tunnel->localport = local_port;
	tunnel->running = TRUE;

	if (pthread_create (&tunnel->thread, NULL, remmina_ssh_tunnel_main_thread, tunnel))
	{
		remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "Failed to initialize pthread.");
		tunnel->thread = 0;
		return FALSE;
	}
	return TRUE;
}
Exemplo n.º 13
0
static gpointer
remmina_ssh_tunnel_main_thread_proc (gpointer data)
{
	RemminaSSHTunnel *tunnel = (RemminaSSHTunnel*) data;
	gchar *ptr;
	ssize_t len = 0, lenw = 0;
	fd_set set;
	struct timeval timeout;
	GTimeVal t1, t2;
	glong diff;
	ssh_channel channel = NULL;
	gboolean first = TRUE;
	gboolean disconnected;
	gint sock;
	gint maxfd;
	gint i;
	gint ret;
	struct sockaddr_in sin;

	g_get_current_time (&t1);
	t2 = t1;

	switch (tunnel->tunnel_type)
	{
		case REMMINA_SSH_TUNNEL_OPEN:
		/* Accept a local connection */
		sock = accept (tunnel->server_sock, NULL, NULL);
		if (sock < 0)
		{
			REMMINA_SSH (tunnel)->error = g_strdup ("Failed to accept local socket");
			tunnel->thread = 0;
			return NULL;
		}

		if ((channel = channel_new (tunnel->ssh.session)) == NULL)
		{
			close (sock);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to createt channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		/* Request the SSH server to connect to the destination */
		if (channel_open_forward (channel, tunnel->dest, tunnel->port, "127.0.0.1", 0) != SSH_OK)
		{
			close (sock);
			channel_close (channel);
			channel_free (channel);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to connect to the SSH tunnel destination: %s"));
			tunnel->thread = 0;
			return NULL;
		}
		remmina_ssh_tunnel_add_channel (tunnel, channel, sock);
		break;

		case REMMINA_SSH_TUNNEL_X11:
		if ((tunnel->x11_channel = channel_new (tunnel->ssh.session)) == NULL)
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to create channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		if (!remmina_public_get_xauth_cookie (tunnel->localdisplay, &ptr))
		{
			remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "%s", ptr);
			g_free(ptr);
			tunnel->thread = 0;
			return NULL;
		}
		if (channel_open_session (tunnel->x11_channel) ||
				channel_request_x11 (tunnel->x11_channel, TRUE, NULL, ptr,
						gdk_screen_get_number (gdk_screen_get_default ())))
		{
			g_free(ptr);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to open channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		g_free(ptr);
		if (channel_request_exec (tunnel->x11_channel, tunnel->dest))
		{
			ptr = g_strdup_printf(_("Failed to execute %s on SSH server : %%s"), tunnel->dest);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), ptr);
			g_free(ptr);
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;

		case REMMINA_SSH_TUNNEL_XPORT:
		/* Detect the next available port starting from 6010 on the server */
		for (i = 10; i <= MAX_X_DISPLAY_NUMBER; i++)
		{
			if (channel_forward_listen (REMMINA_SSH (tunnel)->session,
							(tunnel->bindlocalhost ? "localhost" : NULL), 6000 + i, NULL))
			{
				continue;
			}
			else
			{
				tunnel->remotedisplay = i;
				break;
			}
		}
		if (tunnel->remotedisplay < 1)
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to request port forwarding : %s"));
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;

		case REMMINA_SSH_TUNNEL_REVERSE:
		if (channel_forward_listen (REMMINA_SSH (tunnel)->session, NULL, tunnel->port, NULL))
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to request port forwarding : %s"));
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;
	}

	tunnel->buffer_len = 10240;
	tunnel->buffer = g_malloc (tunnel->buffer_len);

	/* Start the tunnel data transmittion */
	while (tunnel->running)
	{
		if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_XPORT ||
				tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11 ||
				tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
		{
			if (first)
			{
				first = FALSE;
				/* Wait for a period of time for the first incoming connection */
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11)
				{
					channel = channel_accept_x11 (tunnel->x11_channel, 15000);
				}
				else
				{
					channel = channel_forward_accept (REMMINA_SSH (tunnel)->session, 15000);
				}
				if (!channel)
				{
					remmina_ssh_set_application_error (REMMINA_SSH (tunnel), _("No response from the server."));
					if (tunnel->disconnect_func)
					{
						(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
					}
					tunnel->thread = 0;
					return NULL;
				}
				if (tunnel->connect_func)
				{
					(*tunnel->connect_func) (tunnel, tunnel->callback_data);
				}
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
				{
					/* For reverse tunnel, we only need one connection. */
					channel_forward_cancel (REMMINA_SSH (tunnel)->session, NULL, tunnel->port);
				}
			}
			else if (tunnel->tunnel_type != REMMINA_SSH_TUNNEL_REVERSE)
			{
				/* Poll once per some period of time if no incoming connections.
				 * Don't try to poll continuously as it will significantly slow down the loop */
				g_get_current_time (&t1);
				diff = (t1.tv_sec - t2.tv_sec) * 10 + (t1.tv_usec - t2.tv_usec) / 100000;
				if (diff > 1)
				{
					if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11)
					{
						channel = channel_accept_x11 (tunnel->x11_channel, 0);
					}
					else
					{
						channel = channel_forward_accept (REMMINA_SSH (tunnel)->session, 0);
					}
					if (channel == NULL)
					{
						t2 = t1;
					}
				}
			}

			if (channel)
			{
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
				{
					sin.sin_family = AF_INET;
					sin.sin_port = htons (tunnel->localport);
					sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
					sock = socket (AF_INET, SOCK_STREAM, 0);
					if (connect (sock, (struct sockaddr *) &sin, sizeof (sin)) < 0)
					{
						remmina_ssh_set_application_error (REMMINA_SSH (tunnel),
								"Cannot connect to local port %i.", tunnel->localport);
						close (sock);
						sock = -1;
					}
				}
				else
				{
					sock = remmina_public_open_xdisplay (tunnel->localdisplay);
				}
				if (sock >= 0)
				{
					remmina_ssh_tunnel_add_channel (tunnel, channel, sock);
				}
				else
				{
					/* Failed to create unix socket. Will this happen? */
					channel_close (channel);
					channel_free (channel);
				}
				channel = NULL;
			}
		}

		if (tunnel->num_channels <= 0)
		{
			/* No more connections. We should quit */
			break;
		}

		timeout.tv_sec = 0;
		timeout.tv_usec = 200000;

		FD_ZERO (&set);
		maxfd = 0;
		for (i = 0; i < tunnel->num_channels; i++)
		{
			if (tunnel->sockets[i] > maxfd)
			{
				maxfd = tunnel->sockets[i];
			}
			FD_SET (tunnel->sockets[i], &set);
		}

		ret = ssh_select (tunnel->channels, tunnel->channels_out, maxfd + 1, &set, &timeout);
		if (!tunnel->running) break;
		if (ret == SSH_EINTR) continue;
		if (ret == -1) break;

		i = 0;
		while (tunnel->running && i < tunnel->num_channels)
		{
			disconnected = FALSE;
			if (FD_ISSET (tunnel->sockets[i], &set))
			{
				while (!disconnected &&
						(len = read (tunnel->sockets[i], tunnel->buffer, tunnel->buffer_len)) > 0)
				{
					for (ptr = tunnel->buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw)
					{
						lenw = channel_write (tunnel->channels[i], (char*) ptr, len);
						if (lenw <= 0)
						{
							disconnected = TRUE;
							break;
						}
					}
				}
				if (len == 0) disconnected = TRUE;
			}
			if (disconnected)
			{
				remmina_ssh_tunnel_remove_channel (tunnel, i);
				continue;
			}
			i++;
		}
		if (!tunnel->running) break;

		i = 0;
		while (tunnel->running && i < tunnel->num_channels)
		{
			disconnected = FALSE;

			if (!tunnel->socketbuffers[i])
			{
				len = channel_poll (tunnel->channels[i], 0);
				if (len == SSH_ERROR || len == SSH_EOF)
				{
					disconnected = TRUE;
				}
				else if (len > 0)
				{
					tunnel->socketbuffers[i] = remmina_ssh_tunnel_buffer_new (len);
					len = channel_read_nonblocking (tunnel->channels[i], tunnel->socketbuffers[i]->data, len, 0);
					if (len <= 0)
					{
						disconnected = TRUE;
					}
					else
					{
						tunnel->socketbuffers[i]->len = len;
					}
				}
			}

			if (!disconnected && tunnel->socketbuffers[i])
			{
				for (lenw = 0; tunnel->socketbuffers[i]->len > 0;
						tunnel->socketbuffers[i]->len -= lenw, tunnel->socketbuffers[i]->ptr += lenw)
				{
					lenw = write (tunnel->sockets[i], tunnel->socketbuffers[i]->ptr, tunnel->socketbuffers[i]->len);
					if (lenw == -1 && errno == EAGAIN && tunnel->running)
					{
						/* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal
						 * buffer is full. We need read the pending bytes from the socket first. so here we simply
						 * break, leave the buffer there, and continue with other data */
						break;
					}
					if (lenw <= 0)
					{
						disconnected = TRUE;
						break;
					}
				}
				if (tunnel->socketbuffers[i]->len <= 0)
				{
					remmina_ssh_tunnel_buffer_free (tunnel->socketbuffers[i]);
					tunnel->socketbuffers[i] = NULL;
				}
			}

			if (disconnected)
			{
				remmina_ssh_tunnel_remove_channel (tunnel, i);
				continue;
			}
			i++;
		}
	}

	remmina_ssh_tunnel_close_all_channels (tunnel);

	return NULL;
}
Exemplo n.º 14
0
static gpointer
remmina_ssh_shell_thread (gpointer data)
{
	RemminaSSHShell *shell = (RemminaSSHShell*) data;
	fd_set fds;
	struct timeval timeout;
	ssh_channel channel = NULL;
	ssh_channel ch[2], chout[2];
	gchar *buf = NULL;
	gint buf_len;
	gint len;
	gint i, ret;

	LOCK_SSH (shell)

	if ((channel = channel_new (REMMINA_SSH (shell)->session)) == NULL ||
			channel_open_session (channel))
	{
		UNLOCK_SSH (shell)
		remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to open channel : %s");
		if (channel) channel_free (channel);
		shell->thread = 0;
		return NULL;
	}

	channel_request_pty (channel);
	if (shell->exec && shell->exec[0])
	{
		ret = channel_request_exec (channel, shell->exec);
	}
	else
	{
		ret = channel_request_shell (channel);
	}
	if (ret)
	{
		UNLOCK_SSH (shell)
		remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to request shell : %s");
		channel_close (channel);
		channel_free (channel);
		shell->thread = 0;
		return NULL;
	}

	shell->channel = channel;

	UNLOCK_SSH (shell)

	buf_len = 1000;
	buf = g_malloc (buf_len + 1);

	ch[0] = channel;
	ch[1] = NULL;

	while (!shell->closed)
	{
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		FD_ZERO (&fds);
		FD_SET (shell->master, &fds);

		ret = ssh_select (ch, chout, shell->master + 1, &fds, &timeout);
		if (ret == SSH_EINTR) continue;
		if (ret == -1) break;

		if (FD_ISSET (shell->master, &fds))
		{
			len = read (shell->master, buf, buf_len);
			if (len <= 0) break;
			LOCK_SSH (shell)
			channel_write (channel, buf, len);
			UNLOCK_SSH (shell)
		}
		for (i = 0; i < 2; i++)
		{
			LOCK_SSH (shell)
			len = channel_poll (channel, i);
			UNLOCK_SSH (shell)
			if (len == SSH_ERROR || len == SSH_EOF)
			{
				shell->closed = TRUE;
				break;
			}
			if (len <= 0) continue;
			if (len > buf_len)
			{
				buf_len = len;
				buf = (gchar*) g_realloc (buf, buf_len + 1);
			}
			LOCK_SSH (shell)
			len = channel_read_nonblocking (channel, buf, len, i);
			UNLOCK_SSH (shell)
			if (len <= 0)
			{
				shell->closed = TRUE;
				break;
			}
			while (len > 0)
			{
				ret = write (shell->master, buf, len);
				if (ret <= 0) break;
				len -= ret;
			}
		}
	}
Exemplo n.º 15
0
			fclose (local_file);
			local_file = g_fopen (local_path, "wb");
			if (!local_file)
			{
				remmina_sftp_client_thread_set_error (client, task, _("Error creating file %s."), local_path);
				return FALSE;
			}
			size = 0;
			break;

			case GTK_RESPONSE_APPLY:
			break;
		}
	}

	tmp = remmina_ssh_unconvert (REMMINA_SSH (sftp), remote_path);
	remote_file = sftp_open (sftp->sftp_sess, tmp, O_RDONLY, 0);
	g_free(tmp);

	if (!remote_file)
	{
		fclose (local_file);
		remmina_sftp_client_thread_set_error (client, task, _("Error opening file %s on server. %s"),
				remote_path, ssh_get_error (REMMINA_SSH (client->sftp)->session));
		return FALSE;
	}

	if (size > 0)
	{
		if (sftp_seek64 (remote_file, size) < 0)
		{
Exemplo n.º 16
0
static gpointer
remmina_plugin_sftp_main_thread (gpointer data)
{
	RemminaProtocolWidget *gp = (RemminaProtocolWidget*) data;
	RemminaPluginSftpData *gpdata;
	RemminaFile *remminafile;
	RemminaSSH *ssh;
	RemminaSFTP *sftp = NULL;
	gboolean cont = FALSE;
	gint ret;
	const gchar *cs;

	pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
	CANCEL_ASYNC

	gpdata = (RemminaPluginSftpData*) g_object_get_data (G_OBJECT(gp), "plugin-data");

	ssh = g_object_get_data (G_OBJECT(gp), "user-data");
	if (ssh)
	{
		/* Create SFTP connection based on existing SSH session */
		sftp = remmina_sftp_new_from_ssh (ssh);
		if (remmina_ssh_init_session (REMMINA_SSH (sftp)) &&
				remmina_ssh_auth (REMMINA_SSH (sftp), NULL) > 0 &&
				remmina_sftp_open (sftp))
		{
			cont = TRUE;
		}
	}
	else
	{
		/* New SFTP connection */
		remminafile = remmina_plugin_service->protocol_plugin_get_file (gp);
		remmina_plugin_service->file_set_string (remminafile, "ssh_server",
				remmina_plugin_service->file_get_string (remminafile, "server"));

		sftp = remmina_sftp_new_from_file (remminafile);
		while (1)
		{
			if (!remmina_ssh_init_session (REMMINA_SSH (sftp)))
			{
				remmina_plugin_service->protocol_plugin_set_error (gp, "%s", REMMINA_SSH (sftp)->error);
				break;
			}

			ret = remmina_ssh_auth_gui (REMMINA_SSH (sftp),
					REMMINA_INIT_DIALOG (remmina_protocol_widget_get_init_dialog (gp)), TRUE);
			if (ret == 0)
			{
				remmina_plugin_service->protocol_plugin_set_error (gp, "%s", REMMINA_SSH (sftp)->error);
			}
			if (ret <= 0) break;

			if (!remmina_sftp_open (sftp))
			{
				remmina_plugin_service->protocol_plugin_set_error (gp, "%s", REMMINA_SSH (sftp)->error);
				break;
			}

			cs = remmina_plugin_service->file_get_string (remminafile, "execpath");
			if (cs && cs[0])
			{
				remmina_ftp_client_set_dir (REMMINA_FTP_CLIENT (gpdata->client), cs);
			}

			cont = TRUE;
			break;
		}
	}
	if (!cont)
	{
		if (sftp) remmina_sftp_free (sftp);
		IDLE_ADD ((GSourceFunc) remmina_plugin_service->protocol_plugin_close_connection, gp);
		return NULL;
	}

	remmina_sftp_client_open (REMMINA_SFTP_CLIENT (gpdata->client), sftp);
	/* RemminaSFTPClient owns the object, we just take the reference */
	gpdata->sftp = sftp;

	remmina_plugin_service->protocol_plugin_emit_signal (gp, "connect");

	gpdata->thread = 0;
	return NULL;
}