GUACAMOLE-221: Implement guacd support for verifying that client can accept the required instruction.
This commit is contained in:
parent
b00b629b96
commit
bc8ed4e104
@ -341,6 +341,9 @@ static void guacd_exec_proc(guacd_proc* proc, const char* protocol) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable keep alive on the broadcast socket */
|
||||||
|
guac_socket_require_keep_alive(client->socket);
|
||||||
|
|
||||||
cleanup_client:
|
cleanup_client:
|
||||||
|
|
||||||
/* Request client to stop/disconnect */
|
/* Request client to stop/disconnect */
|
||||||
|
@ -478,22 +478,39 @@ int guac_client_load_plugin(guac_client* client, const char* protocol) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function which is invoked by guac_client_owner_send_required() to
|
||||||
|
* send the required parameters to the specified user, who is the owner of the
|
||||||
|
* client session.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The guac_user that will receive the required parameters, who is the owner
|
||||||
|
* of the client.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* Pointer to a NULL-terminated array of required parameters that will be
|
||||||
|
* passed on to the owner to continue the connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A pointer to an integer containing the return status of the send
|
||||||
|
* operation.
|
||||||
|
*/
|
||||||
|
static void* guac_client_owner_send_required_callback(guac_user* user, void* data) {
|
||||||
|
|
||||||
|
const char** required = (const char **) data;
|
||||||
|
|
||||||
|
/* Send required parameters to owner. */
|
||||||
|
return (void*) ((intptr_t) guac_protocol_send_required(user->socket, required));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_client_owner_send_required(guac_client* client, const char** required) {
|
int guac_client_owner_send_required(guac_client* client, const char** required) {
|
||||||
|
|
||||||
int retval;
|
/* Don't send required instruction if client does not support it. */
|
||||||
|
if (!guac_client_owner_supports_required(client))
|
||||||
|
return -1;
|
||||||
|
|
||||||
pthread_rwlock_rdlock(&(client->__users_lock));
|
return (int) ((intptr_t) guac_client_for_owner(client, guac_client_owner_send_required_callback, required));
|
||||||
|
|
||||||
/* Invoke callback with current owner */
|
|
||||||
retval = guac_protocol_send_required(client->__owner->socket, required);
|
|
||||||
|
|
||||||
/* Flush the socket */
|
|
||||||
guac_socket_flush(client->__owner->socket);
|
|
||||||
|
|
||||||
pthread_rwlock_unlock(&(client->__users_lock));
|
|
||||||
|
|
||||||
/* Return value from sending required */
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,6 +669,44 @@ static void* __webp_support_callback(guac_user* user, void* data) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function which is invoked by guac_client_owner_supports_required()
|
||||||
|
* to determine if the owner of a client supports the "required" instruction,
|
||||||
|
* updating the flag to indicate support.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The guac_user that will be checked for "required" instruction support.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* Pointer to an int containing the status for support of the "required"
|
||||||
|
* instruction. This will be 0 if the owner does not support this
|
||||||
|
* instruction, or 1 if the owner does support it.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Always NULL.
|
||||||
|
*/
|
||||||
|
static void* guac_owner_supports_required_callback(guac_user* user, void* data) {
|
||||||
|
|
||||||
|
int* required_supported = (int *) data;
|
||||||
|
|
||||||
|
/* Check if owner supports required */
|
||||||
|
if (*required_supported)
|
||||||
|
*required_supported = guac_user_supports_required(user);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_client_owner_supports_required(guac_client* client) {
|
||||||
|
|
||||||
|
int required_supported = 1;
|
||||||
|
|
||||||
|
guac_client_for_owner(client, guac_owner_supports_required_callback, &required_supported);
|
||||||
|
|
||||||
|
return required_supported;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_client_supports_webp(guac_client* client) {
|
int guac_client_supports_webp(guac_client* client) {
|
||||||
|
|
||||||
#ifdef ENABLE_WEBP
|
#ifdef ENABLE_WEBP
|
||||||
|
@ -708,6 +708,21 @@ void guac_client_stream_webp(guac_client* client, guac_socket* socket,
|
|||||||
guac_composite_mode mode, const guac_layer* layer, int x, int y,
|
guac_composite_mode mode, const guac_layer* layer, int x, int y,
|
||||||
cairo_surface_t* surface, int quality, int lossless);
|
cairo_surface_t* surface, int quality, int lossless);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the owner of the given client supports the "required"
|
||||||
|
* instruction, returning non-zero if the client owner does support the
|
||||||
|
* instruction, or zero if the owner does not.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* The Guacamole client whose owner should be checked for supporting
|
||||||
|
* the "required" instruction.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if the owner of the given client supports the "required"
|
||||||
|
* instruction, zero otherwise.
|
||||||
|
*/
|
||||||
|
int guac_client_owner_supports_required(guac_client* client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether all users of the given client support WebP. If any user does
|
* Returns whether all users of the given client support WebP. If any user does
|
||||||
* not support WebP, or the server cannot encode WebP images, zero is returned.
|
* not support WebP, or the server cannot encode WebP images, zero is returned.
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
* This version is passed by the __guac_protocol_send_args() function from the
|
* This version is passed by the __guac_protocol_send_args() function from the
|
||||||
* server to the client during the client/server handshake.
|
* server to the client during the client/server handshake.
|
||||||
*/
|
*/
|
||||||
#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_1_0"
|
#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_3_0"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of bytes that should be sent in any one blob instruction
|
* The maximum number of bytes that should be sent in any one blob instruction
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef _GUAC_PROTOCOL_TYPES_H
|
#ifndef _GUAC_PROTOCOL_TYPES_H
|
||||||
#define _GUAC_PROTOCOL_TYPES_H
|
#define _GUAC_PROTOCOL_TYPES_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type definitions related to the Guacamole protocol.
|
* Type definitions related to the Guacamole protocol.
|
||||||
*
|
*
|
||||||
@ -276,5 +278,38 @@ typedef enum guac_line_join_style {
|
|||||||
GUAC_LINE_JOIN_ROUND = 0x2
|
GUAC_LINE_JOIN_ROUND = 0x2
|
||||||
} guac_line_join_style;
|
} guac_line_join_style;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track the various protocol versions supported by guacd to help negotiate
|
||||||
|
* features that may not be supported by various versions of the client.
|
||||||
|
*/
|
||||||
|
typedef enum guac_protocol_version {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unknown version of the Guacamole protocol.
|
||||||
|
*/
|
||||||
|
GUAC_PROTOCOL_VERSION_UNKNOWN = 0x000000,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Original protocol version 1.0.0, which lacks support for negotiating
|
||||||
|
* parameters and protocol version.
|
||||||
|
*/
|
||||||
|
GUAC_PROTOCOL_VERSION_1_0_0 = 0x010000,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol version 1.1.0, which includes support for parameter and version
|
||||||
|
* negotiation and for sending timezone information from the client
|
||||||
|
* to the server.
|
||||||
|
*/
|
||||||
|
GUAC_PROTOCOL_VERSION_1_1_0 = 0x010100,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol version 1.3.0, which supports the "required" instruction,
|
||||||
|
* allowing connections in guacd to request information from the client and
|
||||||
|
* await a response.
|
||||||
|
*/
|
||||||
|
GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300
|
||||||
|
|
||||||
|
} guac_protocol_version;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1023,5 +1023,32 @@ int guac_protocol_send_name(guac_socket* socket, const char* name);
|
|||||||
*/
|
*/
|
||||||
int guac_protocol_decode_base64(char* base64);
|
int guac_protocol_decode_base64(char* base64);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a string representation of a protocol version, search the mapping
|
||||||
|
* to find the matching enum version, or GUAC_PROTOCOL_VERSION_UNKNOWN if no
|
||||||
|
* match is found.
|
||||||
|
*
|
||||||
|
* @param version_string
|
||||||
|
* The string representation of the protocol version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The enum value of the protocol version, or GUAC_PROTOCOL_VERSION_UNKNOWN
|
||||||
|
* if no match is found.
|
||||||
|
*/
|
||||||
|
guac_protocol_version guac_protocol_string_to_version(char* version_string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the enum value of the protocol version, return a pointer to the string
|
||||||
|
* representation of the version, or NULL if the version is unknown.
|
||||||
|
*
|
||||||
|
* @param version
|
||||||
|
* The enum value of the protocol version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A pointer to the string representation of the protocol version, or NULL
|
||||||
|
* if the version is unknown.
|
||||||
|
*/
|
||||||
|
const char* guac_protocol_version_to_string(guac_protocol_version version);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -136,10 +136,6 @@ void guac_socket_free(guac_socket* socket);
|
|||||||
* to ensure neither side of the socket times out while the socket is open.
|
* to ensure neither side of the socket times out while the socket is open.
|
||||||
* This ping will take the form of a "nop" instruction.
|
* This ping will take the form of a "nop" instruction.
|
||||||
*
|
*
|
||||||
* @deprecated
|
|
||||||
* Manually starting the keep alive process on sockets is no longer
|
|
||||||
* necessary, as the sockets enable the "nop" ping by default.
|
|
||||||
*
|
|
||||||
* @param socket
|
* @param socket
|
||||||
* The guac_socket to declare as requiring an automatic keep-alive ping.
|
* The guac_socket to declare as requiring an automatic keep-alive ping.
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +96,12 @@ struct guac_user_info {
|
|||||||
*/
|
*/
|
||||||
const char* timezone;
|
const char* timezone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole protocol version that the remote system supports, allowing
|
||||||
|
* for feature support to be negotiated between client and server.
|
||||||
|
*/
|
||||||
|
guac_protocol_version protocol_version;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct guac_user {
|
struct guac_user {
|
||||||
@ -823,6 +829,17 @@ void guac_user_stream_webp(guac_user* user, guac_socket* socket,
|
|||||||
guac_composite_mode mode, const guac_layer* layer, int x, int y,
|
guac_composite_mode mode, const guac_layer* layer, int x, int y,
|
||||||
cairo_surface_t* surface, int quality, int lossless);
|
cairo_surface_t* surface, int quality, int lossless);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given user supports the "required" instruction.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The Guacamole user to check for support of the "required" instruction.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if the user supports the "required" instruction, otherwise zero.
|
||||||
|
*/
|
||||||
|
int guac_user_supports_required(guac_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given user supports WebP. If the user does not
|
* Returns whether the given user supports WebP. If the user does not
|
||||||
* support WebP, or the server cannot encode WebP images, zero is returned.
|
* support WebP, or the server cannot encode WebP images, zero is returned.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "guacamole/layer.h"
|
#include "guacamole/layer.h"
|
||||||
#include "guacamole/object.h"
|
#include "guacamole/object.h"
|
||||||
#include "guacamole/protocol.h"
|
#include "guacamole/protocol.h"
|
||||||
|
#include "guacamole/protocol-types.h"
|
||||||
#include "guacamole/socket.h"
|
#include "guacamole/socket.h"
|
||||||
#include "guacamole/stream.h"
|
#include "guacamole/stream.h"
|
||||||
#include "guacamole/unicode.h"
|
#include "guacamole/unicode.h"
|
||||||
@ -39,6 +40,34 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure mapping the enum value of a protocol version to the string
|
||||||
|
* representation of the version.
|
||||||
|
*/
|
||||||
|
typedef struct guac_protocol_version_mapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum value representing the selected protocol version.
|
||||||
|
*/
|
||||||
|
guac_protocol_version version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string value representing the protocol version.
|
||||||
|
*/
|
||||||
|
char* version_string;
|
||||||
|
|
||||||
|
} guac_protocol_version_mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of known protocol version enum to the corresponding string value.
|
||||||
|
*/
|
||||||
|
guac_protocol_version_mapping guac_protocol_version_table[] = {
|
||||||
|
{ GUAC_PROTOCOL_VERSION_1_0_0, "VERSION_1_0_0" },
|
||||||
|
{ GUAC_PROTOCOL_VERSION_1_1_0, "VERSION_1_1_0" },
|
||||||
|
{ GUAC_PROTOCOL_VERSION_1_3_0, "VERSION_1_3_0" },
|
||||||
|
{ GUAC_PROTOCOL_VERSION_UNKNOWN, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
/* Output formatting functions */
|
/* Output formatting functions */
|
||||||
|
|
||||||
ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) {
|
ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) {
|
||||||
@ -1275,3 +1304,34 @@ int guac_protocol_decode_base64(char* base64) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guac_protocol_version guac_protocol_string_to_version(char* version_string) {
|
||||||
|
|
||||||
|
guac_protocol_version_mapping* current = guac_protocol_version_table;
|
||||||
|
while (current->version != GUAC_PROTOCOL_VERSION_UNKNOWN) {
|
||||||
|
|
||||||
|
if (strcmp(current->version_string, version_string) == 0)
|
||||||
|
return current->version;
|
||||||
|
|
||||||
|
current++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return GUAC_PROTOCOL_VERSION_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* guac_protocol_version_to_string(guac_protocol_version version) {
|
||||||
|
|
||||||
|
guac_protocol_version_mapping* current = guac_protocol_version_table;
|
||||||
|
while (current->version) {
|
||||||
|
|
||||||
|
if (current->version == version) {
|
||||||
|
return (const char*) current->version_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -150,10 +150,8 @@ guac_socket* guac_socket_alloc() {
|
|||||||
socket->state = GUAC_SOCKET_OPEN;
|
socket->state = GUAC_SOCKET_OPEN;
|
||||||
socket->last_write_timestamp = guac_timestamp_current();
|
socket->last_write_timestamp = guac_timestamp_current();
|
||||||
|
|
||||||
/* keep alive ping by default */
|
/* No keep alive ping by default */
|
||||||
socket->__keep_alive_enabled = 1;
|
socket->__keep_alive_enabled = 0;
|
||||||
pthread_create(&(socket->__keep_alive_thread), NULL,
|
|
||||||
__guac_socket_keep_alive_thread, (void*) socket);
|
|
||||||
|
|
||||||
/* No handlers yet */
|
/* No handlers yet */
|
||||||
socket->read_handler = NULL;
|
socket->read_handler = NULL;
|
||||||
|
@ -344,12 +344,16 @@ int guac_user_handle_connection(guac_user* user, int usec_timeout) {
|
|||||||
guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" joined connection "
|
guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" joined connection "
|
||||||
"\"%s\" (%i users now present)", user->user_id,
|
"\"%s\" (%i users now present)", user->user_id,
|
||||||
client->connection_id, client->connected_users);
|
client->connection_id, client->connected_users);
|
||||||
if (strcmp(parser->argv[0],"") != 0)
|
if (strcmp(parser->argv[0],"") != 0) {
|
||||||
guac_client_log(client, GUAC_LOG_DEBUG, "Client is using protocol "
|
guac_client_log(client, GUAC_LOG_DEBUG, "Client is using protocol "
|
||||||
"version \"%s\"", parser->argv[0]);
|
"version \"%s\"", parser->argv[0]);
|
||||||
else
|
user->info.protocol_version = guac_protocol_string_to_version(parser->argv[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
guac_client_log(client, GUAC_LOG_DEBUG, "Client has not defined "
|
guac_client_log(client, GUAC_LOG_DEBUG, "Client has not defined "
|
||||||
"its protocol version.");
|
"its protocol version.");
|
||||||
|
user->info.protocol_version = GUAC_PROTOCOL_VERSION_1_0_0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle user I/O, wait for connection to terminate */
|
/* Handle user I/O, wait for connection to terminate */
|
||||||
guac_user_start(parser, user, usec_timeout);
|
guac_user_start(parser, user, usec_timeout);
|
||||||
|
@ -316,6 +316,15 @@ void guac_user_stream_webp(guac_user* user, guac_socket* socket,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int guac_user_supports_required(guac_user* user) {
|
||||||
|
|
||||||
|
if (user == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (user->info.protocol_version >= GUAC_PROTOCOL_VERSION_1_3_0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_user_supports_webp(guac_user* user) {
|
int guac_user_supports_webp(guac_user* user) {
|
||||||
|
|
||||||
#ifdef ENABLE_WEBP
|
#ifdef ENABLE_WEBP
|
||||||
|
@ -202,7 +202,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
|||||||
/**
|
/**
|
||||||
* Callback invoked by FreeRDP when authentication is required but a username
|
* Callback invoked by FreeRDP when authentication is required but a username
|
||||||
* and password has not already been given. In the case of Guacamole, this
|
* and password has not already been given. In the case of Guacamole, this
|
||||||
* function always succeeds but does not populate the usename or password. The
|
* function always succeeds but does not populate the username or password. The
|
||||||
* username/password must be given within the connection parameters.
|
* username/password must be given within the connection parameters.
|
||||||
*
|
*
|
||||||
* @param instance
|
* @param instance
|
||||||
@ -232,6 +232,11 @@ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username,
|
|||||||
char* params[4] = {};
|
char* params[4] = {};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
/* If the client does not support the "required" instruction, just
|
||||||
|
exit. */
|
||||||
|
if (!guac_client_owner_supports_required(client))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (settings->username == NULL) {
|
if (settings->username == NULL) {
|
||||||
params[i] = GUAC_RDP_PARAMETER_NAME_USERNAME;
|
params[i] = GUAC_RDP_PARAMETER_NAME_USERNAME;
|
||||||
rdp_client->rdp_credential_flags |= GUAC_RDP_CRED_FLAG_USERNAME;
|
rdp_client->rdp_credential_flags |= GUAC_RDP_CRED_FLAG_USERNAME;
|
||||||
@ -257,7 +262,7 @@ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username,
|
|||||||
/* Lock the client thread. */
|
/* Lock the client thread. */
|
||||||
pthread_mutex_lock(&(rdp_client->rdp_credential_lock));
|
pthread_mutex_lock(&(rdp_client->rdp_credential_lock));
|
||||||
|
|
||||||
/* Send require parameters to the owner. */
|
/* Send required parameters to the owner. */
|
||||||
guac_client_owner_send_required(client, (const char**) params);
|
guac_client_owner_send_required(client, (const char**) params);
|
||||||
|
|
||||||
/* Wait for condition. */
|
/* Wait for condition. */
|
||||||
|
@ -74,6 +74,10 @@ static void guac_ssh_get_credential(guac_client *client, char* cred_name) {
|
|||||||
|
|
||||||
guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
|
guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
|
||||||
|
|
||||||
|
/* If the client does not support the "required" instruction, just return. */
|
||||||
|
if (!guac_client_owner_supports_required(client))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Lock the terminal thread while prompting for the credential. */
|
/* Lock the terminal thread while prompting for the credential. */
|
||||||
pthread_mutex_lock(&(ssh_client->term_channel_lock));
|
pthread_mutex_lock(&(ssh_client->term_channel_lock));
|
||||||
|
|
||||||
|
@ -36,6 +36,11 @@ char* guac_vnc_get_password(rfbClient* client) {
|
|||||||
guac_vnc_client* vnc_client = ((guac_vnc_client*) gc->data);
|
guac_vnc_client* vnc_client = ((guac_vnc_client*) gc->data);
|
||||||
guac_vnc_settings* settings = vnc_client->settings;
|
guac_vnc_settings* settings = vnc_client->settings;
|
||||||
|
|
||||||
|
/* If the client does not support the "required" instruction, just return
|
||||||
|
the configuration data. */
|
||||||
|
if (!guac_client_owner_supports_required(gc))
|
||||||
|
return ((guac_vnc_client*) gc->data)->settings->password;
|
||||||
|
|
||||||
/* If password isn't around, prompt for it. */
|
/* If password isn't around, prompt for it. */
|
||||||
if (settings->password == NULL || strcmp(settings->password, "") == 0) {
|
if (settings->password == NULL || strcmp(settings->password, "") == 0) {
|
||||||
/* Lock the thread. */
|
/* Lock the thread. */
|
||||||
@ -68,6 +73,15 @@ rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType) {
|
|||||||
/* Handle request for Username/Password credentials */
|
/* Handle request for Username/Password credentials */
|
||||||
if (credentialType == rfbCredentialTypeUser) {
|
if (credentialType == rfbCredentialTypeUser) {
|
||||||
rfbCredential *creds = malloc(sizeof(rfbCredential));
|
rfbCredential *creds = malloc(sizeof(rfbCredential));
|
||||||
|
|
||||||
|
/* If the client does not support the "required" instruction, just return
|
||||||
|
the parameters already configured. */
|
||||||
|
if (!guac_client_owner_supports_required(gc)) {
|
||||||
|
creds->userCredential.username = settings->username;
|
||||||
|
creds->userCredential.password = settings->password;
|
||||||
|
return creds;
|
||||||
|
}
|
||||||
|
|
||||||
char* params[2] = {NULL};
|
char* params[2] = {NULL};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user