From 30bbb892db2335062b877426b295eff1e14669b2 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 9 Jun 2020 19:27:07 -0400 Subject: [PATCH 1/6] GUACAMOLE-513: Handle cases where socket open fails. --- src/libguac/wol.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libguac/wol.c b/src/libguac/wol.c index b8e5e687..5d8d7982 100644 --- a/src/libguac/wol.c +++ b/src/libguac/wol.c @@ -93,6 +93,12 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, if (wol_dest.sin_family == AF_INET) { int wol_bcast = 1; wol_socket = socket(AF_INET, SOCK_DGRAM, 0); + + /* If opening a socket fails, bail out. */ + if (wol_socket < 0) { + close(wol_socket); + return 0; + } /* Attempt to set broadcast; exit with error if this fails. */ if (setsockopt(wol_socket, SOL_SOCKET, SO_BROADCAST, &wol_bcast, @@ -106,6 +112,12 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, else { wol_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + /* If opening the socket fails, bail out. */ + if (wol_socket < 0) { + close(wol_socket); + return 0; + } + /* Stick to a single hop for now. */ int hops = 1; From 57c4dbf4541dc0e08f2463a5b7c8e34a9d3bdf9e Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jun 2020 11:50:36 -0400 Subject: [PATCH 2/6] GUACAMOLE-513: No need to close socket when socket was never opened. --- src/libguac/wol.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/libguac/wol.c b/src/libguac/wol.c index 5d8d7982..62e298a3 100644 --- a/src/libguac/wol.c +++ b/src/libguac/wol.c @@ -95,10 +95,8 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_socket = socket(AF_INET, SOCK_DGRAM, 0); /* If opening a socket fails, bail out. */ - if (wol_socket < 0) { - close(wol_socket); + if (wol_socket < 0) return 0; - } /* Attempt to set broadcast; exit with error if this fails. */ if (setsockopt(wol_socket, SOL_SOCKET, SO_BROADCAST, &wol_bcast, @@ -113,16 +111,14 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); /* If opening the socket fails, bail out. */ - if (wol_socket < 0) { - close(wol_socket); + if (wol_socket < 0) return 0; - } /* Stick to a single hop for now. */ int hops = 1; if (setsockopt(wol_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, - sizeof(hops))) { + sizeof(hops)) < 0) { close(wol_socket); return 0; } From ec305903d0ad89ee93b3b1f56398dc5413d6118c Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jun 2020 15:05:55 -0400 Subject: [PATCH 3/6] GUACAMOLE-513: Add guac_error handling for WoL --- src/libguac/wol.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/libguac/wol.c b/src/libguac/wol.c index 62e298a3..b66a22a4 100644 --- a/src/libguac/wol.c +++ b/src/libguac/wol.c @@ -19,6 +19,9 @@ #include "config.h" +#include "guacamole/error.h" +#include "guacamole/wol.h" + #include #include #include @@ -27,8 +30,6 @@ #include #include -#include "guacamole/wol.h" - /** * Generate the magic Wake-on-LAN (WoL) packet for the specified MAC address * and place it in the character array. @@ -85,8 +86,11 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_dest.sin_family = AF_INET; if (inet_pton(AF_INET, broadcast_addr, &(wol_dest.sin_addr)) == 0) { wol_dest.sin_family = AF_INET6; - if (inet_pton(AF_INET6, broadcast_addr, &(wol_dest.sin_addr)) == 0) + if (inet_pton(AF_INET6, broadcast_addr, &(wol_dest.sin_addr)) == 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Wake-on-LAN address does not appear to be IPv4 or IPv6"; return 0; + } } /* Set up socket for IPv4 broadcast. */ @@ -95,13 +99,18 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_socket = socket(AF_INET, SOCK_DGRAM, 0); /* If opening a socket fails, bail out. */ - if (wol_socket < 0) + if (wol_socket < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Failed to open IPv4 Wake-on-LAN socket"; return 0; + } /* Attempt to set broadcast; exit with error if this fails. */ if (setsockopt(wol_socket, SOL_SOCKET, SO_BROADCAST, &wol_bcast, sizeof(wol_bcast)) < 0) { close(wol_socket); + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Failed to set IPv4 broadcast for Wake-on-LAN socket"; return 0; } } @@ -111,8 +120,11 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); /* If opening the socket fails, bail out. */ - if (wol_socket < 0) + if (wol_socket < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Failed to open IPv6 Wake-on-LAN socket"; return 0; + } /* Stick to a single hop for now. */ int hops = 1; @@ -120,6 +132,8 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, if (setsockopt(wol_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { close(wol_socket); + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Failed to set IPv6 multicast for Wake-on-LAN socket"; return 0; } } @@ -141,6 +155,8 @@ int guac_wol_wake(const char* mac_addr, const char* broadcast_addr) { if (sscanf(mac_addr, "%x:%x:%x:%x:%x:%x", &(dest_mac[0]), &(dest_mac[1]), &(dest_mac[2]), &(dest_mac[3]), &(dest_mac[4]), &(dest_mac[5])) != 6) { + guac_error = GUAC_STATUS_INVALID_ARGUMENT; + guac_error_message = "Invalid argument for Wake-on-LAN MAC address"; return -1; } From b0bcb30346cb84a59a436ed2847857fe26c7fda3 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Tue, 16 Jun 2020 16:48:51 -0400 Subject: [PATCH 4/6] GUACAMOLE-513: Merge socket calls and handle IP family determination correctly. --- src/libguac/wol.c | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/libguac/wol.c b/src/libguac/wol.c index b66a22a4..5c704459 100644 --- a/src/libguac/wol.c +++ b/src/libguac/wol.c @@ -84,28 +84,47 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, /* Determine the IP version, starting with IPv4. */ wol_dest.sin_port = htons(GUAC_WOL_PORT); wol_dest.sin_family = AF_INET; - if (inet_pton(AF_INET, broadcast_addr, &(wol_dest.sin_addr)) == 0) { + int retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); + + /* If return value is less than zero, the address doesn't match any known family. */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Unknown broadcast or multicast address type specified for Wake-on-LAN"; + return 0; + } + + /* If return value is zero, address doesn't match the IPv4, so try IPv6. */ + else if (retval == 0) { wol_dest.sin_family = AF_INET6; - if (inet_pton(AF_INET6, broadcast_addr, &(wol_dest.sin_addr)) == 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Wake-on-LAN address does not appear to be IPv4 or IPv6"; + retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); + + /* IPv6 didn't work, either, so bail out. */ + if (retval == 0) { + guac_error = GUAC_STATUS_INVALID_ARGUMENT; + guac_error_message = "Invalid broadcast or multicast address specified for Wake-on-LAN"; return 0; } } + + + /* Set up the socket */ + wol_socket = socket(wol_dest.sin_family, SOCK_DGRAM, 0); + + /* If socket open fails, bail out. */ + if (wol_socket < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Failed to open socket to send Wake-on-LAN packet"; + return 0; + } + /* Set up socket for IPv4 broadcast. */ if (wol_dest.sin_family == AF_INET) { - int wol_bcast = 1; - wol_socket = socket(AF_INET, SOCK_DGRAM, 0); - /* If opening a socket fails, bail out. */ - if (wol_socket < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Failed to open IPv4 Wake-on-LAN socket"; - return 0; - } + /* For configuring socket broadcast */ + int wol_bcast = 1; - /* Attempt to set broadcast; exit with error if this fails. */ + /* Attempt to set IPv4 broadcast; exit with error if this fails. */ if (setsockopt(wol_socket, SOL_SOCKET, SO_BROADCAST, &wol_bcast, sizeof(wol_bcast)) < 0) { close(wol_socket); @@ -117,18 +136,11 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, /* Set up socket for IPv6 multicast. */ else { - wol_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - - /* If opening the socket fails, bail out. */ - if (wol_socket < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Failed to open IPv6 Wake-on-LAN socket"; - return 0; - } /* Stick to a single hop for now. */ int hops = 1; + /* Attempt to set IPv6 multicast; exit with error if this fails. */ if (setsockopt(wol_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { close(wol_socket); From e51c269a51a6e9db2aeb91969444600616b442b7 Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 17 Jun 2020 06:50:43 -0400 Subject: [PATCH 5/6] GUACAMOL-513: Correctly handle unknown address families. --- src/libguac/wol.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libguac/wol.c b/src/libguac/wol.c index 5c704459..dcbd07cd 100644 --- a/src/libguac/wol.c +++ b/src/libguac/wol.c @@ -86,10 +86,10 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_dest.sin_family = AF_INET; int retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); - /* If return value is less than zero, the address doesn't match any known family. */ + /* If return value is less than zero, this system doesn't know about IPv4. */ if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Unknown broadcast or multicast address type specified for Wake-on-LAN"; + guac_error_message = "IPv4 address family is not supported"; return 0; } @@ -98,8 +98,15 @@ static ssize_t __guac_wol_send_packet(const char* broadcast_addr, wol_dest.sin_family = AF_INET6; retval = inet_pton(wol_dest.sin_family, broadcast_addr, &(wol_dest.sin_addr)); - /* IPv6 didn't work, either, so bail out. */ - if (retval == 0) { + /* System does not support IPv6. */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "IPv6 address family is not supported"; + return 0; + } + + /* Address didn't match IPv6. */ + else if (retval == 0) { guac_error = GUAC_STATUS_INVALID_ARGUMENT; guac_error_message = "Invalid broadcast or multicast address specified for Wake-on-LAN"; return 0; From db4b155c511ff947ce365cea664641cf1f3dab4e Mon Sep 17 00:00:00 2001 From: Nick Couchman Date: Wed, 17 Jun 2020 15:21:14 -0400 Subject: [PATCH 6/6] GUACAMOLE-513: Update default WoL boot wait time to 0. --- src/common/common/defaults.h | 2 +- src/protocols/rdp/settings.c | 3 ++- src/protocols/ssh/settings.c | 3 ++- src/protocols/telnet/settings.c | 3 ++- src/protocols/vnc/settings.c | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/common/common/defaults.h b/src/common/common/defaults.h index 17d761d7..a061be66 100644 --- a/src/common/common/defaults.h +++ b/src/common/common/defaults.h @@ -24,7 +24,7 @@ * The default number of seconds to wait after sending the Wake-on-LAN packet * for the destination host to start responding. */ -#define GUAC_WOL_DEFAULT_BOOT_WAIT_TIME 60 +#define GUAC_WOL_DEFAULT_BOOT_WAIT_TIME 0 #endif /* GUAC_COMMON_DEFAULTS_H */ diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 381ec303..307c83ba 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -612,7 +612,8 @@ enum RDP_ARGS_IDX { * The amount of time, in seconds, to wait after sending the WoL packet * before attempting to connect to the host. This should be a reasonable * amount of time to allow the remote host to fully boot and respond to - * network connection requests. The default amount of time is 60 seconds. + * network connection requests. The default is not to wait at all + * (0 seconds). */ IDX_WOL_WAIT_TIME, diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c index 9539d033..edad700c 100644 --- a/src/protocols/ssh/settings.c +++ b/src/protocols/ssh/settings.c @@ -318,7 +318,8 @@ enum SSH_ARGS_IDX { /** * The amount of time to wait after sending the magic WoL packet prior to - * continuing the connection attempt. + * continuing the connection attempt. The default is no wait time + * (0 seconds). */ IDX_WOL_WAIT_TIME, diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c index 8b537de4..d51d4406 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -259,7 +259,8 @@ enum TELNET_ARGS_IDX { /** * The amount of time, in seconds, to wait after the magic WoL packet is - * sent before continuing the connection attempt. + * sent before continuing the connection attempt. The default is not to + * wait at all (0 seconds). */ IDX_WOL_WAIT_TIME, diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c index c64c73af..c0d14859 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -361,7 +361,8 @@ enum VNC_ARGS_IDX { /** * The number of seconds to wait after sending the magic WoL packet before - * attempting to connect to the remote host. + * attempting to connect to the remote host. The default is not to wait + * at all (0 seconds). */ IDX_WOL_WAIT_TIME,