Index: vino/server/libvncserver/main.c =================================================================== --- vino.orig/server/libvncserver/main.c 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/libvncserver/main.c 2006-10-13 09:44:25.000000000 +0100 @@ -447,6 +447,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc, rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width); rfbScreen->autoPort=FALSE; + rfbScreen->localOnly=FALSE; rfbScreen->rfbClientHead=0; rfbScreen->rfbPort=5900; rfbScreen->socketInitDone=FALSE; Index: vino/server/libvncserver/rfb/rfb.h =================================================================== --- vino.orig/server/libvncserver/rfb/rfb.h 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/libvncserver/rfb/rfb.h 2006-10-13 09:44:25.000000000 +0100 @@ -170,6 +170,7 @@ typedef struct _rfbScreenInfo char rfbThisHost[255]; rfbBool autoPort; + rfbBool localOnly; int rfbPort; SOCKET rfbListenSock; int maxSock; @@ -468,6 +469,7 @@ extern char rfbEndianTest; extern int rfbMaxClientWait; extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbSetLocalOnly(rfbScreenInfoPtr rfbScreen, rfbBool localOnly); extern void rfbCloseClient(rfbClientPtr cl); extern int ReadExact(rfbClientPtr cl, char *buf, int len); extern int ReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); @@ -476,7 +478,7 @@ extern void rfbProcessNewConnection(rfbS extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); extern int ConnectToTcpAddr(char* host, int port); -extern int ListenOnTCPPort(int port); +extern int ListenOnTCPPort(int port, rfbBool localOnly); /* rfbserver.c */ Index: vino/server/libvncserver/sockets.c =================================================================== --- vino.orig/server/libvncserver/sockets.c 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/libvncserver/sockets.c 2006-10-13 09:44:25.000000000 +0100 @@ -139,7 +139,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScree rfbLog("Autoprobing TCP port \n"); for (i = 5900; i < 6000; i++) { - if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i)) >= 0) { + if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i, rfbScreen->localOnly)) >= 0) { rfbScreen->rfbPort = i; break; } @@ -158,7 +158,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScree else if(rfbScreen->rfbPort>0) { rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->rfbPort); - if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort)) < 0) { + if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort, rfbScreen->localOnly)) < 0) { rfbLogPerror("ListenOnTCPPort"); return; } @@ -170,6 +170,35 @@ rfbInitSockets(rfbScreenInfoPtr rfbScree } void +rfbSetLocalOnly(rfbScreenInfoPtr rfbScreen, rfbBool localOnly) +{ + if (rfbScreen->localOnly == localOnly) + return; + + rfbScreen->localOnly = localOnly; + + if (!rfbScreen->socketInitDone) + return; + + if (rfbScreen->rfbListenSock > 0) { + FD_CLR(rfbScreen->rfbListenSock, &(rfbScreen->allFds)); + close(rfbScreen->rfbListenSock); + rfbScreen->rfbListenSock = -1; + } + + rfbLog("Re-binding socket to listen for %s VNC connections on TCP port %d\n", + rfbScreen->localOnly ? "local" : "all", rfbScreen->rfbPort); + + if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort, rfbScreen->localOnly)) < 0) { + rfbLogPerror("ListenOnTCPPort"); + return; + } + + FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = max(rfbScreen->rfbListenSock, rfbScreen->maxFd); +} + +void rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) { struct sockaddr_in addr; @@ -537,8 +566,9 @@ WriteExact(rfbClientPtr cl, const char* } int -ListenOnTCPPort(port) +ListenOnTCPPort(port, localOnly) int port; + rfbBool localOnly; { struct sockaddr_in addr; int sock; @@ -548,7 +578,7 @@ ListenOnTCPPort(port) addr.sin_family = AF_INET; addr.sin_port = htons(port); /* addr.sin_addr.s_addr = interface.s_addr; */ - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_addr.s_addr = localOnly ? htonl(INADDR_LOOPBACK) : htonl(INADDR_ANY); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; Index: vino/server/vino-prefs.c =================================================================== --- vino.orig/server/vino-prefs.c 2006-10-13 09:45:41.000000000 +0100 +++ vino.orig/server/vino-prefs.c 2006-10-13 09:45:41.000000000 +0100 @@ -32,11 +32,12 @@ #define VINO_PREFS_ENABLED VINO_PREFS_DIR "/enabled" #define VINO_PREFS_PROMPT_ENABLED VINO_PREFS_DIR "/prompt_enabled" #define VINO_PREFS_VIEW_ONLY VINO_PREFS_DIR "/view_only" +#define VINO_PREFS_LOCAL_ONLY VINO_PREFS_DIR "/local_only" #define VINO_PREFS_REQUIRE_ENCRYPTION VINO_PREFS_DIR "/require_encryption" #define VINO_PREFS_AUTHENTICATION_METHODS VINO_PREFS_DIR "/authentication_methods" #define VINO_PREFS_VNC_PASSWORD VINO_PREFS_DIR "/vnc_password" -#define VINO_N_LISTENERS 6 +#define VINO_N_LISTENERS 7 static GConfClient *vino_client = NULL; static GSList *vino_servers = NULL; @@ -45,6 +46,7 @@ static guint vino_listeners [VINO static gboolean vino_enabled = FALSE; static gboolean vino_prompt_enabled = FALSE; static gboolean vino_view_only = FALSE; +static gboolean vino_local_only = FALSE; static gboolean vino_require_encryption = FALSE; static VinoAuthMethod vino_auth_methods = VINO_AUTH_VNC; static char *vino_vnc_password = NULL; @@ -123,6 +125,30 @@ vino_prefs_view_only_changed (GConfClien } static void +vino_prefs_local_only_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry) +{ + gboolean local_only; + GSList *l; + + if (!entry->value || entry->value->type != GCONF_VALUE_BOOL) + return; + + local_only = gconf_value_get_bool (entry->value) != FALSE; + + if (vino_local_only == local_only) + return; + + vino_local_only = local_only; + + dprintf (PREFS, "Local only changed: %s\n", vino_local_only ? "(true)" : "(false)"); + + for (l = vino_servers; l; l = l->next) + vino_server_set_local_only (l->data, local_only); +} + +static void vino_prefs_require_encryption_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry) @@ -241,6 +267,7 @@ vino_prefs_create_server (GdkScreen *scr server = g_object_new (VINO_TYPE_SERVER, "prompt-enabled", vino_prompt_enabled, "view-only", vino_view_only, + "local-only", vino_local_only, "auth-methods", vino_auth_methods, "require-encryption", vino_require_encryption, "vnc-password", vino_vnc_password, @@ -284,6 +311,11 @@ vino_prefs_init (gboolean view_only) } dprintf (PREFS, "View only: %s\n", vino_view_only ? "(true)" : "(false)"); + vino_local_only = gconf_client_get_bool (vino_client, + VINO_PREFS_LOCAL_ONLY, + NULL); + dprintf (PREFS, "Local only: %s\n", vino_local_only ? "(true)" : "(false)"); + vino_require_encryption = gconf_client_get_bool (vino_client, VINO_PREFS_REQUIRE_ENCRYPTION, NULL); @@ -333,6 +365,13 @@ vino_prefs_init (gboolean view_only) vino_listeners [i] = gconf_client_notify_add (vino_client, + VINO_PREFS_LOCAL_ONLY, + (GConfClientNotifyFunc) vino_prefs_local_only_changed, + NULL, NULL, NULL); + i++; + + vino_listeners [i] = + gconf_client_notify_add (vino_client, VINO_PREFS_REQUIRE_ENCRYPTION, (GConfClientNotifyFunc) vino_prefs_require_encryption_changed, NULL, NULL, NULL); Index: vino/server/vino-server.c =================================================================== --- vino.orig/server/vino-server.c 2006-10-13 09:45:41.000000000 +0100 +++ vino.orig/server/vino-server.c 2006-10-13 09:45:41.000000000 +0100 @@ -64,6 +64,7 @@ struct _VinoServerPrivate #endif guint on_hold : 1; + guint local_only : 1; guint prompt_enabled : 1; guint view_only : 1; guint require_encryption : 1; @@ -90,6 +91,7 @@ enum PROP_ON_HOLD, PROP_PROMPT_ENABLED, PROP_VIEW_ONLY, + PROP_LOCAL_ONLY, PROP_REQUIRE_ENCRYPTION, PROP_AUTH_METHODS, PROP_VNC_PASSWORD @@ -669,6 +671,7 @@ vino_server_init_from_screen (VinoServer * 5900-6000 */ rfb_screen->rfbDeferUpdateTime = 0; + rfb_screen->localOnly = server->priv->local_only; rfb_screen->autoPort = TRUE; rfb_screen->rfbAlwaysShared = TRUE; @@ -788,6 +791,9 @@ vino_server_set_property (GObject * case PROP_VIEW_ONLY: vino_server_set_view_only (server, g_value_get_boolean (value)); break; + case PROP_LOCAL_ONLY: + vino_server_set_local_only (server, g_value_get_boolean (value)); + break; case PROP_REQUIRE_ENCRYPTION: vino_server_set_require_encryption (server, g_value_get_boolean (value)); break; @@ -825,6 +831,9 @@ vino_server_get_property (GObject *ob case PROP_VIEW_ONLY: g_value_set_boolean (value, server->priv->view_only); break; + case PROP_LOCAL_ONLY: + g_value_set_boolean (value, server->priv->local_only); + break; case PROP_REQUIRE_ENCRYPTION: g_value_set_boolean (value, server->priv->require_encryption); break; @@ -890,6 +899,14 @@ vino_server_class_init (VinoServerClass G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, + PROP_LOCAL_ONLY, + g_param_spec_boolean ("local-only", + _("Local Only"), + _("Only allow local connections"), + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, PROP_REQUIRE_ENCRYPTION, g_param_spec_boolean ("require-encryption", _("Require Encryption"), @@ -989,6 +1006,34 @@ vino_server_set_view_only (VinoServer *s } gboolean +vino_server_get_local_only (VinoServer *server) +{ + g_return_val_if_fail (VINO_IS_SERVER (server), FALSE); + + return server->priv->local_only; +} + +void +vino_server_set_local_only (VinoServer *server, + gboolean local_only) +{ + g_return_if_fail (VINO_IS_SERVER (server)); + + local_only = local_only != FALSE; + + if (server->priv->local_only != local_only) + { + server->priv->local_only = local_only; + + if (server->priv->rfb_screen != NULL) + rfbSetLocalOnly (server->priv->rfb_screen, + server->priv->local_only); + + g_object_notify (G_OBJECT (server), "local-only"); + } +} + +gboolean vino_server_get_on_hold (VinoServer *server) { g_return_val_if_fail (VINO_IS_SERVER (server), FALSE); Index: vino/server/vino-server.h =================================================================== --- vino.orig/server/vino-server.h 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/vino-server.h 2006-10-13 09:44:25.000000000 +0100 @@ -72,6 +72,9 @@ gboolean vino_server_get_pro void vino_server_set_view_only (VinoServer *server, gboolean view_only); gboolean vino_server_get_view_only (VinoServer *server); +void vino_server_set_local_only (VinoServer *server, + gboolean local_only); +gboolean vino_server_get_local_only (VinoServer *server); void vino_server_set_require_encryption (VinoServer *server, gboolean require_encryption); gboolean vino_server_get_require_encryption (VinoServer *server); Index: vino/server/vino-server.schemas.in =================================================================== --- vino.orig/server/vino-server.schemas.in 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/vino-server.schemas.in 2006-10-13 09:44:25.000000000 +0100 @@ -51,6 +51,24 @@ + /schemas/desktop/gnome/remote_access/local_only + /desktop/gnome/remote_access/local_only + gnome + bool + false + + Only allow local connections + + If true, the server will only accept connections from + localhost and network connections will be rejected. + + Set this option to true if you wish to exclusively use + a tunneling mechanism to access the server, such as ssh. + + + + + /schemas/desktop/gnome/remote_access/require_encryption /desktop/gnome/remote_access/require_encryption gnome Index: vino/server/libvncserver/CHANGES =================================================================== --- vino.orig/server/libvncserver/CHANGES 2006-10-13 09:44:25.000000000 +0100 +++ vino.orig/server/libvncserver/CHANGES 2006-10-13 09:44:25.000000000 +0100 @@ -30,6 +30,10 @@ be prompted on whether to allow authenticated clients to connect. A second level of authentication. + + Added rfbSetLocalOnly() - i.e. make the server only accept + connections from localhost. Useful for people who use + SSH tunnels. + + Removed defaultNewClientHook and made accept new clients by default. Index: vino/ChangeLog =================================================================== --- vino.orig/ChangeLog 2006-10-13 09:45:41.000000000 +0100 +++ vino.orig/ChangeLog 2006-10-13 09:45:41.000000000 +0100 @@ -0,0 +1,36 @@ +2006-10-12 Mark McLoughlin + + Add a "local_only" GConf key, for people who want to exclusively + use SSH tunnels to access the server. + + Based on patch from Shaya Potter + in bug #156242 + + * server/libvncserver/sockets.c: + (rfbInitSockets): pass rfbScreen->localOnly to ListenOnTcpPort() + (rfbSetLocalOnly): re-bind the socket if localOnly changes. + (ListenOnTcpPort): add localOnly argument and bind with + INADDR_LOOPBACK if true. + + * server/libvncserver/rfb/rfb.h: modify ListenOnTcpPort() + prototype and add rfbSetLocalOnly() + + * server/libvncserver/main.c: (rfbGetScreen): init localOnly. + + * server/libvncserver/CHANGES: add note. + + * server/vino-server.schemas.in: add local_only GConf key + + * server/vino-prefs.c: + (vino_prefs_local_only_changed), + (vino_prefs_create_server), + (vino_prefs_init): add handling for local_only key + + * server/vino-server.[ch]: + (vino_server_init_from_screen): propogate local_only to rfbScreen. + (vino_server_set_property), (vino_server_get_property), + (vino_server_class_init): add "local-only" property + (vino_server_get_local_only), + (vino_server_set_local_only): add accessors. Call rfbSetLocalOnly() + if it changes. +