GUACAMOLE-221: Move VNC and RDP argv to new callback.
This commit is contained in:
parent
f70fdfc612
commit
b6d3edb749
@ -30,160 +30,31 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/**
|
int guac_rdp_argv_callback(guac_user* user, const char* mimetype,
|
||||||
* All RDP connection settings which may be updated by unprivileged users
|
const char* name, const char* value, void* data) {
|
||||||
* through "argv" streams.
|
|
||||||
*/
|
|
||||||
typedef enum guac_rdp_argv_setting {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The username of the connection.
|
|
||||||
*/
|
|
||||||
GUAC_RDP_ARGV_SETTING_USERNAME,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The password to authenticate the connection.
|
|
||||||
*/
|
|
||||||
GUAC_RDP_ARGV_SETTING_PASSWORD,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The domain to use for connection authentication.
|
|
||||||
*/
|
|
||||||
GUAC_RDP_ARGV_SETTING_DOMAIN,
|
|
||||||
|
|
||||||
} guac_rdp_argv_setting;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The value or current status of a connection parameter received over an
|
|
||||||
* "argv" stream.
|
|
||||||
*/
|
|
||||||
typedef struct guac_rdp_argv {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The specific setting being updated.
|
|
||||||
*/
|
|
||||||
guac_rdp_argv_setting setting;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer space for containing the received argument value.
|
|
||||||
*/
|
|
||||||
char buffer[GUAC_RDP_ARGV_MAX_LENGTH];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of bytes received so far.
|
|
||||||
*/
|
|
||||||
int length;
|
|
||||||
|
|
||||||
} guac_rdp_argv;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for "blob" instructions which appends the data from received blobs
|
|
||||||
* to the end of the in-progress argument value buffer.
|
|
||||||
*
|
|
||||||
* @see guac_user_blob_handler
|
|
||||||
*/
|
|
||||||
static int guac_rdp_argv_blob_handler(guac_user* user,
|
|
||||||
guac_stream* stream, void* data, int length) {
|
|
||||||
|
|
||||||
guac_rdp_argv* argv = (guac_rdp_argv*) stream->data;
|
|
||||||
|
|
||||||
/* Calculate buffer size remaining, including space for null terminator,
|
|
||||||
adjusting received length accordingly */
|
|
||||||
int remaining = sizeof(argv->buffer) - argv->length - 1;
|
|
||||||
if (length > remaining)
|
|
||||||
length = remaining;
|
|
||||||
|
|
||||||
/* Append received data to end of buffer */
|
|
||||||
memcpy(argv->buffer + argv->length, data, length);
|
|
||||||
argv->length += length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for "end" instructions which applies the changes specified by the
|
|
||||||
* argument value buffer associated with the stream.
|
|
||||||
*
|
|
||||||
* @see guac_user_end_handler
|
|
||||||
*/
|
|
||||||
static int guac_rdp_argv_end_handler(guac_user* user,
|
|
||||||
guac_stream* stream) {
|
|
||||||
|
|
||||||
guac_client* client = user->client;
|
guac_client* client = user->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_rdp_settings* settings = rdp_client->settings;
|
guac_rdp_settings* settings = rdp_client->settings;
|
||||||
|
|
||||||
/* Append null terminator to value */
|
|
||||||
guac_rdp_argv* argv = (guac_rdp_argv*) stream->data;
|
|
||||||
|
|
||||||
/* Apply changes to chosen setting */
|
/* Update username */
|
||||||
switch (argv->setting) {
|
if (strcmp(name, GUAC_RDP_ARGV_USERNAME) == 0) {
|
||||||
|
free(settings->username);
|
||||||
/* Update RDP username. */
|
settings->username = strdup(value);
|
||||||
case GUAC_RDP_ARGV_SETTING_USERNAME:
|
|
||||||
free(settings->username);
|
|
||||||
settings->username = strndup(argv->buffer, argv->length);
|
|
||||||
rdp_client->rdp_credential_flags &= ~GUAC_RDP_CRED_FLAG_USERNAME;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUAC_RDP_ARGV_SETTING_PASSWORD:
|
|
||||||
free(settings->password);
|
|
||||||
settings->password = strndup(argv->buffer, argv->length);
|
|
||||||
rdp_client->rdp_credential_flags &= ~GUAC_RDP_CRED_FLAG_PASSWORD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GUAC_RDP_ARGV_SETTING_DOMAIN:
|
|
||||||
free(settings->domain);
|
|
||||||
settings->domain = strndup(argv->buffer, argv->length);
|
|
||||||
rdp_client->rdp_credential_flags &= ~GUAC_RDP_CRED_FLAG_DOMAIN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rdp_client->rdp_credential_flags)
|
/* Update password */
|
||||||
pthread_cond_signal(&(rdp_client->rdp_credential_cond));
|
else if (strcmp(name, GUAC_RDP_ARGV_PASSWORD) == 0) {
|
||||||
|
free(settings->password);
|
||||||
free(argv);
|
settings->password = strdup(value);
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
}
|
/* Update domain */
|
||||||
|
else if (strcmp(name, GUAC_RDP_ARGV_DOMAIN) == 0) {
|
||||||
int guac_rdp_argv_handler(guac_user* user, guac_stream* stream,
|
free(settings->domain);
|
||||||
char* mimetype, char* name) {
|
settings->domain = strdup(value);
|
||||||
|
|
||||||
guac_rdp_argv_setting setting;
|
|
||||||
|
|
||||||
/* Allow users to update authentication details */
|
|
||||||
if (strcmp(name, GUAC_RDP_ARGV_USERNAME) == 0)
|
|
||||||
setting = GUAC_RDP_ARGV_SETTING_USERNAME;
|
|
||||||
else if (strcmp(name, GUAC_RDP_ARGV_PASSWORD) == 0)
|
|
||||||
setting = GUAC_RDP_ARGV_SETTING_PASSWORD;
|
|
||||||
else if (strcmp(name, GUAC_RDP_ARGV_DOMAIN) == 0)
|
|
||||||
setting = GUAC_RDP_ARGV_SETTING_DOMAIN;
|
|
||||||
|
|
||||||
/* No other connection parameters may be updated */
|
|
||||||
else {
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
|
||||||
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guac_rdp_argv* argv = malloc(sizeof(guac_rdp_argv));
|
|
||||||
argv->setting = setting;
|
|
||||||
argv->length = 0;
|
|
||||||
|
|
||||||
/* Prepare stream to receive argument value */
|
|
||||||
stream->blob_handler = guac_rdp_argv_blob_handler;
|
|
||||||
stream->end_handler = guac_rdp_argv_end_handler;
|
|
||||||
stream->data = argv;
|
|
||||||
|
|
||||||
/* Signal stream is ready */
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Ready for updated "
|
|
||||||
"parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -23,19 +23,14 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of bytes to allow for any argument value received via an
|
* Handles a received argument value from a Guacamole "argv" instruction,
|
||||||
* argv stream, including null terminator.
|
* updating the given connection parameter.
|
||||||
*/
|
*/
|
||||||
#define GUAC_RDP_ARGV_MAX_LENGTH 16384
|
guac_argv_callback guac_rdp_argv_callback;
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an incoming stream from a Guacamole "argv" instruction, updating the
|
|
||||||
* given connection parameter if that parameter is allowed to be updated.
|
|
||||||
*/
|
|
||||||
guac_user_argv_handler guac_rdp_argv_handler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the parameter that specifies/updates the username that will be
|
* The name of the parameter that specifies/updates the username that will be
|
||||||
|
@ -158,11 +158,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
/* Initalize the lock */
|
/* Initalize the lock */
|
||||||
pthread_rwlock_init(&(rdp_client->lock), NULL);
|
pthread_rwlock_init(&(rdp_client->lock), NULL);
|
||||||
|
|
||||||
/* Init RDP credential lock and condition */
|
|
||||||
pthread_mutex_init(&(rdp_client->rdp_credential_lock), &(rdp_client->attributes));
|
|
||||||
pthread_cond_init(&(rdp_client->rdp_credential_cond), NULL);;
|
|
||||||
rdp_client->rdp_credential_flags = 0;
|
|
||||||
|
|
||||||
/* Set handlers */
|
/* Set handlers */
|
||||||
client->join_handler = guac_rdp_user_join_handler;
|
client->join_handler = guac_rdp_user_join_handler;
|
||||||
client->free_handler = guac_rdp_client_free_handler;
|
client->free_handler = guac_rdp_client_free_handler;
|
||||||
@ -223,10 +218,6 @@ int guac_rdp_client_free_handler(guac_client* client) {
|
|||||||
/* Clean up audio input buffer, if allocated */
|
/* Clean up audio input buffer, if allocated */
|
||||||
if (rdp_client->audio_input != NULL)
|
if (rdp_client->audio_input != NULL)
|
||||||
guac_rdp_audio_buffer_free(rdp_client->audio_input);
|
guac_rdp_audio_buffer_free(rdp_client->audio_input);
|
||||||
|
|
||||||
/* Destroy the pthread conditional handler */
|
|
||||||
pthread_cond_destroy(&(rdp_client->rdp_credential_cond));
|
|
||||||
pthread_mutex_destroy(&(rdp_client->rdp_credential_lock));
|
|
||||||
|
|
||||||
pthread_rwlock_destroy(&(rdp_client->lock));
|
pthread_rwlock_destroy(&(rdp_client->lock));
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include <freerdp/primary.h>
|
#include <freerdp/primary.h>
|
||||||
#include <freerdp/settings.h>
|
#include <freerdp/settings.h>
|
||||||
#include <freerdp/update.h>
|
#include <freerdp/update.h>
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/audio.h>
|
#include <guacamole/audio.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
@ -247,25 +248,25 @@ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username,
|
|||||||
"be requested.");
|
"be requested.");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the username is undefined, add it to the requested parameters. */
|
/* If the username is undefined, add it to the requested parameters. */
|
||||||
if (settings->username == NULL) {
|
if (settings->username == NULL) {
|
||||||
|
guac_argv_register(GUAC_RDP_ARGV_USERNAME, guac_rdp_argv_callback, NULL, 0);
|
||||||
params[i] = GUAC_RDP_ARGV_USERNAME;
|
params[i] = GUAC_RDP_ARGV_USERNAME;
|
||||||
rdp_client->rdp_credential_flags |= GUAC_RDP_CRED_FLAG_USERNAME;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the password is undefined, add it to the requested parameters. */
|
/* If the password is undefined, add it to the requested parameters. */
|
||||||
if (settings->password == NULL) {
|
if (settings->password == NULL) {
|
||||||
|
guac_argv_register(GUAC_RDP_ARGV_PASSWORD, guac_rdp_argv_callback, NULL, 0);
|
||||||
params[i] = GUAC_RDP_ARGV_PASSWORD;
|
params[i] = GUAC_RDP_ARGV_PASSWORD;
|
||||||
rdp_client->rdp_credential_flags |= GUAC_RDP_CRED_FLAG_PASSWORD;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the domain is undefined, add it to the requested parameters. */
|
/* If the domain is undefined, add it to the requested parameters. */
|
||||||
if (settings->domain == NULL) {
|
if (settings->domain == NULL) {
|
||||||
|
guac_argv_register(GUAC_RDP_ARGV_DOMAIN, guac_rdp_argv_callback, NULL, 0);
|
||||||
params[i] = GUAC_RDP_ARGV_DOMAIN;
|
params[i] = GUAC_RDP_ARGV_DOMAIN;
|
||||||
rdp_client->rdp_credential_flags |= GUAC_RDP_CRED_FLAG_DOMAIN;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,22 +274,17 @@ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username,
|
|||||||
params[i] = NULL;
|
params[i] = NULL;
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
/* Lock the client thread. */
|
|
||||||
pthread_mutex_lock(&(rdp_client->rdp_credential_lock));
|
|
||||||
|
|
||||||
/* Send required 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. */
|
guac_argv_await((const char**) params);
|
||||||
pthread_cond_wait(&(rdp_client->rdp_credential_cond), &(rdp_client->rdp_credential_lock));
|
|
||||||
|
|
||||||
/* Get new values from settings. */
|
/* Get new values from settings. */
|
||||||
*username = settings->username;
|
*username = settings->username;
|
||||||
*password = settings->password;
|
*password = settings->password;
|
||||||
*domain = settings->domain;
|
*domain = settings->domain;
|
||||||
|
|
||||||
/* Unlock the thread. */
|
|
||||||
pthread_mutex_unlock(&(rdp_client->rdp_credential_lock));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always return TRUE allowing connection to retry. */
|
/* Always return TRUE allowing connection to retry. */
|
||||||
|
@ -49,21 +49,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag for tracking if we are waiting conditionally on a username.
|
|
||||||
*/
|
|
||||||
#define GUAC_RDP_CRED_FLAG_USERNAME 1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag for tracking if we are waiting conditionally on a password.
|
|
||||||
*/
|
|
||||||
#define GUAC_RDP_CRED_FLAG_PASSWORD 2
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag for tracking if we are waiting conditionally on a domain.
|
|
||||||
*/
|
|
||||||
#define GUAC_RDP_CRED_FLAG_DOMAIN 4
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RDP-specific client data.
|
* RDP-specific client data.
|
||||||
*/
|
*/
|
||||||
@ -168,34 +153,6 @@ typedef struct guac_rdp_client {
|
|||||||
*/
|
*/
|
||||||
guac_common_list* available_svc;
|
guac_common_list* available_svc;
|
||||||
|
|
||||||
/**
|
|
||||||
* Lock which is locked when one or more credentials are required to
|
|
||||||
* complete the connection, and unlocked when credentials have been
|
|
||||||
* provided by the client.
|
|
||||||
*/
|
|
||||||
pthread_mutex_t rdp_credential_lock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condition which is used when the pthread needs to wait for one or more
|
|
||||||
* credentials to be provided by the client.
|
|
||||||
*/
|
|
||||||
pthread_cond_t rdp_credential_cond;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flags for tracking events related to the rdp_credential_cond
|
|
||||||
* pthread condition. These flags will be set when credential parameters
|
|
||||||
* are required by the connection, and cleared when those have been
|
|
||||||
* provided by the client. All flags are cleared at the start of the
|
|
||||||
* connection, and then set as the RDP client determines that further
|
|
||||||
* information is required.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @see GUAC_RDP_CRED_FLAG_USERNAME
|
|
||||||
* @see GUAC_RDP_CRED_FLAG_PASSWORD
|
|
||||||
* @see GUAC_RDP_CRED_FLAG_DOMAIN
|
|
||||||
*/
|
|
||||||
unsigned rdp_credential_flags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common attributes for locks.
|
* Common attributes for locks.
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "argv.h"
|
|
||||||
#include "channels/audio-input/audio-input.h"
|
#include "channels/audio-input/audio-input.h"
|
||||||
#include "channels/cliprdr.h"
|
#include "channels/cliprdr.h"
|
||||||
#include "channels/pipe-svc.h"
|
#include "channels/pipe-svc.h"
|
||||||
@ -34,6 +33,7 @@
|
|||||||
#include "sftp.h"
|
#include "sftp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/audio.h>
|
#include <guacamole/audio.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
@ -119,7 +119,7 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) {
|
|||||||
user->pipe_handler = guac_rdp_pipe_svc_pipe_handler;
|
user->pipe_handler = guac_rdp_pipe_svc_pipe_handler;
|
||||||
|
|
||||||
/* Handler for updating parameters during connection. */
|
/* Handler for updating parameters during connection. */
|
||||||
user->argv_handler = guac_rdp_argv_handler;
|
user->argv_handler = guac_argv_handler;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,156 +29,25 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/**
|
int guac_vnc_argv_callback(guac_user* user, const char* mimetype,
|
||||||
* All VNC connection settings which may be updated by unprivileged users
|
const char* name, const char* value, void* data) {
|
||||||
* through "argv" streams.
|
|
||||||
*/
|
|
||||||
typedef enum guac_vnc_argv_setting {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The username for the connection.
|
|
||||||
*/
|
|
||||||
GUAC_VNC_ARGV_SETTING_USERNAME,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The password for the connection.
|
|
||||||
*/
|
|
||||||
GUAC_VNC_ARGV_SETTING_PASSWORD
|
|
||||||
|
|
||||||
} guac_vnc_argv_setting;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The value or current status of a connection parameter received over an
|
|
||||||
* "argv" stream.
|
|
||||||
*/
|
|
||||||
typedef struct guac_vnc_argv {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The specific setting being updated.
|
|
||||||
*/
|
|
||||||
guac_vnc_argv_setting setting;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer space for containing the received argument value.
|
|
||||||
*/
|
|
||||||
char buffer[GUAC_VNC_ARGV_MAX_LENGTH];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of bytes received so far.
|
|
||||||
*/
|
|
||||||
int length;
|
|
||||||
|
|
||||||
} guac_vnc_argv;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for "blob" instructions which appends the data from received blobs
|
|
||||||
* to the end of the in-progress argument value buffer.
|
|
||||||
*
|
|
||||||
* @see guac_user_blob_handler
|
|
||||||
*/
|
|
||||||
static int guac_vnc_argv_blob_handler(guac_user* user, guac_stream* stream,
|
|
||||||
void* data, int length) {
|
|
||||||
|
|
||||||
guac_vnc_argv* argv = (guac_vnc_argv*) stream->data;
|
|
||||||
|
|
||||||
/* Calculate buffer size remaining, including space for null terminator,
|
|
||||||
* adjusting received length accordingly */
|
|
||||||
int remaining = sizeof(argv->buffer) - argv->length - 1;
|
|
||||||
if (length > remaining)
|
|
||||||
length = remaining;
|
|
||||||
|
|
||||||
/* Append received data to end of buffer */
|
|
||||||
memcpy(argv->buffer + argv->length, data, length);
|
|
||||||
argv->length += length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for "end" instructions which applies the changes specified by the
|
|
||||||
* argument value buffer associated with the stream.
|
|
||||||
*
|
|
||||||
* @see guac_user_end_handler
|
|
||||||
*/
|
|
||||||
static int guac_vnc_argv_end_handler(guac_user* user, guac_stream* stream) {
|
|
||||||
|
|
||||||
guac_client* client = user->client;
|
guac_client* client = user->client;
|
||||||
guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
|
guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
|
||||||
guac_vnc_settings* settings = vnc_client->settings;
|
guac_vnc_settings* settings = vnc_client->settings;
|
||||||
|
|
||||||
/* Append null terminator to value */
|
/* Update username */
|
||||||
guac_vnc_argv* argv = (guac_vnc_argv*) stream->data;
|
if (strcmp(name, GUAC_VNC_ARGV_USERNAME) == 0) {
|
||||||
argv->buffer[argv->length] = '\0';
|
free(settings->username);
|
||||||
|
settings->username = strdup(value);
|
||||||
/* Apply changes to chosen setting */
|
|
||||||
switch (argv->setting) {
|
|
||||||
|
|
||||||
/* Update username */
|
|
||||||
case GUAC_VNC_ARGV_SETTING_USERNAME:
|
|
||||||
|
|
||||||
/* Update username in settings. */
|
|
||||||
free(settings->username);
|
|
||||||
settings->username = strndup(argv->buffer, argv->length);
|
|
||||||
|
|
||||||
/* Remove the username conditional flag. */
|
|
||||||
vnc_client->vnc_credential_flags &= ~GUAC_VNC_COND_FLAG_USERNAME;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Update password */
|
|
||||||
case GUAC_VNC_ARGV_SETTING_PASSWORD:
|
|
||||||
|
|
||||||
/* Update password in settings */
|
|
||||||
free(settings->password);
|
|
||||||
settings->password = strndup(argv->buffer, argv->length);
|
|
||||||
|
|
||||||
/* Remove the password conditional flag. */
|
|
||||||
vnc_client->vnc_credential_flags &= ~GUAC_VNC_COND_FLAG_PASSWORD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no flags are set, signal the conditional. */
|
/* Update password */
|
||||||
if (!vnc_client->vnc_credential_flags)
|
else if (strcmp(name, GUAC_VNC_ARGV_PASSWORD) == 0) {
|
||||||
pthread_cond_broadcast(&(vnc_client->vnc_credential_cond));
|
free(settings->password);
|
||||||
|
settings->password = strdup(value);
|
||||||
free(argv);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int guac_vnc_argv_handler(guac_user* user, guac_stream* stream, char* mimetype,
|
|
||||||
char* name) {
|
|
||||||
|
|
||||||
guac_vnc_argv_setting setting;
|
|
||||||
|
|
||||||
/* Allow users to update authentication information */
|
|
||||||
if (strcmp(name, GUAC_VNC_ARGV_USERNAME) == 0)
|
|
||||||
setting = GUAC_VNC_ARGV_SETTING_USERNAME;
|
|
||||||
else if (strcmp(name, GUAC_VNC_ARGV_PASSWORD) == 0)
|
|
||||||
setting = GUAC_VNC_ARGV_SETTING_PASSWORD;
|
|
||||||
|
|
||||||
/* No other connection parameters may be updated */
|
|
||||||
else {
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
|
||||||
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guac_vnc_argv* argv = malloc(sizeof(guac_vnc_argv));
|
|
||||||
argv->setting = setting;
|
|
||||||
argv->length = 0;
|
|
||||||
|
|
||||||
/* Prepare stream to receive argument value */
|
|
||||||
stream->blob_handler = guac_vnc_argv_blob_handler;
|
|
||||||
stream->end_handler = guac_vnc_argv_end_handler;
|
|
||||||
stream->data = argv;
|
|
||||||
|
|
||||||
/* Signal stream is ready */
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Ready for updated "
|
|
||||||
"parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
@ -22,20 +22,14 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of bytes to allow for any argument value received via an
|
* Handles a received argument value from a Guacamole "argv" instruction,
|
||||||
* argv stream, including null terminator.
|
* updating the given connection parameter.
|
||||||
*/
|
*/
|
||||||
#define GUAC_VNC_ARGV_MAX_LENGTH 16384
|
guac_argv_callback guac_vnc_argv_callback;
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an incoming stream from a Guacamole "argv" instruction, updating the
|
|
||||||
* given connection parameter if that parameter is allowed to be updated.
|
|
||||||
*/
|
|
||||||
guac_user_argv_handler guac_vnc_argv_handler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the parameter Guacamole will use to specify/update the username
|
* The name of the parameter Guacamole will use to specify/update the username
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "vnc.h"
|
#include "vnc.h"
|
||||||
|
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
#include <guacamole/socket.h>
|
#include <guacamole/socket.h>
|
||||||
@ -44,22 +45,17 @@ char* guac_vnc_get_password(rfbClient* client) {
|
|||||||
|
|
||||||
/* 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. */
|
|
||||||
pthread_mutex_lock(&(vnc_client->vnc_credential_lock));
|
guac_argv_register(GUAC_VNC_ARGV_PASSWORD, guac_vnc_argv_callback, NULL, 0);
|
||||||
|
|
||||||
|
const char* params[] = {GUAC_VNC_ARGV_PASSWORD, NULL};
|
||||||
|
|
||||||
/* Send the request for password to the owner. */
|
/* Send the request for password to the owner. */
|
||||||
guac_client_owner_send_required(gc,
|
guac_client_owner_send_required(gc, params);
|
||||||
(const char* []) {GUAC_VNC_ARGV_PASSWORD, NULL});
|
|
||||||
|
/* Wait for the arguments to be returned */
|
||||||
/* Set the conditional flag. */
|
guac_argv_await(params);
|
||||||
vnc_client->vnc_credential_flags |= GUAC_VNC_COND_FLAG_PASSWORD;
|
|
||||||
|
|
||||||
/* Wait for the condition. */
|
|
||||||
pthread_cond_wait(&(vnc_client->vnc_credential_cond),
|
|
||||||
&(vnc_client->vnc_credential_lock));
|
|
||||||
|
|
||||||
/* Unlock the thread. */
|
|
||||||
pthread_mutex_unlock(&(vnc_client->vnc_credential_lock));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings->password;
|
return settings->password;
|
||||||
@ -88,36 +84,26 @@ rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType) {
|
|||||||
|
|
||||||
/* Check if username is null or empty. */
|
/* Check if username is null or empty. */
|
||||||
if (settings->username == NULL) {
|
if (settings->username == NULL) {
|
||||||
|
guac_argv_register(GUAC_VNC_ARGV_USERNAME, guac_vnc_argv_callback, NULL, 0);
|
||||||
params[i] = GUAC_VNC_ARGV_USERNAME;
|
params[i] = GUAC_VNC_ARGV_USERNAME;
|
||||||
i++;
|
i++;
|
||||||
vnc_client->vnc_credential_flags |= GUAC_VNC_COND_FLAG_USERNAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if password is null or empty. */
|
/* Check if password is null or empty. */
|
||||||
if (settings->password == NULL) {
|
if (settings->password == NULL) {
|
||||||
|
guac_argv_register(GUAC_VNC_ARGV_PASSWORD, guac_vnc_argv_callback, NULL, 0);
|
||||||
params[i] = GUAC_VNC_ARGV_PASSWORD;
|
params[i] = GUAC_VNC_ARGV_PASSWORD;
|
||||||
i++;
|
i++;
|
||||||
vnc_client->vnc_credential_flags |= GUAC_VNC_COND_FLAG_PASSWORD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have empty parameters, request them. */
|
/* If we have empty parameters, request them. */
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
/* Lock the thread. */
|
|
||||||
pthread_mutex_lock(&(vnc_client->vnc_credential_lock));
|
|
||||||
|
|
||||||
/* Send required parameters to owner. */
|
/* Send required parameters to owner. */
|
||||||
guac_client_owner_send_required(gc, (const char**) params);
|
guac_client_owner_send_required(gc, (const char**) params);
|
||||||
|
|
||||||
/* Wait for the parameters to be returned. */
|
/* Wait for the parameters to be returned. */
|
||||||
pthread_cond_wait(&(vnc_client->vnc_credential_cond),
|
guac_argv_await((const char**) params);
|
||||||
&(vnc_client->vnc_credential_lock));
|
|
||||||
|
|
||||||
/* Pull the credentials from updated settings. */
|
|
||||||
creds->userCredential.username = settings->username;
|
|
||||||
creds->userCredential.password = settings->password;
|
|
||||||
|
|
||||||
/* Unlock the thread. */
|
|
||||||
pthread_mutex_unlock(&(vnc_client->vnc_credential_lock));
|
|
||||||
|
|
||||||
return creds;
|
return creds;
|
||||||
|
|
||||||
|
@ -53,11 +53,6 @@ int guac_client_init(guac_client* client) {
|
|||||||
/* Initialize the TLS write lock */
|
/* Initialize the TLS write lock */
|
||||||
pthread_mutex_init(&vnc_client->tls_lock, NULL);
|
pthread_mutex_init(&vnc_client->tls_lock, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize credential lock, cond, and flags */
|
|
||||||
pthread_mutex_init(&vnc_client->vnc_credential_lock, NULL);
|
|
||||||
pthread_cond_init(&vnc_client->vnc_credential_cond, NULL);
|
|
||||||
vnc_client->vnc_credential_flags = 0;
|
|
||||||
|
|
||||||
/* Init clipboard */
|
/* Init clipboard */
|
||||||
vnc_client->clipboard = guac_common_clipboard_alloc(GUAC_VNC_CLIPBOARD_MAX_LENGTH);
|
vnc_client->clipboard = guac_common_clipboard_alloc(GUAC_VNC_CLIPBOARD_MAX_LENGTH);
|
||||||
@ -140,10 +135,6 @@ int guac_vnc_client_free_handler(guac_client* client) {
|
|||||||
/* Clean up TLS lock mutex. */
|
/* Clean up TLS lock mutex. */
|
||||||
pthread_mutex_destroy(&(vnc_client->tls_lock));
|
pthread_mutex_destroy(&(vnc_client->tls_lock));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Clean up credential mutex */
|
|
||||||
pthread_cond_destroy(&vnc_client->vnc_credential_cond);
|
|
||||||
pthread_mutex_destroy(&vnc_client->vnc_credential_lock);
|
|
||||||
|
|
||||||
/* Free generic data struct */
|
/* Free generic data struct */
|
||||||
free(client->data);
|
free(client->data);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "pulse/pulse.h"
|
#include "pulse/pulse.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <guacamole/argv.h>
|
||||||
#include <guacamole/audio.h>
|
#include <guacamole/audio.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/socket.h>
|
#include <guacamole/socket.h>
|
||||||
@ -98,6 +99,9 @@ int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) {
|
|||||||
/* Inbound (client to server) clipboard transfer */
|
/* Inbound (client to server) clipboard transfer */
|
||||||
if (!settings->disable_paste)
|
if (!settings->disable_paste)
|
||||||
user->clipboard_handler = guac_vnc_clipboard_handler;
|
user->clipboard_handler = guac_vnc_clipboard_handler;
|
||||||
|
|
||||||
|
/* Updates to connection parameters */
|
||||||
|
user->argv_handler = guac_argv_handler;
|
||||||
|
|
||||||
#ifdef ENABLE_COMMON_SSH
|
#ifdef ENABLE_COMMON_SSH
|
||||||
/* Set generic (non-filesystem) file upload handler */
|
/* Set generic (non-filesystem) file upload handler */
|
||||||
|
@ -45,16 +45,6 @@
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag for tracking the status of requesting username from client.
|
|
||||||
*/
|
|
||||||
#define GUAC_VNC_COND_FLAG_USERNAME 1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag for tracking the status of requesting password from client.
|
|
||||||
*/
|
|
||||||
#define GUAC_VNC_COND_FLAG_PASSWORD 2
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VNC-specific client data.
|
* VNC-specific client data.
|
||||||
*/
|
*/
|
||||||
@ -143,30 +133,6 @@ typedef struct guac_vnc_client {
|
|||||||
* Clipboard encoding-specific writer.
|
* Clipboard encoding-specific writer.
|
||||||
*/
|
*/
|
||||||
guac_iconv_write* clipboard_writer;
|
guac_iconv_write* clipboard_writer;
|
||||||
|
|
||||||
/**
|
|
||||||
* A lock that controls access to updating credentials when connecting
|
|
||||||
* to a VNC server.
|
|
||||||
*/
|
|
||||||
pthread_mutex_t vnc_credential_lock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A condition for signaling the thread when credentials have been
|
|
||||||
* retrieved from the client.
|
|
||||||
*/
|
|
||||||
pthread_cond_t vnc_credential_cond;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A field to track flags related to retrieving required credentials
|
|
||||||
* from the client. These flags will be set when credentials are required
|
|
||||||
* that have not been provided, and cleared when those credentials are
|
|
||||||
* provided. All flags are cleared at the start of the connection, and
|
|
||||||
* then set as the client determines which are required.
|
|
||||||
*
|
|
||||||
* @see GUAC_VNC_COND_FLAG_USERNAME
|
|
||||||
* @see GUAC_VNC_COND_FLAG_PASSWORD
|
|
||||||
*/
|
|
||||||
unsigned vnc_credential_flags;
|
|
||||||
|
|
||||||
} guac_vnc_client;
|
} guac_vnc_client;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user