Commit 0f11550c for guacamole.apache.org
commit 0f11550c58d7cbdc44226ba0d5b2c1be6c8deea6
Author: Virtually Nick <vnick@apache.org>
Date: Mon Jul 20 19:57:45 2026 -0400
GUACAMOLE-2273: Handle FreeRDP version support for authentication reasons; support requesting gateway authentication.
diff --git a/src/protocols/rdp/argv.c b/src/protocols/rdp/argv.c
index d85bc13c..4822a5f5 100644
--- a/src/protocols/rdp/argv.c
+++ b/src/protocols/rdp/argv.c
@@ -56,6 +56,24 @@ int guac_rdp_argv_callback(guac_user* user, const char* mimetype,
settings->domain = guac_strdup(value);
}
+ /* Update gateway username */
+ else if (strcmp(name, GUAC_RDP_ARGV_GATEWAY_USERNAME) == 0) {
+ guac_mem_free(settings->gateway_username);
+ settings->gateway_username = guac_strdup(value);
+ }
+
+ /* Update gateway password */
+ else if (strcmp(name, GUAC_RDP_ARGV_GATEWAY_PASSWORD) == 0) {
+ guac_mem_free(settings->gateway_password);
+ settings->gateway_password = guac_strdup(value);
+ }
+
+ /* Update gateway domain */
+ else if (strcmp(name, GUAC_RDP_ARGV_GATEWAY_DOMAIN) == 0) {
+ guac_mem_free(settings->gateway_domain);
+ settings->gateway_domain = guac_strdup(value);
+ }
+
return 0;
}
diff --git a/src/protocols/rdp/argv.h b/src/protocols/rdp/argv.h
index c321dc6e..9d3e1a71 100644
--- a/src/protocols/rdp/argv.h
+++ b/src/protocols/rdp/argv.h
@@ -47,5 +47,23 @@ guac_argv_callback guac_rdp_argv_callback;
*/
#define GUAC_RDP_ARGV_DOMAIN "domain"
+/**
+ * The name of the parameter that specifies/updates the gateway username that
+ * will be sent to the RDP server during authentication.
+ */
+#define GUAC_RDP_ARGV_GATEWAY_USERNAME "gateway-username"
+
+/**
+ * The name of the parameter that specifies/updates the gateway password that
+ * will be sent to the RDP server during authentication.
+ */
+#define GUAC_RDP_ARGV_GATEWAY_PASSWORD "gateway-password"
+
+/**
+ * The name of the parmaeter that specifies/updates the gateway domain that
+ * will be sent to the RDP server during authentication.
+ */
+#define GUAC_RDP_ARGV_GATEWAY_DOMAIN "gateway-domain"
+
#endif
diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
index 1e2f954e..bc5513c5 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -54,15 +54,16 @@
#include <freerdp/freerdp.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/graphics.h>
-#include <guacamole/proctitle.h>
#include <freerdp/primary.h>
#include <freerdp/settings.h>
#include <freerdp/update.h>
+#include <freerdp/version.h>
#include <guacamole/argv.h>
#include <guacamole/audio.h>
#include <guacamole/client.h>
#include <guacamole/display.h>
#include <guacamole/mem.h>
+#include <guacamole/proctitle.h>
#include <guacamole/protocol.h>
#include <guacamole/recording.h>
#include <guacamole/socket.h>
@@ -231,6 +232,8 @@ static BOOL rdp_freerdp_pre_connect(freerdp* instance) {
return TRUE;
}
+#if defined(HAVE_FREERDP_AUTHENTICATE) || defined(HAVE_FREERDP_AUTHENTICATEEX)
+
/**
* Provided a guac_client, a NULL-terminated list of parameters, and the
* pointers to the various authentication-related parameters, send the
@@ -271,20 +274,42 @@ static void guac_rdp_send_auth_params(guac_client* client, const char** params,
/* Free old values and get new values from settings. */
for (int i = 0; params[i] != NULL; i++) {
- if (!strcmp(params[i], GUAC_RDP_ARGV_USERNAME)) {
+ if (strcmp(params[i], GUAC_RDP_ARGV_USERNAME) == 0) {
guac_mem_free(*username);
*username = guac_strdup(settings->username);
}
- if (!strcmp(params[i], GUAC_RDP_ARGV_DOMAIN)) {
+ else if (strcmp(params[i], GUAC_RDP_ARGV_GATEWAY_USERNAME) == 0) {
+ guac_mem_free(*username);
+ *username = guac_strdup(settings->gateway_username);
+ }
+
+ else if (strcmp(params[i], GUAC_RDP_ARGV_DOMAIN) == 0) {
guac_mem_free(*domain);
*domain = guac_strdup(settings->domain);
}
- if (!strcmp(params[i], GUAC_RDP_ARGV_PASSWORD)) {
+ else if (strcmp(params[i], GUAC_RDP_ARGV_GATEWAY_DOMAIN) == 0) {
+ guac_mem_free(*domain);
+ *domain = guac_strdup(settings->gateway_domain);
+ }
+
+ else if (strcmp(params[i], GUAC_RDP_ARGV_PASSWORD) == 0) {
guac_mem_free(*password);
*password = guac_strdup(settings->password);
}
+
+ else if (strcmp(params[i], GUAC_RDP_ARGV_GATEWAY_PASSWORD) == 0) {
+ guac_mem_free(*password);
+ *password = guac_strdup(settings->gateway_password);
+ }
+
+ /* This should never happen, but we'll log it just in case. */
+ else {
+ guac_client_log(client, GUAC_LOG_WARNING,
+ "Unknown authentication parameter requested.");
+ }
+
}
}
@@ -338,6 +363,54 @@ static int guac_rdp_register_required_auth(guac_rdp_settings* settings, char** p
}
+#ifdef HAVE_FREERDP_AUTHENTICATEEX
+/**
+ * A function called when FreeRDP receives a request for gateway-related
+ * authentication settings, returning the number of settings that will be
+ * requested from the client.
+ *
+ * @param settings
+ * The settings member from the RDP client.
+ *
+ * @param params
+ * The structure used to store the parameters.
+ *
+ * @return
+ * The number of settings that will be requested from the client.
+ */
+static int guac_rdp_register_required_gateway_auth(guac_rdp_settings* settings, char** params) {
+
+ int i = 0;
+
+ /* If the gateway username is null, we'll request that. */
+ if (settings->gateway_username == NULL) {
+ guac_argv_register(GUAC_RDP_ARGV_GATEWAY_USERNAME, guac_rdp_argv_callback, NULL, 0);
+ params[i] = GUAC_RDP_ARGV_GATEWAY_USERNAME;
+ i++;
+
+ /* If the gateway domain is null, we'll also request that. */
+ if (settings->gateway_domain == NULL) {
+ guac_argv_register(GUAC_RDP_ARGV_GATEWAY_DOMAIN, guac_rdp_argv_callback, NULL, 0);
+ params[i] = GUAC_RDP_ARGV_GATEWAY_DOMAIN;
+ i++;
+ }
+ }
+
+ /* If the gateway password is null, request that. */
+ if (settings->gateway_password == NULL) {
+ guac_argv_register(GUAC_RDP_ARGV_GATEWAY_PASSWORD, guac_rdp_argv_callback, NULL, 0);
+ params[i] = GUAC_RDP_ARGV_GATEWAY_PASSWORD;
+ i++;
+ }
+
+ /* NULL-terminate the array and return the number of items. */
+ params[i] = NULL;
+
+ return i;
+
+}
+#endif // HAVE_FREERDP_AUTHENTICATEEX
+
#ifdef HAVE_FREERDP_AUTHENTICATE
/**
* Callback invoked by FreeRDP when authentication is required but the required
@@ -457,8 +530,12 @@ static BOOL rdp_freerdp_authenticate_ex(freerdp* instance, char** username,
switch (reason) {
/* In the case that we just need a PIN, request only the PIN/password. */
- case AUTH_SMARTCARD_PIN:
+#if (FREERDP_VERSION_MAJOR >= 4) || \
+ (FREERDP_VERSION_MAJOR == 3 && FREERDP_VERSION_MINOR >= 25)
+ /* FIDO PIN support was added in 3.25.0 */
case AUTH_FIDO_PIN:
+#endif
+ case AUTH_SMARTCARD_PIN:
/* If the password/PIN is undefined, add it to the requested parameters. */
if (settings->password == NULL) {
@@ -473,15 +550,23 @@ static BOOL rdp_freerdp_authenticate_ex(freerdp* instance, char** username,
break;
/* For all other cases, request anything that isn't configured. */
+#if (FREERDP_VERSION_MAJOR >= 4) || \
+ (FREERDP_VERSION_MAJOR == 3 && FREERDP_VERSION_MINOR >= 18)
+ /* RDSTLS support was added in 3.18.0 */
case AUTH_RDSTLS:
+#endif
case AUTH_TLS:
case AUTH_RDP:
case AUTH_NLA:
+ i = guac_rdp_register_required_auth(settings, params);
+ break;
+
case GW_AUTH_HTTP:
case GW_AUTH_RDG:
case GW_AUTH_RPC:
- i = guac_rdp_register_required_auth(settings, params);
+ i = guac_rdp_register_required_gateway_auth(settings, params);
break;
+
}
/* If one or more params have been required, send them. */
@@ -493,6 +578,7 @@ static BOOL rdp_freerdp_authenticate_ex(freerdp* instance, char** username,
}
#endif // HAVE_FREERDP_AUTHENTICATEEX
+#endif // HAVE_FREERDP_AUTHENTICATE OR HAVE_FREERDP_AUTHENTICATEEX
#ifdef HAVE_FREERDP_VERIFYCERTIFICATEEX
/**
diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c
index 451a056b..09566492 100644
--- a/src/protocols/rdp/settings.c
+++ b/src/protocols/rdp/settings.c
@@ -133,9 +133,9 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
"gateway-hostname",
"gateway-port",
- "gateway-domain",
- "gateway-username",
- "gateway-password",
+ GUAC_RDP_ARGV_GATEWAY_DOMAIN,
+ GUAC_RDP_ARGV_GATEWAY_USERNAME,
+ GUAC_RDP_ARGV_GATEWAY_PASSWORD,
"load-balance-info",