GUACAMOLE-208: Merge new protocol status codes.
This commit is contained in:
commit
077cc84d27
@ -483,7 +483,7 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
||||
|
||||
/* If unable to connect to anything, fail */
|
||||
if (current_address == NULL) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
||||
"Unable to connect to any addresses.");
|
||||
close(fd);
|
||||
return NULL;
|
||||
|
@ -35,8 +35,8 @@
|
||||
*
|
||||
* 0x0000 - 0x00FF: Successful operations.
|
||||
* 0x0100 - 0x01FF: Operations that failed due to implementation status.
|
||||
* 0x0200 - 0x02FF: Operations that failed due to environmental.
|
||||
* 0x0300 - 0x03FF: Operations that failed due to user action.
|
||||
* 0x0200 - 0x02FF: Operations that failed due to remote state/environment.
|
||||
* 0x0300 - 0x03FF: Operations that failed due to user/client action.
|
||||
*
|
||||
* There is a general correspondence of these status codes with HTTP response
|
||||
* codes.
|
||||
@ -67,25 +67,25 @@ typedef enum guac_protocol_status {
|
||||
* The operation could not be performed because the upstream server
|
||||
* is not responding.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_TIMEOUT = 0x202,
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_TIMEOUT = 0x0202,
|
||||
|
||||
/**
|
||||
* The operation was unsuccessful due to an error or otherwise
|
||||
* unexpected condition of the upstream server.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR = 0x203,
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR = 0x0203,
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the requested resource
|
||||
* does not exist.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND = 0x204,
|
||||
GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND = 0x0204,
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the requested resource is
|
||||
* already in use.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_RESOURCE_CONFLICT = 0x205,
|
||||
GUAC_PROTOCOL_STATUS_RESOURCE_CONFLICT = 0x0205,
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the requested resource is now
|
||||
@ -93,6 +93,35 @@ typedef enum guac_protocol_status {
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_RESOURCE_CLOSED = 0x0206,
|
||||
|
||||
/**
|
||||
* The operation could not be performed because the upstream server does
|
||||
* not appear to exist.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND = 0x0207,
|
||||
|
||||
/**
|
||||
* The operation could not be performed because the upstream server is not
|
||||
* available to service the request.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE = 0x0208,
|
||||
|
||||
/**
|
||||
* The session within the upstream server has ended because it conflicted
|
||||
* with another session.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_SESSION_CONFLICT = 0x0209,
|
||||
|
||||
/**
|
||||
* The session within the upstream server has ended because it appeared to
|
||||
* be inactive.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_SESSION_TIMEOUT = 0x020A,
|
||||
|
||||
/**
|
||||
* The session within the upstream server has been forcibly terminated.
|
||||
*/
|
||||
GUAC_PROTOCOL_STATUS_SESSION_CLOSED = 0x020B,
|
||||
|
||||
/**
|
||||
* The operation could not be performed because bad parameters were
|
||||
* given.
|
||||
|
@ -29,6 +29,7 @@ libguac_client_rdp_la_SOURCES = \
|
||||
audio_input.c \
|
||||
client.c \
|
||||
dvc.c \
|
||||
error.c \
|
||||
input.c \
|
||||
keyboard.c \
|
||||
ptr_string.c \
|
||||
@ -98,6 +99,7 @@ noinst_HEADERS = \
|
||||
audio_input.h \
|
||||
client.h \
|
||||
dvc.h \
|
||||
error.h \
|
||||
input.h \
|
||||
keyboard.h \
|
||||
ptr_string.h \
|
||||
|
146
src/protocols/rdp/error.c
Normal file
146
src/protocols/rdp/error.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
void guac_rdp_client_abort(guac_client* client) {
|
||||
|
||||
/*
|
||||
* NOTE: The RDP status codes translated here are documented within
|
||||
* [MS-RDPBCGR], section 2.2.5.1.1: "Set Error Info PDU Data", in the
|
||||
* description of the "errorInfo" field.
|
||||
*
|
||||
* https://msdn.microsoft.com/en-us/library/cc240544.aspx
|
||||
*/
|
||||
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
freerdp* rdp_inst = rdp_client->rdp_inst;
|
||||
|
||||
guac_protocol_status status;
|
||||
const char* message;
|
||||
|
||||
/* Read disconnect reason code from connection */
|
||||
int error_info = freerdp_error_info(rdp_inst);
|
||||
|
||||
/* Translate reason code into Guacamole protocol status */
|
||||
switch (error_info) {
|
||||
|
||||
/* Normal disconnect */
|
||||
case 0x0: /* ERRINFO_SUCCESS */
|
||||
status = GUAC_PROTOCOL_STATUS_SUCCESS;
|
||||
message = "Disconnected.";
|
||||
break;
|
||||
|
||||
/* Forced disconnect (possibly by admin) */
|
||||
case 0x1: /* ERRINFO_RPC_INITIATED_DISCONNECT */
|
||||
status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED;
|
||||
message = "Forcibly disconnected.";
|
||||
break;
|
||||
|
||||
/* The user was logged off (possibly by admin) */
|
||||
case 0x2: /* ERRINFO_RPC_INITIATED_LOGOFF */
|
||||
status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED;
|
||||
message = "Logged off.";
|
||||
break;
|
||||
|
||||
/* The user was idle long enough that the RDP server disconnected */
|
||||
case 0x3: /* ERRINFO_IDLE_TIMEOUT */
|
||||
status = GUAC_PROTOCOL_STATUS_SESSION_TIMEOUT;
|
||||
message = "Idle session time limit exceeded.";
|
||||
break;
|
||||
|
||||
/* The user's session has been active for too long */
|
||||
case 0x4: /* ERRINFO_LOGON_TIMEOUT */
|
||||
status = GUAC_PROTOCOL_STATUS_SESSION_CLOSED;
|
||||
message = "Active session time limit exceeded.";
|
||||
break;
|
||||
|
||||
/* Another user logged on, disconnecting this user */
|
||||
case 0x5: /* ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION */
|
||||
status = GUAC_PROTOCOL_STATUS_SESSION_CONFLICT;
|
||||
message = "Disconnected by other connection.";
|
||||
break;
|
||||
|
||||
/* The RDP server is refusing to service the connection */
|
||||
case 0x6: /* ERRINFO_OUT_OF_MEMORY */
|
||||
case 0x7: /* ERRINFO_SERVER_DENIED_CONNECTION */
|
||||
status = GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE;
|
||||
message = "Server refused connection.";
|
||||
break;
|
||||
|
||||
/* The user does not have permission to connect */
|
||||
case 0x9: /* ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES */
|
||||
status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN;
|
||||
message = "Insufficient privileges.";
|
||||
break;
|
||||
|
||||
/* The user's credentials have expired */
|
||||
case 0xA: /* ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED */
|
||||
status = GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN;
|
||||
message = "Credentials expired.";
|
||||
break;
|
||||
|
||||
/* The user manually disconnected using an administrative tool within
|
||||
* the session */
|
||||
case 0xB: /* ERRINFO_RPC_INITIATED_DISCONNECT_BYUSER */
|
||||
status = GUAC_PROTOCOL_STATUS_SUCCESS;
|
||||
message = "Manually disconnected.";
|
||||
break;
|
||||
|
||||
/* The user manually logged off */
|
||||
case 0xC: /* ERRINFO_LOGOFF_BY_USER */
|
||||
status = GUAC_PROTOCOL_STATUS_SUCCESS;
|
||||
message = "Manually logged off.";
|
||||
break;
|
||||
|
||||
/* Unimplemented/unknown disconnect reason code */
|
||||
default:
|
||||
status = GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR;
|
||||
message = "Upstream error.";
|
||||
|
||||
}
|
||||
|
||||
/* Send error code if an error occurred */
|
||||
if (status != GUAC_PROTOCOL_STATUS_SUCCESS) {
|
||||
guac_protocol_send_error(client->socket, message, status);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
/* Log human-readable description of disconnect at info level */
|
||||
guac_client_log(client, GUAC_LOG_INFO, "RDP server closed connection: %s",
|
||||
message);
|
||||
|
||||
/* Log internal disconnect reason code at debug level */
|
||||
if (error_info)
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Disconnect reason "
|
||||
"code: 0x%X.", error_info);
|
||||
|
||||
/* Abort connection */
|
||||
guac_client_stop(client);
|
||||
|
||||
}
|
||||
|
36
src/protocols/rdp/error.h
Normal file
36
src/protocols/rdp/error.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_RDP_ERROR_H
|
||||
#define GUAC_RDP_ERROR_H
|
||||
|
||||
#include <guacamole/client.h>
|
||||
|
||||
/**
|
||||
* Stops the current connection due to the RDP server disconnecting. If the RDP
|
||||
* server provided a reason for disconnecting, that reason will be logged, and
|
||||
* an appropriate error code will be sent to the Guacamole client.
|
||||
*
|
||||
* @param client
|
||||
* The Guacamole client to disconnect.
|
||||
*/
|
||||
void guac_rdp_client_abort(guac_client* client);
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "common/display.h"
|
||||
#include "common/recording.h"
|
||||
#include "dvc.h"
|
||||
#include "error.h"
|
||||
#include "keyboard.h"
|
||||
#include "rdp.h"
|
||||
#include "rdp_bitmap.h"
|
||||
@ -627,7 +628,7 @@ static int rdp_guac_client_wait_for_messages(guac_client* client,
|
||||
return 0;
|
||||
|
||||
/* Otherwise, return as error */
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
|
||||
"Error waiting for file descriptor.");
|
||||
return -1;
|
||||
|
||||
@ -722,7 +723,7 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
|
||||
/* Connect to RDP server */
|
||||
if (!freerdp_connect(rdp_inst)) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
||||
"Error connecting to RDP server");
|
||||
return 1;
|
||||
}
|
||||
@ -764,7 +765,7 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
/* Check the libfreerdp fds */
|
||||
if (!freerdp_check_fds(rdp_inst)) {
|
||||
guac_client_abort(client,
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
|
||||
"Error handling RDP file descriptors");
|
||||
pthread_mutex_unlock(&(rdp_client->rdp_lock));
|
||||
return 1;
|
||||
@ -773,7 +774,7 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
/* Check channel fds */
|
||||
if (!freerdp_channels_check_fds(channels, rdp_inst)) {
|
||||
guac_client_abort(client,
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
|
||||
"Error handling RDP channel file descriptors");
|
||||
pthread_mutex_unlock(&(rdp_client->rdp_lock));
|
||||
return 1;
|
||||
@ -802,9 +803,7 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
|
||||
/* Handle RDP disconnect */
|
||||
if (freerdp_shall_disconnect(rdp_inst)) {
|
||||
guac_client_stop(client);
|
||||
guac_client_log(client, GUAC_LOG_INFO,
|
||||
"RDP server closed connection");
|
||||
guac_rdp_client_abort(client);
|
||||
pthread_mutex_unlock(&(rdp_client->rdp_lock));
|
||||
return 1;
|
||||
}
|
||||
@ -844,7 +843,7 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
|
||||
/* If an error occurred, fail */
|
||||
if (wait_result < 0)
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
|
||||
"Connection closed.");
|
||||
|
||||
/* Flush frame */
|
||||
@ -1002,7 +1001,7 @@ void* guac_rdp_client_thread(void* data) {
|
||||
if (rdp_client->sftp_filesystem == NULL) {
|
||||
guac_common_ssh_destroy_session(rdp_client->sftp_session);
|
||||
guac_common_ssh_destroy_user(rdp_client->sftp_user);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE,
|
||||
"SFTP connection failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -352,7 +352,8 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
|
||||
|
||||
/* If unable to connect to anything, fail */
|
||||
if (current_address == NULL) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to connect to any addresses.");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
||||
"Unable to connect to any addresses.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,8 @@ void* guac_vnc_client_thread(void* data) {
|
||||
|
||||
/* If the final connect attempt fails, return error */
|
||||
if (!rfb_client) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to connect to VNC server.");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
||||
"Unable to connect to VNC server.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user