Skip to content

Commit 544ac9f

Browse files
authored
Merge branch 'apache:main' into configurable-clipboard-limit
2 parents a894101 + 32dbdfa commit 544ac9f

File tree

9 files changed

+147
-77
lines changed

9 files changed

+147
-77
lines changed

configure.ac

+16-35
Original file line numberDiff line numberDiff line change
@@ -657,59 +657,40 @@ then
657657
fi
658658

659659
#
660-
# libVNCserver support for the rfbSetDesktopSizeMsg message, which allows the
661-
# VNC client to send its dimensions to the server, requesting that the server
662-
# resize itself to match. If libvnc lacks this message, remote resize will
663-
# be completely disabled.
660+
# libVNCserver support for the rfbSetDesktopSizeMsg message and the screen
661+
# data structure, both of which are required in order to properly request that
662+
# a remote server resize its screen to match the dimensions that the client
663+
# sends. If libvnc lacks either this message or the screen data structure
664+
# remote resize will be completely disabled.
664665
#
665666

666667
if test "x${have_libvncserver}" = "xyes"
667668
then
668669

669-
have_vnc_size_msg=yes
670+
have_vnc_resize_support=yes
670671
AC_CHECK_TYPE([rfbSetDesktopSizeMsg],
671-
[], [have_vnc_size_msg=no],
672+
[], [have_vnc_resize_support=no],
672673
[[#include <rfb/rfbproto.h>]])
673674

674-
if test "x${have_vnc_size_msg}" = "xno"
675+
AC_CHECK_MEMBERS([rfbClient.screen],
676+
[], [have_vnc_resize_support=no],
677+
[[#include <rfb/rfbclient.h>]])
678+
679+
if test "x${have_vnc_resize_support}" = "xno"
675680
then
676681
AC_MSG_WARN([
677682
--------------------------------------------------------
678-
No support for rfbSetDesktopSizeMsg in libvncclient.
679-
VNC support for remote display resize will be disabled.
683+
The libvncclient library lacks support for either the
684+
rfbSetDesktopSizeMsg message or for extended screen
685+
support. Resizing of remote displays will be disabled.
680686
--------------------------------------------------------])
681687
else
682-
AC_DEFINE([LIBVNC_HAS_SIZE_MSG],,
688+
AC_DEFINE([LIBVNC_HAS_RESIZE_SUPPORT],,
683689
[Whether VNC client will support sending desktop size messages.])
684690
fi
685691

686692
fi
687693

688-
#
689-
# libVNCserver support for the screen structure, which allows for tracking
690-
# multiple screens that are part of a larger frame buffer display. If this
691-
# feature is missing, the VNC client may still attempt to send the display
692-
# resize messages, but will assume that there is a one-to-one relationship
693-
# between the screen size and the frame buffer size (which is currently safe
694-
# for Guacamole, as it lacks multi-monitor/screen support).
695-
#
696-
697-
if test "x${have_libvncserver}" = "xyes"
698-
then
699-
700-
have_vnc_screen=yes
701-
AC_CHECK_MEMBERS([rfbClient.screen],
702-
[], [have_vnc_screen=no],
703-
[[#include <rfb/rfbclient.h>]])
704-
705-
if test "x${have_vnc_screen}" = "xyes"
706-
then
707-
AC_DEFINE([LIBVNC_CLIENT_HAS_SCREEN],,
708-
[Whether rfbClient contains the screen data structure.])
709-
fi
710-
711-
fi
712-
713694
#
714695
# libVNCserver support for the requestedResize member, which enables the
715696
# client to pause frame buffer updates during a resize operation. If support

src/common-ssh/ssh.c

+65-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* under the License.
1818
*/
1919

20+
#include "common/string.h"
21+
2022
#include "common-ssh/key.h"
2123
#include "common-ssh/ssh.h"
2224
#include "common-ssh/user.h"
@@ -41,6 +43,7 @@
4143
#include <netinet/in.h>
4244
#include <pthread.h>
4345
#include <pwd.h>
46+
#include <stdbool.h>
4447
#include <stddef.h>
4548
#include <stdlib.h>
4649
#include <string.h>
@@ -64,7 +67,7 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
6467
/**
6568
* A list of ciphers that are both FIPS-compliant, and OpenSSL-supported.
6669
*/
67-
#define FIPS_COMPLIANT_CIPHERS "aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,aes192-cbc,aes256-cbc"
70+
#define FIPS_COMPLIANT_CIPHERS "[email protected],[email protected],aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,aes192-cbc,aes256-cbc"
6871

6972
#ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS
7073
/**
@@ -412,6 +415,59 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
412415

413416
}
414417

418+
/**
419+
* Verifies if given algorithms are supported by libssh2.
420+
* Writes log messages if an algorithm is not supported or
421+
* could not get the list of supported algorithms from libssh2.
422+
*
423+
* @param client
424+
* The Guacamole client that is using SSH.
425+
*
426+
* @param session
427+
* The session associated with the user to be authenticated.
428+
*
429+
* @param method_type
430+
* One of the libssh2 Method Type constants for libssh2_session_method_pref().
431+
*
432+
* @param algs
433+
* A string with preferred list of algorithms, for example FIPS_COMPLIANT_CIPHERS.
434+
*
435+
*/
436+
static void check_if_algs_are_supported(guac_client* client, LIBSSH2_SESSION* session,
437+
int method_type, const char* algs) {
438+
439+
/* Request the list of supported algorithms/cyphers from libssh2. */
440+
const char** supported_algs;
441+
int supported_algs_count =
442+
libssh2_session_supported_algs(session, method_type, &supported_algs);
443+
444+
if (supported_algs_count > 0) {
445+
char** preferred_algs = guac_split(algs, ',');
446+
for (int i = 0; preferred_algs[i]; i++) {
447+
bool found = false;
448+
/* Check if the algorithm is found in the libssh2 supported list. */
449+
for (int j = 0; j < supported_algs_count; j++) {
450+
if (strcmp(preferred_algs[i], supported_algs[j]) == 0) {
451+
found = true;
452+
break;
453+
}
454+
}
455+
if (!found) {
456+
guac_client_log(client, GUAC_LOG_WARNING,
457+
"Preferred algorithm/cipher '%s' is not supported by libssh2", preferred_algs[i]);
458+
}
459+
}
460+
guac_mem_free(preferred_algs);
461+
/* should free if supported_algs_count is a positive number. */
462+
libssh2_free(session, supported_algs);
463+
}
464+
else {
465+
guac_client_log(client, GUAC_LOG_WARNING,
466+
"libssh2 reports that no ciphers/algorithms are supported. This may be a bug in libssh2. "
467+
"If the SSH connection fails, it may not be possible to log the cause here.");
468+
}
469+
}
470+
415471
guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
416472
const char* hostname, const char* port, guac_common_ssh_user* user,
417473
int timeout, int keepalive, const char* host_key,
@@ -445,8 +501,16 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
445501
* https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp2906.pdf
446502
*/
447503
if (guac_fips_enabled()) {
504+
/*
505+
* The following algorithm check is only to simplify debugging.
506+
* libssh2_session_method_pref() ignores unsupported methods.
507+
* So they are not sent to the remote host during protocol negotiation anyways.
508+
*/
509+
check_if_algs_are_supported(client, session, LIBSSH2_METHOD_KEX, FIPS_COMPLIANT_KEX_ALGORITHMS);
448510
libssh2_session_method_pref(session, LIBSSH2_METHOD_KEX, FIPS_COMPLIANT_KEX_ALGORITHMS);
511+
check_if_algs_are_supported(client, session, LIBSSH2_METHOD_CRYPT_CS, FIPS_COMPLIANT_CIPHERS);
449512
libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_CS, FIPS_COMPLIANT_CIPHERS);
513+
check_if_algs_are_supported(client, session, LIBSSH2_METHOD_CRYPT_SC, FIPS_COMPLIANT_CIPHERS);
450514
libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_SC, FIPS_COMPLIANT_CIPHERS);
451515
}
452516

src/protocols/vnc/display.c

+8-26
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, in
146146

147147
}
148148

149-
#ifdef LIBVNC_HAS_SIZE_MSG
149+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
150150
/**
151151
* This function does the actual work of sending the message to the RFB/VNC
152152
* server to request the resize, and then makes sure that the client frame
@@ -173,7 +173,11 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
173173
/* Get the Guacamole client data */
174174
guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
175175

176-
#ifdef LIBVNC_CLIENT_HAS_SCREEN
176+
if (client->screen.width == 0 || client->screen.height == 0) {
177+
guac_client_log(gc, GUAC_LOG_WARNING, "Screen data has not been initialized, yet.");
178+
return FALSE;
179+
}
180+
177181
guac_client_log(gc, GUAC_LOG_TRACE,
178182
"Current screen size is %ix%i; setting new size %ix%i\n",
179183
rfbClientSwap16IfLE(client->screen.width),
@@ -185,19 +189,6 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
185189
guac_client_log(gc, GUAC_LOG_WARNING, "Screen size has not changed, not sending update.");
186190
return FALSE;
187191
}
188-
#else
189-
/* Don't send an update if the screen appears to be uninitialized. */
190-
if (client->width == 0 || client->height == 0) {
191-
guac_client_log(gc, GUAC_LOG_WARNING, "Framebuffer has not been initialized, cannot send resize.");
192-
return FALSE;
193-
}
194-
195-
/* Don't send an update if the requested dimensions are identical to current dimensions. */
196-
if (client->width == rfbClientSwap16IfLE(width) && client->height == rfbClientSwap16IfLE(height)) {
197-
guac_client_log(gc, GUAC_LOG_WARNING, "Screen size has not changed, not sending update.");
198-
return FALSE;
199-
}
200-
#endif
201192

202193
/**
203194
* Note: The RFB protocol requires two message types to be sent during a
@@ -219,19 +210,11 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
219210
size_msg.height = rfbClientSwap16IfLE(height);
220211
size_msg.numberOfScreens = 1;
221212

222-
#ifdef LIBVNC_CLIENT_HAS_SCREEN
223213
/* Configure the screen update message. */
224214
new_screen.id = GUAC_VNC_SCREEN_ID;
225215
new_screen.x = client->screen.x;
226216
new_screen.y = client->screen.y;
227217
new_screen.flags = client->screen.flags;
228-
#else
229-
/* Assume screen starts at the origin. */
230-
new_screen.id = GUAC_VNC_SCREEN_ID;
231-
new_screen.x = 0;
232-
new_screen.y = 0;
233-
new_screen.flags = 0;
234-
#endif // LIBVNC_CLIENT_HAS_SCREEN
235218

236219
new_screen.width = rfbClientSwap16IfLE(width);
237220
new_screen.height = rfbClientSwap16IfLE(height);
@@ -246,11 +229,9 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
246229

247230
}
248231

249-
#ifdef LIBVNC_CLIENT_HAS_SCREEN
250232
/* Update the client frame buffer with the requested size. */
251233
client->screen.width = rfbClientSwap16IfLE(width);
252234
client->screen.height = rfbClientSwap16IfLE(height);
253-
#endif // LIBVNC_CLIENT_HAS_SCREEN
254235

255236
#ifdef LIBVNC_CLIENT_HAS_REQUESTED_RESIZE
256237
client->requestedResize = FALSE;
@@ -266,6 +247,7 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
266247

267248
/* Update should be successful. */
268249
return TRUE;
250+
269251
}
270252

271253
void* guac_vnc_display_set_owner_size(guac_user* owner, void* data) {
@@ -323,7 +305,7 @@ void guac_vnc_display_set_size(rfbClient* client, int requested_width, int reque
323305
pthread_mutex_unlock(&(vnc_client->message_lock));
324306

325307
}
326-
#endif // LIBVNC_HAS_SIZE_MSG
308+
#endif // LIBVNC_HAS_RESIZE_SUPPORT
327309

328310
void guac_vnc_set_pixel_format(rfbClient* client, int color_depth) {
329311
client->format.trueColour = 1;

src/protocols/vnc/input.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ int guac_vnc_user_key_handler(guac_user* user, int keysym, int pressed) {
6464
return 0;
6565
}
6666

67-
#ifdef LIBVNC_HAS_SIZE_MSG
67+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
6868
int guac_vnc_user_size_handler(guac_user* user, int width, int height) {
6969

7070
guac_user_log(user, GUAC_LOG_TRACE, "Running user size handler.");
@@ -78,4 +78,4 @@ int guac_vnc_user_size_handler(guac_user* user, int width, int height) {
7878
return 0;
7979

8080
}
81-
#endif //LIBVNC_HAS_SIZE_MSG
81+
#endif // LIBVNC_HAS_RESIZE_SUPPORT

src/protocols/vnc/user.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,14 @@ int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) {
8989
user->file_handler = guac_vnc_sftp_file_handler;
9090
#endif
9191

92-
#ifdef LIBVNC_HAS_SIZE_MSG
92+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
9393
/* If user is owner, set size handler. */
9494
if (user->owner && !settings->disable_display_resize)
9595
user->size_handler = guac_vnc_user_size_handler;
96-
#endif // LIBVNC_HAS_SIZE_MSG
96+
#else
97+
guac_user_log(user, GUAC_LOG_WARNING,
98+
"The libvncclient library does not support remote resize.");
99+
#endif // LIBVNC_HAS_RESIZE_SUPPORT
97100

98101
}
99102

src/protocols/vnc/vnc.c

+33-7
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,9 @@ static int guac_vnc_wait_for_messages(rfbClient* rfb_client, int msec_timeout) {
281281
* True (non-zero) if messages were handled successfully, false (zero)
282282
* otherwise.
283283
*/
284-
static rfbBool guac_vnc_handle_messages(guac_vnc_client* vnc_client) {
284+
static rfbBool guac_vnc_handle_messages(guac_client* client) {
285285

286+
guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
286287
rfbClient* rfb_client = vnc_client->rfb_client;
287288
guac_display_layer* default_layer = guac_display_default_layer(vnc_client->display);
288289

@@ -311,6 +312,31 @@ static rfbBool guac_vnc_handle_messages(guac_vnc_client* vnc_client) {
311312
guac_display_layer_close_raw(default_layer, context);
312313
vnc_client->current_context = NULL;
313314

315+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
316+
// If screen was not previously initialized, check for it and set it.
317+
if (!vnc_client->rfb_screen_initialized
318+
&& rfb_client->screen.width > 0
319+
&& rfb_client->screen.height > 0) {
320+
vnc_client->rfb_screen_initialized = true;
321+
guac_client_log(client, GUAC_LOG_DEBUG, "Screen is now initialized.");
322+
}
323+
324+
/*
325+
* If the screen is now or has been initialized, check to see if the initial
326+
* dimensions have already been sent. If not, and resize is not disabled,
327+
* send the initial size.
328+
*/
329+
if (vnc_client->rfb_screen_initialized) {
330+
guac_vnc_settings* settings = vnc_client->settings;
331+
if (!vnc_client->rfb_initial_resize && !settings->disable_display_resize) {
332+
guac_client_log(client, GUAC_LOG_DEBUG,
333+
"Sending initial screen size to VNC server.");
334+
guac_client_for_owner(client, guac_vnc_display_set_owner_size, rfb_client);
335+
vnc_client->rfb_initial_resize = true;
336+
}
337+
}
338+
#endif // LIBVNC_HAS_RESIZE_SUPPORT
339+
314340
/* Resize the surface if VNC screen size has changed (this call
315341
* automatically deals with invalid dimensions and is a no-op
316342
* if the size has not changed) */
@@ -592,11 +618,11 @@ void* guac_vnc_client_thread(void* data) {
592618
guac_display_set_cursor(vnc_client->display, GUAC_DISPLAY_CURSOR_POINTER);
593619
}
594620

595-
#ifdef LIBVNC_HAS_SIZE_MSG
596-
/* Update the display with the owner's screen size. */
597-
if (!settings->disable_display_resize)
598-
guac_client_for_owner(client, guac_vnc_display_set_owner_size, rfb_client);
599-
#endif // LIBVNC_HAS_SIZE_MSG
621+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
622+
/* Set initial state of the screen and resize flags. */
623+
vnc_client->rfb_screen_initialized = false;
624+
vnc_client->rfb_initial_resize = false;
625+
#endif // LIBVNC_HAS_RESIZE_SUPPORT
600626

601627
guac_display_end_frame(vnc_client->display);
602628

@@ -610,7 +636,7 @@ void* guac_vnc_client_thread(void* data) {
610636
if (wait_result > 0) {
611637

612638
/* Handle any message received */
613-
if (!guac_vnc_handle_messages(vnc_client)) {
639+
if (!guac_vnc_handle_messages(client)) {
614640
guac_client_abort(client,
615641
GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
616642
"Error handling message from VNC server.");

src/protocols/vnc/vnc.h

+13
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,19 @@ typedef struct guac_vnc_client {
164164
*/
165165
guac_iconv_write* clipboard_writer;
166166

167+
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
168+
/**
169+
* Whether or not the server has sent the required message to initialize
170+
* the screen data in the client.
171+
*/
172+
bool rfb_screen_initialized;
173+
174+
/**
175+
* Whether or not the client has sent it's starting size to the server.
176+
*/
177+
bool rfb_initial_resize;
178+
#endif
179+
167180
} guac_vnc_client;
168181

169182
/**

0 commit comments

Comments
 (0)