Skip to content

Commit 0941de2

Browse files
committed
VNCConn: add SSH tunneling
re #200
1 parent 876fee9 commit 0941de2

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

src/VNCConn.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <cstdarg>
2626
#include <cerrno>
27+
#include <wx/file.h>
2728
#include <wx/intl.h>
2829
#include <wx/log.h>
2930
#include <wx/socket.h>
@@ -32,7 +33,6 @@
3233
#else
3334
#include <arpa/inet.h>
3435
#endif
35-
#include <libsshtunnel.h>
3636
#include "VNCConn.h"
3737

3838
bool VNCConn::libsshtunnel_initialized = false;
@@ -95,6 +95,7 @@ VNCConn::VNCConn(void* p) : condition_auth(mutex_auth)
9595
err.Printf(_("libsshtunnel initialization failed"));
9696
}
9797
}
98+
ssh_tunnel = NULL;
9899

99100
// statistics stuff
100101
do_stats = false;
@@ -227,6 +228,60 @@ wxThread::ExitCode VNCConn::Entry()
227228
{
228229
// init connection before going into main loop if this is not a listening one
229230
if (!thread_listenmode) {
231+
if (!ssh_host.IsEmpty()) {
232+
// ssh-tunneling, check whether it's password- or key-based
233+
if (ssh_password.IsOk()) {
234+
// password-based
235+
ssh_tunnel = ssh_tunnel_open_with_password(ssh_host.mb_str(),
236+
wxAtoi(ssh_port),
237+
ssh_username.mb_str(),
238+
ssh_password.GetAsString().mb_str(),
239+
cl->serverHost,
240+
cl->serverPort,
241+
this,
242+
thread_on_ssh_fingerprint_check,
243+
thread_on_ssh_error);
244+
} else {
245+
// key-based
246+
std::vector<char> ssh_priv_key;
247+
if (!ssh_priv_key_filename.IsEmpty()) {
248+
wxFile sshPrivKeyFile(ssh_priv_key_filename);
249+
if (sshPrivKeyFile.IsOpened()) {
250+
wxFileOffset fileSize = sshPrivKeyFile.Length();
251+
ssh_priv_key.resize(fileSize);
252+
sshPrivKeyFile.Read(ssh_priv_key.data(), fileSize);
253+
}
254+
}
255+
ssh_tunnel = ssh_tunnel_open_with_privkey(ssh_host.mb_str(),
256+
wxAtoi(ssh_port),
257+
ssh_username.mb_str(),
258+
ssh_priv_key.data(),
259+
ssh_priv_key.size(),
260+
ssh_priv_key_password.GetAsString().mb_str(),
261+
cl->serverHost,
262+
cl->serverPort,
263+
this,
264+
thread_on_ssh_fingerprint_check,
265+
thread_on_ssh_error);
266+
}
267+
268+
if(ssh_tunnel) {
269+
cl->serverHost = strdup("127.0.0.1");
270+
cl->serverPort = ssh_tunnel_get_port(ssh_tunnel);
271+
} else {
272+
err.Printf(_("Failure connecting to SSH server at %s:%s!"), ssh_host, ssh_port);
273+
if(thread_shutdown) {
274+
wxLogDebug("VNCConn %p: ssh_tunnel_open_* canceled.", this);
275+
thread_post_init_notify(InitState::CONNECT_CANCEL);
276+
} else {
277+
wxLogDebug("VNCConn %p: ssh_tunnel_open_* failed.", this);
278+
thread_post_init_notify(InitState::CONNECT_FAIL);
279+
}
280+
wxLogDebug("VNCConn %p: vncthread done early", this);
281+
return 0;
282+
}
283+
}
284+
230285
rfbClientLog("About to connect to '%s', port %d\n", cl->serverHost, cl->serverPort);
231286

232287
// save these for the error case
@@ -235,6 +290,10 @@ wxThread::ExitCode VNCConn::Entry()
235290

236291
if (!rfbClientConnect(cl)) {
237292
err.Printf(_("Failure connecting to server at %s:%d!"), host, port);
293+
// There might be the case that the SSH tunnel got setup alright, but connecting to the VNC server failed.
294+
// In this case we have to dispose of the tunnel explicitly here.
295+
ssh_tunnel_close(ssh_tunnel);
296+
ssh_tunnel = NULL;
238297
if(thread_shutdown) {
239298
wxLogDebug("VNCConn %p: rfbClientConnect() canceled.", this);
240299
thread_post_init_notify(InitState::CONNECT_CANCEL);
@@ -248,6 +307,10 @@ wxThread::ExitCode VNCConn::Entry()
248307
wxLogDebug("VNCConn %p: rfbClientConnect() succeeded.", this);
249308
thread_post_init_notify(InitState::CONNECT_SUCCESS);
250309
if (!rfbClientInitialise(cl)) {
310+
// There might be the case that the SSH tunnel got setup alright, but auth at the VNC server failed.
311+
// In this case we have to dispose of the tunnel explicitly here.
312+
ssh_tunnel_close(ssh_tunnel);
313+
ssh_tunnel = NULL;
251314
err.Printf(_("Failure connecting to server at %s:%d!"), host, port);
252315
if(thread_shutdown) {
253316
wxLogDebug("VNCConn %p: rfbClientInitialise() canceled.", this);
@@ -1030,8 +1093,23 @@ void VNCConn::thread_logger(const char *format, ...)
10301093
}
10311094

10321095

1096+
void VNCConn::thread_on_ssh_error(void *client, ssh_tunnel_error_t error_code, const char *error_message) {
1097+
wxString msg = wxString::Format("SSH tunnel error: %d - %s", error_code, error_message);
1098+
rfbClientErr(msg.mb_str());
1099+
VNCConn* conn = (VNCConn*) client;
1100+
conn->err.Printf(msg);
1101+
}
10331102

10341103

1104+
int VNCConn::thread_on_ssh_fingerprint_check(void *client,
1105+
const char *fingerprint,
1106+
int fingerprint_len,
1107+
const char *host) {
1108+
VNCConn* conn = (VNCConn*) client;
1109+
// TODO
1110+
return 0;
1111+
}
1112+
10351113

10361114
/*
10371115
public members
@@ -1204,6 +1282,9 @@ void VNCConn::Shutdown()
12041282
rfbCloseSocket(cl->sock);
12051283
}
12061284

1285+
ssh_tunnel_close(ssh_tunnel);
1286+
ssh_tunnel = NULL;
1287+
12071288
// end vnc thread and wait for it to get done
12081289
if(GetThread() && GetThread()->IsRunning())
12091290
{

src/VNCConn.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <wx/thread.h>
3636
#include <wx/secretstore.h>
3737
#include <wx/msgqueue.h>
38+
#include "libsshtunnel.h"
3839
#include "rfb/rfbclient.h"
3940

4041

@@ -227,8 +228,6 @@ class VNCConn: public wxEvtHandler, public wxThreadHelper
227228
wxCriticalSection mutex_multicastratio; // the fifos above are read by both the VNC and the GUI thread
228229
wxStopWatch multicastratio_stopwatch;
229230

230-
static bool libsshtunnel_initialized;
231-
232231
// this counts the ms since Init()
233232
wxStopWatch conn_stopwatch;
234233

@@ -254,6 +253,8 @@ class VNCConn: public wxEvtHandler, public wxThreadHelper
254253
wxSecretValue ssh_password;
255254
wxString ssh_priv_key_filename;
256255
wxSecretValue ssh_priv_key_password;
256+
static bool libsshtunnel_initialized;
257+
ssh_tunnel_t *ssh_tunnel;
257258

258259
// statistics
259260
bool do_stats;
@@ -349,6 +350,12 @@ class VNCConn: public wxEvtHandler, public wxThreadHelper
349350
static void thread_logger(const char *format, ...);
350351
static char* thread_getpasswd(rfbClient* client);
351352
static rfbCredential* thread_getcreds(rfbClient* client, int type);
353+
// libsshtunnel callbacks
354+
static void thread_on_ssh_error(void *client, ssh_tunnel_error_t error_code, const char *error_message);
355+
static int thread_on_ssh_fingerprint_check(void *client,
356+
const char *fingerprint,
357+
int fingerprint_len,
358+
const char *host);
352359
};
353360

354361

0 commit comments

Comments
 (0)