From bded9bf2a29f0845c6f82235f035c1b697599c3d Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Aug 28 2007 23:56:06 +0000 Subject: Support for connecting over an SSH tunnel --- diff --git a/src/main.c b/src/main.c index ff5b7be..24d5c3c 100644 --- a/src/main.c +++ b/src/main.c @@ -32,7 +32,8 @@ #include #include #include - +#include +#include #define DEBUG 0 #ifdef DEBUG @@ -100,6 +101,11 @@ static void viewer_shutdown(GtkWidget *src G_GNUC_UNUSED, void *dummy G_GNUC_UNU gtk_main_quit(); } +static void viewer_quit(GtkWidget *src G_GNUC_UNUSED, GtkWidget *vnc) +{ + viewer_shutdown(src, NULL, vnc); +} + static void viewer_connected(GtkWidget *vnc G_GNUC_UNUSED) { DEBUG_LOG("Connected to server\n"); @@ -292,7 +298,7 @@ static GtkWidget *viewer_build_file_menu(VncDisplay *vnc) quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL); gtk_menu_append(GTK_MENU(filemenu), quit); - g_signal_connect(quit, "activate", GTK_SIGNAL_FUNC(viewer_shutdown), vnc); + g_signal_connect(quit, "activate", GTK_SIGNAL_FUNC(viewer_quit), vnc); return file; } @@ -529,13 +535,14 @@ static int viewer_extract_vnc_graphics(virDomainPtr dom, char **port) return ret; } -static int viewer_extract_host(const char *uristr, char **host, char **transport) +static int viewer_extract_host(const char *uristr, char **host, char **transport, char **user) { xmlURIPtr uri; char *offset; *host = NULL; *transport = NULL; + *user = NULL; if (uristr == NULL || !strcasecmp(uristr, "xen")) @@ -551,6 +558,15 @@ static int viewer_extract_host(const char *uristr, char **host, char **transport xmlFreeURI(uri); return -1; } + if (uri->user) { + *user = strdup(uri->user); + if (!*user) { + xmlFreeURI(uri); + free(*host); + *host =NULL; + return -1; + } + } offset = strchr(uri->scheme, '+'); if (offset) { @@ -558,6 +574,8 @@ static int viewer_extract_host(const char *uristr, char **host, char **transport if (!*transport) { free(*host); *host = NULL; + free(*user); + *user = NULL; xmlFreeURI(uri); return -1; } @@ -566,6 +584,65 @@ static int viewer_extract_host(const char *uristr, char **host, char **transport return 0; } +static int viewer_open_tunnel(const char **cmd) +{ + int fd[2]; + pid_t pid; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0) + return -1; + + pid = fork(); + if (pid == -1) { + close(fd[0]); + close(fd[1]); + return -1; + } + + if (pid == 0) { /* child */ + close(fd[0]); + close(0); + close(1); + if (dup(fd[1]) < 0) + _exit(1); + if (dup(fd[1]) < 0) + _exit(1); + close(fd[1]); + execvp("ssh", (char *const*)cmd); + _exit(1); + } + close(fd[1]); + return fd[0]; +} + + +static int viewer_open_tunnel_ssh(const char *host, const char *port, const char *user) +{ + const char *cmd[6]; + char *dst = malloc((user ? strlen(user) + 1: 0) + strlen(host) + 1); + int ret; + if (!dst) + return -1; + if (user) { + strcpy(dst, user); + strcat(dst, "@"); + strcat(dst, host); + } else { + strcpy(dst, host); + } + + cmd[0] = "ssh"; + cmd[1] = dst; + cmd[2] = "nc"; + cmd[3] = "localhost"; + cmd[4] = port; + cmd[5] = NULL; + + ret = viewer_open_tunnel(cmd); + free(dst); + return ret; +} + int main(int argc, char **argv) { @@ -589,6 +666,8 @@ int main(int argc, char **argv) char *host = NULL; char *port = NULL; char *transport = NULL; + char *user = NULL; + int fd = -1; while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) { switch (ch) { @@ -645,12 +724,17 @@ int main(int argc, char **argv) } usleep(300*1000); } while (!port); + virDomainFree(dom); + virConnectClose(conn); - if (viewer_extract_host(uri, &host, &transport) < 0) { + if (viewer_extract_host(uri, &host, &transport, &user) < 0) { fprintf(stderr, "unable to determine hostname for URI %s\n", uri); return 5; } - DEBUG_LOG("Remote host is %s and transport %s\n", host, transport ? transport : ""); + DEBUG_LOG("Remote host is %s and transport %s user %s\n", host, transport ? transport : "", user ? user : ""); + + if (strcasecmp(transport, "ssh") == 0) + fd = viewer_open_tunnel_ssh(host, port, user); vnc = vnc_display_new(); window = viewer_build_window(VNC_DISPLAY(vnc)); @@ -659,7 +743,10 @@ int main(int argc, char **argv) vnc_display_set_keyboard_grab(VNC_DISPLAY(vnc), TRUE); vnc_display_set_pointer_grab(VNC_DISPLAY(vnc), TRUE); - vnc_display_open_host(VNC_DISPLAY(vnc), host, port); + if (fd >= 0) + vnc_display_open_fd(VNC_DISPLAY(vnc), fd); + else + vnc_display_open_host(VNC_DISPLAY(vnc), host, port); gtk_main();