Compare commits
51 Commits
working/tn
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
47b9360d46 | ||
|
98c2a6adcb | ||
|
3b0a9bac75 | ||
|
f6893ed319 | ||
|
a5214c971a | ||
|
ccfcef8c0f | ||
|
1a7a57ed19 | ||
|
eac064bde9 | ||
|
4afc1d85ce | ||
|
818b5f79df | ||
|
8ef60bfa9d | ||
|
d90e0e97fe | ||
|
ec7964e8fb | ||
|
add7ce361b | ||
|
7d16f67d6d | ||
|
e3adb97085 | ||
|
55941823ec | ||
|
07acce8a76 | ||
|
5b1677f21a | ||
|
623c398005 | ||
|
aa92239edd | ||
|
897712c743 | ||
|
02b24d0101 | ||
|
26eadc37a3 | ||
|
6d7156bc70 | ||
|
6312e1720d | ||
|
cb7ae25177 | ||
|
a4adb3f5c0 | ||
|
5cf408ebbb | ||
|
3ca6bb0a61 | ||
|
457a169c49 | ||
|
bad381cebe | ||
|
6171da6d0b | ||
|
067f2a91a0 | ||
|
bc52485570 | ||
|
b20afa275a | ||
|
b096e47f57 | ||
|
4d211e0c9e | ||
|
dffbeac57a | ||
|
0361adc01f | ||
|
1971a9dad2 | ||
|
5dbf4820ab | ||
|
b2eb13a178 | ||
|
2bc9d5ff01 | ||
|
5918cc9f7c | ||
|
15f6e9f678 | ||
|
b5addfe3da | ||
|
7f4246b6d5 | ||
|
6ab82446bb | ||
|
9c93337d97 | ||
|
cdee93ae25 |
207
Dockerfile
207
Dockerfile
@ -21,25 +21,32 @@
|
|||||||
# Dockerfile for guacamole-server
|
# Dockerfile for guacamole-server
|
||||||
#
|
#
|
||||||
|
|
||||||
# The Ubuntu image that should be used as the basis for the guacd image
|
# The Alpine Linux image that should be used as the basis for the guacd image
|
||||||
ARG UBUNTU_BASE_IMAGE=21.10
|
ARG ALPINE_BASE_IMAGE=latest
|
||||||
|
FROM alpine:${ALPINE_BASE_IMAGE} AS builder
|
||||||
|
|
||||||
# Use Debian as base for the build
|
# Install build dependencies
|
||||||
FROM ubuntu:${UBUNTU_BASE_IMAGE} AS builder
|
RUN apk add --no-cache \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
build-base \
|
||||||
|
cairo-dev \
|
||||||
|
cmake \
|
||||||
|
git \
|
||||||
|
grep \
|
||||||
|
libjpeg-turbo-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libtool \
|
||||||
|
libwebp-dev \
|
||||||
|
make \
|
||||||
|
openssl-dev \
|
||||||
|
pango-dev \
|
||||||
|
pulseaudio-dev \
|
||||||
|
util-linux-dev
|
||||||
|
|
||||||
#
|
# Copy source to container for sake of build
|
||||||
# The Debian repository that should be preferred for dependencies (this will be
|
ARG BUILD_DIR=/tmp/guacamole-server
|
||||||
# added to /etc/apt/sources.list if not already present)
|
COPY . ${BUILD_DIR}
|
||||||
#
|
|
||||||
# NOTE: Due to limitations of the Docker image build process, this value is
|
|
||||||
# duplicated in an ARG in the second stage of the build.
|
|
||||||
#
|
|
||||||
ARG UBUNTU_RELEASE=impish-backports
|
|
||||||
|
|
||||||
# Add repository for specified Ubuntu release if not already present in
|
|
||||||
# sources.list
|
|
||||||
RUN grep " ${UBUNTU_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources.list \
|
|
||||||
"deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE} main contrib non-free"
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Base directory for installed build artifacts.
|
# Base directory for installed build artifacts.
|
||||||
@ -47,70 +54,99 @@ RUN grep " ${UBUNTU_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources
|
|||||||
# NOTE: Due to limitations of the Docker image build process, this value is
|
# NOTE: Due to limitations of the Docker image build process, this value is
|
||||||
# duplicated in an ARG in the second stage of the build.
|
# duplicated in an ARG in the second stage of the build.
|
||||||
#
|
#
|
||||||
ARG PREFIX_DIR=/usr/local/guacamole
|
ARG PREFIX_DIR=/opt/guacamole
|
||||||
|
|
||||||
# Build arguments
|
#
|
||||||
ARG BUILD_DIR=/tmp/guacd-docker-BUILD
|
# Automatically select the latest versions of each core protocol support
|
||||||
ARG BUILD_DEPENDENCIES=" \
|
# library (these can be overridden at build time if a specific version is
|
||||||
autoconf \
|
# needed)
|
||||||
automake \
|
#
|
||||||
freerdp2-dev \
|
ARG WITH_FREERDP='2(\.\d+)+'
|
||||||
gcc \
|
ARG WITH_LIBSSH2='libssh2-\d+(\.\d+)+'
|
||||||
libcairo2-dev \
|
ARG WITH_LIBTELNET='\d+(\.\d+)+'
|
||||||
libgcrypt-dev \
|
ARG WITH_LIBVNCCLIENT='LibVNCServer-\d+(\.\d+)+'
|
||||||
libjpeg-turbo8-dev \
|
ARG WITH_LIBWEBSOCKETS='v\d+(\.\d+)+'
|
||||||
libossp-uuid-dev \
|
|
||||||
libpango1.0-dev \
|
|
||||||
libpulse-dev \
|
|
||||||
libssh2-1-dev \
|
|
||||||
libssl-dev \
|
|
||||||
libtelnet-dev \
|
|
||||||
libtool \
|
|
||||||
libvncserver-dev \
|
|
||||||
libwebsockets-dev \
|
|
||||||
libwebp-dev \
|
|
||||||
make"
|
|
||||||
|
|
||||||
# Do not require interaction during build
|
#
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
# Default build options for each core protocol support library, as well as
|
||||||
|
# guacamole-server itself (these can be overridden at build time if different
|
||||||
|
# options are needed)
|
||||||
|
#
|
||||||
|
|
||||||
# Bring build environment up to date and install build dependencies
|
ARG FREERDP_OPTS="\
|
||||||
RUN apt-get update && \
|
-DBUILTIN_CHANNELS=OFF \
|
||||||
apt-get install -t ${UBUNTU_RELEASE} -y $BUILD_DEPENDENCIES && \
|
-DCHANNEL_URBDRC=OFF \
|
||||||
rm -rf /var/lib/apt/lists/*
|
-DWITH_ALSA=OFF \
|
||||||
|
-DWITH_CAIRO=ON \
|
||||||
|
-DWITH_CHANNELS=ON \
|
||||||
|
-DWITH_CLIENT=ON \
|
||||||
|
-DWITH_CUPS=OFF \
|
||||||
|
-DWITH_DIRECTFB=OFF \
|
||||||
|
-DWITH_FFMPEG=OFF \
|
||||||
|
-DWITH_GSM=OFF \
|
||||||
|
-DWITH_GSSAPI=OFF \
|
||||||
|
-DWITH_IPP=OFF \
|
||||||
|
-DWITH_JPEG=ON \
|
||||||
|
-DWITH_LIBSYSTEMD=OFF \
|
||||||
|
-DWITH_MANPAGES=OFF \
|
||||||
|
-DWITH_OPENH264=OFF \
|
||||||
|
-DWITH_OPENSSL=ON \
|
||||||
|
-DWITH_OSS=OFF \
|
||||||
|
-DWITH_PCSC=OFF \
|
||||||
|
-DWITH_PULSE=OFF \
|
||||||
|
-DWITH_SERVER=OFF \
|
||||||
|
-DWITH_SERVER_INTERFACE=OFF \
|
||||||
|
-DWITH_SHADOW_MAC=OFF \
|
||||||
|
-DWITH_SHADOW_X11=OFF \
|
||||||
|
-DWITH_SSE2=ON \
|
||||||
|
-DWITH_WAYLAND=OFF \
|
||||||
|
-DWITH_X11=OFF \
|
||||||
|
-DWITH_X264=OFF \
|
||||||
|
-DWITH_XCURSOR=ON \
|
||||||
|
-DWITH_XEXT=ON \
|
||||||
|
-DWITH_XI=OFF \
|
||||||
|
-DWITH_XINERAMA=OFF \
|
||||||
|
-DWITH_XKBFILE=ON \
|
||||||
|
-DWITH_XRENDER=OFF \
|
||||||
|
-DWITH_XTEST=OFF \
|
||||||
|
-DWITH_XV=OFF \
|
||||||
|
-DWITH_ZLIB=ON"
|
||||||
|
|
||||||
# Add configuration scripts
|
ARG GUACAMOLE_SERVER_OPTS="\
|
||||||
COPY src/guacd-docker/bin "${PREFIX_DIR}/bin/"
|
--disable-guaclog"
|
||||||
|
|
||||||
# Copy source to container for sake of build
|
ARG LIBSSH2_OPTS="\
|
||||||
COPY . "$BUILD_DIR"
|
-DBUILD_EXAMPLES=OFF \
|
||||||
|
-DBUILD_SHARED_LIBS=ON"
|
||||||
|
|
||||||
# Build guacamole-server from local source
|
ARG LIBTELNET_OPTS="\
|
||||||
RUN ${PREFIX_DIR}/bin/build-guacd.sh "$BUILD_DIR" "$PREFIX_DIR"
|
--disable-static \
|
||||||
|
--disable-util"
|
||||||
|
|
||||||
|
ARG LIBVNCCLIENT_OPTS=""
|
||||||
|
|
||||||
|
ARG LIBWEBSOCKETS_OPTS="\
|
||||||
|
-DDISABLE_WERROR=ON \
|
||||||
|
-DLWS_WITHOUT_SERVER=ON \
|
||||||
|
-DLWS_WITHOUT_TESTAPPS=ON \
|
||||||
|
-DLWS_WITHOUT_TEST_CLIENT=ON \
|
||||||
|
-DLWS_WITHOUT_TEST_PING=ON \
|
||||||
|
-DLWS_WITHOUT_TEST_SERVER=ON \
|
||||||
|
-DLWS_WITHOUT_TEST_SERVER_EXTPOLL=ON \
|
||||||
|
-DLWS_WITH_STATIC=OFF"
|
||||||
|
|
||||||
|
# Build guacamole-server and its core protocol library dependencies
|
||||||
|
RUN ${BUILD_DIR}/src/guacd-docker/bin/build-all.sh
|
||||||
|
|
||||||
# Record the packages of all runtime library dependencies
|
# Record the packages of all runtime library dependencies
|
||||||
RUN ${PREFIX_DIR}/bin/list-dependencies.sh \
|
RUN ${BUILD_DIR}/src/guacd-docker/bin/list-dependencies.sh \
|
||||||
${PREFIX_DIR}/sbin/guacd \
|
${PREFIX_DIR}/sbin/guacd \
|
||||||
${PREFIX_DIR}/lib/libguac-client-*.so \
|
${PREFIX_DIR}/lib/libguac-client-*.so \
|
||||||
${PREFIX_DIR}/lib/freerdp2/*guac*.so \
|
${PREFIX_DIR}/lib/freerdp2/*guac*.so \
|
||||||
> ${PREFIX_DIR}/DEPENDENCIES
|
> ${PREFIX_DIR}/DEPENDENCIES
|
||||||
|
|
||||||
# Use same Debian as the base for the runtime image
|
# Use same Alpine version as the base for the runtime image
|
||||||
FROM ubuntu:${UBUNTU_BASE_IMAGE}
|
FROM alpine:${ALPINE_BASE_IMAGE}
|
||||||
|
|
||||||
#
|
|
||||||
# The Debian repository that should be preferred for dependencies (this will be
|
|
||||||
# added to /etc/apt/sources.list if not already present)
|
|
||||||
#
|
|
||||||
# NOTE: Due to limitations of the Docker image build process, this value is
|
|
||||||
# duplicated in an ARG in the first stage of the build.
|
|
||||||
#
|
|
||||||
ARG UBUNTU_RELEASE=impish-backports
|
|
||||||
|
|
||||||
# Add repository for specified Ubuntu release if not already present in
|
|
||||||
# sources.list
|
|
||||||
RUN grep " ${UBUNTU_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources.list \
|
|
||||||
"deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_RELEASE} main contrib non-free"
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Base directory for installed build artifacts. See also the
|
# Base directory for installed build artifacts. See also the
|
||||||
@ -119,36 +155,27 @@ RUN grep " ${UBUNTU_RELEASE} " /etc/apt/sources.list || echo >> /etc/apt/sources
|
|||||||
# NOTE: Due to limitations of the Docker image build process, this value is
|
# NOTE: Due to limitations of the Docker image build process, this value is
|
||||||
# duplicated in an ARG in the first stage of the build.
|
# duplicated in an ARG in the first stage of the build.
|
||||||
#
|
#
|
||||||
ARG PREFIX_DIR=/usr/local/guacamole
|
ARG PREFIX_DIR=/opt/guacamole
|
||||||
|
|
||||||
# Runtime environment
|
# Runtime environment
|
||||||
ENV LC_ALL=C.UTF-8
|
ENV LC_ALL=C.UTF-8
|
||||||
ENV LD_LIBRARY_PATH=${PREFIX_DIR}/lib
|
ENV LD_LIBRARY_PATH=${PREFIX_DIR}/lib
|
||||||
ENV GUACD_LOG_LEVEL=info
|
ENV GUACD_LOG_LEVEL=info
|
||||||
|
|
||||||
ARG RUNTIME_DEPENDENCIES=" \
|
|
||||||
netcat-openbsd \
|
|
||||||
ca-certificates \
|
|
||||||
ghostscript \
|
|
||||||
fonts-liberation \
|
|
||||||
fonts-dejavu \
|
|
||||||
xfonts-terminus"
|
|
||||||
|
|
||||||
# Do not require interaction during build
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
# Copy build artifacts into this stage
|
# Copy build artifacts into this stage
|
||||||
COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR}
|
COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR}
|
||||||
|
|
||||||
# Bring runtime environment up to date and install runtime dependencies
|
# Bring runtime environment up to date and install runtime dependencies
|
||||||
RUN apt-get update && \
|
RUN apk add --no-cache \
|
||||||
apt-get install -t ${UBUNTU_RELEASE} -y --no-install-recommends $RUNTIME_DEPENDENCIES && \
|
ca-certificates \
|
||||||
apt-get install -t ${UBUNTU_RELEASE} -y --no-install-recommends $(cat "${PREFIX_DIR}"/DEPENDENCIES) && \
|
ghostscript \
|
||||||
rm -rf /var/lib/apt/lists/*
|
netcat-openbsd \
|
||||||
|
shadow \
|
||||||
# Link FreeRDP plugins into proper path
|
terminus-font \
|
||||||
RUN ${PREFIX_DIR}/bin/link-freerdp-plugins.sh \
|
ttf-dejavu \
|
||||||
${PREFIX_DIR}/lib/freerdp2/libguac*.so
|
ttf-liberation \
|
||||||
|
util-linux-login && \
|
||||||
|
xargs apk add --no-cache < ${PREFIX_DIR}/DEPENDENCIES
|
||||||
|
|
||||||
# Checks the operating status every 5 minutes with a timeout of 5 seconds
|
# Checks the operating status every 5 minutes with a timeout of 5 seconds
|
||||||
HEALTHCHECK --interval=5m --timeout=5s CMD nc -z 127.0.0.1 4822 || exit 1
|
HEALTHCHECK --interval=5m --timeout=5s CMD nc -z 127.0.0.1 4822 || exit 1
|
||||||
@ -157,7 +184,7 @@ HEALTHCHECK --interval=5m --timeout=5s CMD nc -z 127.0.0.1 4822 || exit 1
|
|||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
RUN groupadd --gid $GID guacd
|
RUN groupadd --gid $GID guacd
|
||||||
RUN useradd --system --create-home --shell /usr/sbin/nologin --uid $UID --gid $GID guacd
|
RUN useradd --system --create-home --shell /sbin/nologin --uid $UID --gid $GID guacd
|
||||||
|
|
||||||
# Run with user guacd
|
# Run with user guacd
|
||||||
USER guacd
|
USER guacd
|
||||||
@ -170,5 +197,5 @@ EXPOSE 4822
|
|||||||
# Note the path here MUST correspond to the value specified in the
|
# Note the path here MUST correspond to the value specified in the
|
||||||
# PREFIX_DIR build argument.
|
# PREFIX_DIR build argument.
|
||||||
#
|
#
|
||||||
CMD /usr/local/guacamole/sbin/guacd -b 0.0.0.0 -L $GUACD_LOG_LEVEL -f
|
CMD /opt/guacamole/sbin/guacd -b 0.0.0.0 -L $GUACD_LOG_LEVEL -f
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ error() {
|
|||||||
##
|
##
|
||||||
usage() {
|
usage() {
|
||||||
cat >&2 <<END
|
cat >&2 <<END
|
||||||
guacctl 1.4.0, Apache Guacamole terminal session control utility.
|
guacctl 1.5.0, Apache Guacamole terminal session control utility.
|
||||||
Usage: guacctl [OPTION] [FILE or NAME]...
|
Usage: guacctl [OPTION] [FILE or NAME]...
|
||||||
|
|
||||||
-d, --download download each of the files listed.
|
-d, --download download each of the files listed.
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
AC_PREREQ([2.61])
|
AC_PREREQ([2.61])
|
||||||
AC_INIT([guacamole-server], [1.4.0])
|
AC_INIT([guacamole-server], [1.5.0])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "common-ssh/user.h"
|
#include "common-ssh/user.h"
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
|
#include <guacamole/fips.h>
|
||||||
#include <libssh2.h>
|
#include <libssh2.h>
|
||||||
|
|
||||||
#ifdef LIBSSH2_USES_GCRYPT
|
#ifdef LIBSSH2_USES_GCRYPT
|
||||||
@ -46,6 +47,20 @@
|
|||||||
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all key exchange algorithms that are both FIPS-compliant, and
|
||||||
|
* OpenSSL-supported. Note that "ext-info-c" is also included. While not a key
|
||||||
|
* exchange algorithm per se, it must be in the list to ensure that the server
|
||||||
|
* will send a SSH_MSG_EXT_INFO response, which is required to perform RSA key
|
||||||
|
* upgrades.
|
||||||
|
*/
|
||||||
|
#define FIPS_COMPLIANT_KEX_ALGORITHMS "diffie-hellman-group-exchange-sha256,ext-info-c"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of ciphers that are both FIPS-compliant, and OpenSSL-supported.
|
||||||
|
*/
|
||||||
|
#define FIPS_COMPLIANT_CIPHERS "aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,aes192-cbc,aes256-cbc"
|
||||||
|
|
||||||
#ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS
|
#ifdef OPENSSL_REQUIRES_THREADING_CALLBACKS
|
||||||
/**
|
/**
|
||||||
* Array of mutexes, used by OpenSSL.
|
* Array of mutexes, used by OpenSSL.
|
||||||
@ -165,9 +180,11 @@ int guac_common_ssh_init(guac_client* client) {
|
|||||||
CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback);
|
CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init OpenSSL */
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
/* Init OpenSSL - only required for OpenSSL Versions < 1.1.0 */
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Init libssh2 */
|
/* Init libssh2 */
|
||||||
libssh2_init(0);
|
libssh2_init(0);
|
||||||
@ -484,6 +501,17 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If FIPS mode is enabled, prefer only FIPS-compatible algorithms and
|
||||||
|
* ciphers that are also supported by libssh2. For more info, see:
|
||||||
|
* https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp2906.pdf
|
||||||
|
*/
|
||||||
|
if (guac_fips_enabled()) {
|
||||||
|
libssh2_session_method_pref(session, LIBSSH2_METHOD_KEX, FIPS_COMPLIANT_KEX_ALGORITHMS);
|
||||||
|
libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_CS, FIPS_COMPLIANT_CIPHERS);
|
||||||
|
libssh2_session_method_pref(session, LIBSSH2_METHOD_CRYPT_SC, FIPS_COMPLIANT_CIPHERS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform handshake */
|
/* Perform handshake */
|
||||||
if (libssh2_session_handshake(session, fd)) {
|
if (libssh2_session_handshake(session, fd)) {
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||||
|
@ -166,6 +166,8 @@ void guac_common_display_free(guac_common_display* display) {
|
|||||||
void guac_common_display_dup(guac_common_display* display, guac_user* user,
|
void guac_common_display_dup(guac_common_display* display, guac_user* user,
|
||||||
guac_socket* socket) {
|
guac_socket* socket) {
|
||||||
|
|
||||||
|
guac_client* client = user->client;
|
||||||
|
|
||||||
pthread_mutex_lock(&display->_lock);
|
pthread_mutex_lock(&display->_lock);
|
||||||
|
|
||||||
/* Sunchronize shared cursor */
|
/* Sunchronize shared cursor */
|
||||||
@ -178,6 +180,9 @@ void guac_common_display_dup(guac_common_display* display, guac_user* user,
|
|||||||
guac_common_display_dup_layers(display->layers, user, socket);
|
guac_common_display_dup_layers(display->layers, user, socket);
|
||||||
guac_common_display_dup_layers(display->buffers, user, socket);
|
guac_common_display_dup_layers(display->buffers, user, socket);
|
||||||
|
|
||||||
|
/* Sends a sync instruction to mark the boundary of the first frame */
|
||||||
|
guac_protocol_send_sync(socket, client->last_sent_timestamp, 1);
|
||||||
|
|
||||||
pthread_mutex_unlock(&display->_lock);
|
pthread_mutex_unlock(&display->_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -384,4 +389,3 @@ void guac_common_display_free_buffer(guac_common_display* display,
|
|||||||
pthread_mutex_unlock(&display->_lock);
|
pthread_mutex_unlock(&display->_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
115
src/guacd-docker/bin/build-all.sh
Executable file
115
src/guacd-docker/bin/build-all.sh
Executable file
@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
##
|
||||||
|
## @fn build-all.sh
|
||||||
|
##
|
||||||
|
## Builds the source of guacamole-server and its various core protocol library
|
||||||
|
## dependencies.
|
||||||
|
##
|
||||||
|
|
||||||
|
# Pre-populate build control variables such that the custom build prefix is
|
||||||
|
# used for C headers, locating libraries, etc.
|
||||||
|
export CFLAGS="-I${PREFIX_DIR}/include"
|
||||||
|
export LDFLAGS="-L${PREFIX_DIR}/lib"
|
||||||
|
export PKG_CONFIG_PATH="${PREFIX_DIR}/lib/pkgconfig"
|
||||||
|
|
||||||
|
# Ensure thread stack size will be 8 MB (glibc's default on Linux) rather than
|
||||||
|
# 128 KB (musl's default)
|
||||||
|
export LDFLAGS="$LDFLAGS -Wl,-z,stack-size=8388608"
|
||||||
|
|
||||||
|
##
|
||||||
|
## Builds and installs the source at the given git repository, automatically
|
||||||
|
## switching to the version of the source at the tag/commit that matches the
|
||||||
|
## given pattern.
|
||||||
|
##
|
||||||
|
## @param URL
|
||||||
|
## The URL of the git repository that the source should be downloaded from.
|
||||||
|
##
|
||||||
|
## @param PATTERN
|
||||||
|
## The Perl-compatible regular expression that the tag must match. If no
|
||||||
|
## tag matches the regular expression, the pattern is assumed to be an
|
||||||
|
## exact reference to a commit, branch, etc. acceptable by git checkout.
|
||||||
|
##
|
||||||
|
## @param ...
|
||||||
|
## Any additional command-line options that should be provided to CMake or
|
||||||
|
## the configure script.
|
||||||
|
##
|
||||||
|
install_from_git() {
|
||||||
|
|
||||||
|
URL="$1"
|
||||||
|
PATTERN="$2"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
# Calculate top-level directory name of resulting repository from the
|
||||||
|
# provided URL
|
||||||
|
REPO_DIR="$(basename "$URL" .git)"
|
||||||
|
|
||||||
|
# Allow dependencies to be manually omitted with the tag/commit pattern "NO"
|
||||||
|
if [ "$PATTERN" = "NO" ]; then
|
||||||
|
echo "NOT building $REPO_DIR (explicitly skipped)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clone repository and change to top-level directory of source
|
||||||
|
cd /tmp
|
||||||
|
git clone "$URL"
|
||||||
|
cd $REPO_DIR/
|
||||||
|
|
||||||
|
# Locate tag/commit based on provided pattern
|
||||||
|
VERSION="$(git tag -l --sort=-v:refname | grep -Px -m1 "$PATTERN" \
|
||||||
|
|| echo "$PATTERN")"
|
||||||
|
|
||||||
|
# Switch to desired version of source
|
||||||
|
echo "Building $REPO_DIR @ $VERSION ..."
|
||||||
|
git -c advice.detachedHead=false checkout "$VERSION"
|
||||||
|
|
||||||
|
# Configure build using CMake or GNU Autotools, whichever happens to be
|
||||||
|
# used by the library being built
|
||||||
|
if [ -e CMakeLists.txt ]; then
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX_DIR" "$@" .
|
||||||
|
else
|
||||||
|
[ -e configure ] || autoreconf -fi
|
||||||
|
./configure --prefix="$PREFIX_DIR" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build and install
|
||||||
|
make && make install
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build and install core protocol library dependencies
|
||||||
|
#
|
||||||
|
|
||||||
|
install_from_git "https://github.com/FreeRDP/FreeRDP" "$WITH_FREERDP" $FREERDP_OPTS
|
||||||
|
install_from_git "https://github.com/libssh2/libssh2" "$WITH_LIBSSH2" $LIBSSH2_OPTS
|
||||||
|
install_from_git "https://github.com/seanmiddleditch/libtelnet" "$WITH_LIBTELNET" $LIBTELNET_OPTS
|
||||||
|
install_from_git "https://github.com/LibVNC/libvncserver" "$WITH_LIBVNCCLIENT" $LIBVNCCLIENT_OPTS
|
||||||
|
install_from_git "https://libwebsockets.org/repo/libwebsockets" "$WITH_LIBWEBSOCKETS" $LIBWEBSOCKETS_OPTS
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build guacamole-server
|
||||||
|
#
|
||||||
|
|
||||||
|
cd "$BUILD_DIR"
|
||||||
|
autoreconf -fi && ./configure --prefix="$PREFIX_DIR" $GUACAMOLE_SERVER_OPTS
|
||||||
|
make && make install
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
##
|
|
||||||
## @fn build-guacd.sh
|
|
||||||
##
|
|
||||||
## Builds the source of guacamole-server, automatically creating any required
|
|
||||||
## symbolic links for the proper loading of FreeRDP plugins.
|
|
||||||
##
|
|
||||||
## @param BUILD_DIR
|
|
||||||
## The directory which currently contains the guacamole-server source and
|
|
||||||
## in which the build should be performed.
|
|
||||||
##
|
|
||||||
## @param PREFIX_DIR
|
|
||||||
## The directory prefix into which the build artifacts should be installed
|
|
||||||
## in which the build should be performed. This is passed to the --prefix
|
|
||||||
## option of `configure`.
|
|
||||||
##
|
|
||||||
|
|
||||||
BUILD_DIR="$1"
|
|
||||||
PREFIX_DIR="$2"
|
|
||||||
|
|
||||||
#
|
|
||||||
# Build guacamole-server
|
|
||||||
#
|
|
||||||
|
|
||||||
cd "$BUILD_DIR"
|
|
||||||
autoreconf -fi
|
|
||||||
./configure --prefix="$PREFIX_DIR" --disable-guaclog --with-freerdp-plugin-dir="$PREFIX_DIR/lib/freerdp2"
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
ldconfig
|
|
@ -1,76 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
##
|
|
||||||
## @fn link-freerdp-plugins.sh
|
|
||||||
##
|
|
||||||
## Automatically creates any required symbolic links for the proper loading of
|
|
||||||
## the given FreeRDP plugins. If a given plugin is already in the correct
|
|
||||||
## directory, no link is created for that plugin.
|
|
||||||
##
|
|
||||||
## @param ...
|
|
||||||
## The FreeRDP plugins to add links for.
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
## Locates the base directory of the FreeRDP installation (where the FreeRDP library
|
|
||||||
## .so files are located), printing the result to STDOUT. If the directory cannot be
|
|
||||||
## determined, an error is printed.
|
|
||||||
##
|
|
||||||
where_is_freerdp() {
|
|
||||||
|
|
||||||
# Determine the location of any freerdp2 .so files
|
|
||||||
PATHS="$(find / -iname '*libfreerdp2.so.*' \
|
|
||||||
| xargs -r dirname \
|
|
||||||
| xargs -r realpath \
|
|
||||||
| sort -u)"
|
|
||||||
|
|
||||||
# Verify that exactly one location was found
|
|
||||||
if [ -z "$PATHS" -o "$(echo "$PATHS" | wc -l)" != 1 ]; then
|
|
||||||
echo "$1: Unable to locate FreeRDP install location." >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$PATHS"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Create symbolic links as necessary to include all given plugins within the
|
|
||||||
# search path of FreeRDP
|
|
||||||
#
|
|
||||||
|
|
||||||
# Determine correct install location for FreeRDP plugins
|
|
||||||
FREERDP_DIR="$(where_is_freerdp)"
|
|
||||||
FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp2"
|
|
||||||
|
|
||||||
while [ -n "$1" ]; do
|
|
||||||
|
|
||||||
# Add symbolic link if necessary
|
|
||||||
if [ ! -e "$FREERDP_PLUGIN_DIR/$(basename "$1")" ]; then
|
|
||||||
mkdir -p "$FREERDP_PLUGIN_DIR"
|
|
||||||
ln -s "$1" "$FREERDP_PLUGIN_DIR"
|
|
||||||
else
|
|
||||||
echo "$1: Already in correct directory." >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
shift
|
|
||||||
|
|
||||||
done
|
|
@ -21,7 +21,7 @@
|
|||||||
##
|
##
|
||||||
## @fn list-dependencies.sh
|
## @fn list-dependencies.sh
|
||||||
##
|
##
|
||||||
## Lists the Debian/Ubuntu package names for all library dependencies of the
|
## Lists the Alpine Linux package names for all library dependencies of the
|
||||||
## given binaries. Each package is only listed once, even if multiple binaries
|
## given binaries. Each package is only listed once, even if multiple binaries
|
||||||
## provided by the same package are given.
|
## provided by the same package are given.
|
||||||
##
|
##
|
||||||
@ -35,19 +35,17 @@ while [ -n "$1" ]; do
|
|||||||
ldd "$1" | grep -v 'libguac' | awk '/=>/{print $(NF-1)}' \
|
ldd "$1" | grep -v 'libguac' | awk '/=>/{print $(NF-1)}' \
|
||||||
| while read LIBRARY; do
|
| while read LIBRARY; do
|
||||||
|
|
||||||
# In some cases, the library that's linked against is a hard link
|
# List the package providing that library, if any
|
||||||
# to the file that's managed by the package, which dpkg doesn't understand.
|
apk info -W "$LIBRARY" 2> /dev/null \
|
||||||
# Searching by */basename ensures the package will be found in these cases.
|
| grep 'is owned by' | grep -o '[^ ]*$' || true
|
||||||
LIBRARY_BASENAME=$(basename "$LIBRARY")
|
|
||||||
|
|
||||||
# Determine the Debian package which is associated with that
|
|
||||||
# library, if any
|
|
||||||
dpkg-query -S "*/$LIBRARY_BASENAME" || true
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Next binary
|
# Next binary
|
||||||
shift
|
shift
|
||||||
|
|
||||||
done | cut -f1 -d: | sort -u
|
# Strip the "-VERSION" suffix from each package name, listing each resulting
|
||||||
|
# package uniquely ("apk add" cannot handle package names that include the
|
||||||
|
# version number)
|
||||||
|
done | sed 's/\(.*\)-[0-9]\+\..*$/\1/' | sort -u
|
||||||
|
|
||||||
|
@ -381,10 +381,15 @@ int main(int argc, char* argv[]) {
|
|||||||
CRYPTO_set_locking_callback(guacd_openssl_locking_callback);
|
CRYPTO_set_locking_callback(guacd_openssl_locking_callback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Init SSL */
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
/* Init OpenSSL for OpenSSL Versions < 1.1.0 */
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
ssl_context = SSL_CTX_new(SSLv23_server_method());
|
ssl_context = SSL_CTX_new(SSLv23_server_method());
|
||||||
|
#else
|
||||||
|
/* Set up OpenSSL for OpenSSL Versions >= 1.1.0 */
|
||||||
|
ssl_context = SSL_CTX_new(TLS_server_method());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Load key */
|
/* Load key */
|
||||||
if (config->key_file != NULL) {
|
if (config->key_file != NULL) {
|
||||||
|
@ -213,7 +213,7 @@ int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec,
|
AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, const AVCodec* codec,
|
||||||
int bitrate, int width, int height, int gop_size, int qmax, int qmin,
|
int bitrate, int width, int height, int gop_size, int qmax, int qmin,
|
||||||
int pix_fmt, AVRational time_base) {
|
int pix_fmt, AVRational time_base) {
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int guacenc_open_avcodec(AVCodecContext *avcodec_context,
|
int guacenc_open_avcodec(AVCodecContext *avcodec_context,
|
||||||
AVCodec *codec, AVDictionary **options,
|
const AVCodec *codec, AVDictionary **options,
|
||||||
AVStream* stream) {
|
AVStream* stream) {
|
||||||
|
|
||||||
int ret = avcodec_open2(avcodec_context, codec, options);
|
int ret = avcodec_open2(avcodec_context, codec, options);
|
||||||
|
@ -128,7 +128,7 @@ int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame);
|
|||||||
* The pointer to the configured AVCodecContext.
|
* The pointer to the configured AVCodecContext.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec,
|
AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, const AVCodec* codec,
|
||||||
int bitrate, int width, int height, int gop_size, int qmax, int qmin,
|
int bitrate, int width, int height, int gop_size, int qmax, int qmin,
|
||||||
int pix_fmt, AVRational time_base);
|
int pix_fmt, AVRational time_base);
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ AVCodecContext* guacenc_build_avcodeccontext(AVStream* stream, AVCodec* codec,
|
|||||||
* Zero on success, a negative value on error.
|
* Zero on success, a negative value on error.
|
||||||
*/
|
*/
|
||||||
int guacenc_open_avcodec(AVCodecContext *avcodec_context,
|
int guacenc_open_avcodec(AVCodecContext *avcodec_context,
|
||||||
AVCodec *codec, AVDictionary **options,
|
const AVCodec *codec, AVDictionary **options,
|
||||||
AVStream* stream);
|
AVStream* stream);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name,
|
guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name,
|
||||||
int width, int height, int bitrate) {
|
int width, int height, int bitrate) {
|
||||||
|
|
||||||
AVOutputFormat *container_format;
|
const AVOutputFormat *container_format;
|
||||||
AVFormatContext *container_format_context;
|
AVFormatContext *container_format_context;
|
||||||
AVStream *video_stream;
|
AVStream *video_stream;
|
||||||
int ret;
|
int ret;
|
||||||
@ -63,7 +63,7 @@ guacenc_video* guacenc_video_alloc(const char* path, const char* codec_name,
|
|||||||
container_format = container_format_context->oformat;
|
container_format = container_format_context->oformat;
|
||||||
|
|
||||||
/* Pull codec based on name */
|
/* Pull codec based on name */
|
||||||
AVCodec* codec = avcodec_find_encoder_by_name(codec_name);
|
const AVCodec* codec = avcodec_find_encoder_by_name(codec_name);
|
||||||
if (codec == NULL) {
|
if (codec == NULL) {
|
||||||
guacenc_log(GUAC_LOG_ERROR, "Failed to locate codec \"%s\".",
|
guacenc_log(GUAC_LOG_ERROR, "Failed to locate codec \"%s\".",
|
||||||
codec_name);
|
codec_name);
|
||||||
|
@ -44,6 +44,7 @@ libguacinc_HEADERS = \
|
|||||||
guacamole/client-types.h \
|
guacamole/client-types.h \
|
||||||
guacamole/error.h \
|
guacamole/error.h \
|
||||||
guacamole/error-types.h \
|
guacamole/error-types.h \
|
||||||
|
guacamole/fips.h \
|
||||||
guacamole/hash.h \
|
guacamole/hash.h \
|
||||||
guacamole/layer.h \
|
guacamole/layer.h \
|
||||||
guacamole/layer-types.h \
|
guacamole/layer-types.h \
|
||||||
@ -93,6 +94,7 @@ libguac_la_SOURCES = \
|
|||||||
encode-jpeg.c \
|
encode-jpeg.c \
|
||||||
encode-png.c \
|
encode-png.c \
|
||||||
error.c \
|
error.c \
|
||||||
|
fips.c \
|
||||||
hash.c \
|
hash.c \
|
||||||
id.c \
|
id.c \
|
||||||
palette.c \
|
palette.c \
|
||||||
@ -137,7 +139,7 @@ libguac_la_CFLAGS = \
|
|||||||
-Werror -Wall -pedantic
|
-Werror -Wall -pedantic
|
||||||
|
|
||||||
libguac_la_LDFLAGS = \
|
libguac_la_LDFLAGS = \
|
||||||
-version-info 20:0:0 \
|
-version-info 21:0:0 \
|
||||||
-no-undefined \
|
-no-undefined \
|
||||||
@CAIRO_LIBS@ \
|
@CAIRO_LIBS@ \
|
||||||
@DL_LIBS@ \
|
@DL_LIBS@ \
|
||||||
|
@ -307,6 +307,10 @@ int guac_client_add_user(guac_client* client, guac_user* user, int argc, char**
|
|||||||
|
|
||||||
pthread_rwlock_unlock(&(client->__users_lock));
|
pthread_rwlock_unlock(&(client->__users_lock));
|
||||||
|
|
||||||
|
/* Notify owner of user joining connection. */
|
||||||
|
if (retval == 0 && !user->owner)
|
||||||
|
guac_client_owner_notify_join(client, user);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -333,6 +337,10 @@ void guac_client_remove_user(guac_client* client, guac_user* user) {
|
|||||||
|
|
||||||
pthread_rwlock_unlock(&(client->__users_lock));
|
pthread_rwlock_unlock(&(client->__users_lock));
|
||||||
|
|
||||||
|
/* Update owner of user having left the connection. */
|
||||||
|
if (!user->owner)
|
||||||
|
guac_client_owner_notify_leave(client, user);
|
||||||
|
|
||||||
/* Call handler, if defined */
|
/* Call handler, if defined */
|
||||||
if (user->leave_handler)
|
if (user->leave_handler)
|
||||||
user->leave_handler(user);
|
user->leave_handler(user);
|
||||||
@ -675,6 +683,36 @@ static void* __webp_support_callback(guac_user* user, void* data) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function which is invoked by guac_client_owner_supports_msg()
|
||||||
|
* to determine if the owner of a client supports the "msg" instruction,
|
||||||
|
* returning zero if the user does not support the instruction or non-zero if
|
||||||
|
* the user supports it.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The guac_user that will be checked for "msg" instruction support.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* Data provided to the callback. This value is never used within this
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A non-zero integer if the provided user who owns the connection supports
|
||||||
|
* the "msg" instruction, or zero if the user does not. The integer is cast
|
||||||
|
* as a void*.
|
||||||
|
*/
|
||||||
|
static void* guac_owner_supports_msg_callback(guac_user* user, void* data) {
|
||||||
|
|
||||||
|
return (void*) ((intptr_t) guac_user_supports_msg(user));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_client_owner_supports_msg(guac_client* client) {
|
||||||
|
|
||||||
|
return (int) ((intptr_t) guac_client_for_owner(client, guac_owner_supports_msg_callback, NULL));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback function which is invoked by guac_client_owner_supports_required()
|
* A callback function which is invoked by guac_client_owner_supports_required()
|
||||||
* to determine if the owner of a client supports the "required" instruction,
|
* to determine if the owner of a client supports the "required" instruction,
|
||||||
@ -705,6 +743,124 @@ int guac_client_owner_supports_required(guac_client* client) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function that is invokved by guac_client_owner_notify_join() to
|
||||||
|
* notify the owner of a connection that another user has joined the
|
||||||
|
* connection, returning zero if the message is sent successfully, or non-zero
|
||||||
|
* if an error occurs.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The user to send the notification to, which will be the owner of the
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* The data provided to the callback, which is the user that is joining the
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the message is sent successfully to the owner, otherwise
|
||||||
|
* non-zero, cast as a void*.
|
||||||
|
*/
|
||||||
|
static void* guac_client_owner_notify_join_callback(guac_user* user, void* data) {
|
||||||
|
|
||||||
|
const guac_user* joiner = (const guac_user *) data;
|
||||||
|
|
||||||
|
if (user == NULL)
|
||||||
|
return (void*) ((intptr_t) -1);
|
||||||
|
|
||||||
|
char* log_owner = "owner";
|
||||||
|
if (user->info.name != NULL)
|
||||||
|
log_owner = (char *) user->info.name;
|
||||||
|
|
||||||
|
char* log_joiner = "anonymous";
|
||||||
|
char* send_joiner = "";
|
||||||
|
if (joiner->info.name != NULL) {
|
||||||
|
log_joiner = (char *) joiner->info.name;
|
||||||
|
send_joiner = (char *) joiner->info.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
guac_user_log(user, GUAC_LOG_DEBUG, "Notifying owner \"%s\" of \"%s\" joining.",
|
||||||
|
log_owner, log_joiner);
|
||||||
|
|
||||||
|
/* Send user joined notification to owner. */
|
||||||
|
const char* args[] = { (const char*)joiner->user_id, (const char*)send_joiner, NULL };
|
||||||
|
return (void*) ((intptr_t) guac_protocol_send_msg(user->socket, GUAC_MESSAGE_USER_JOINED, args));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_client_owner_notify_join(guac_client* client, guac_user* joiner) {
|
||||||
|
|
||||||
|
/* Don't send msg instruction if client does not support it. */
|
||||||
|
if (!guac_client_owner_supports_msg(client)) {
|
||||||
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"Client does not support the \"msg\" instruction and "
|
||||||
|
"will not be notified of the user joining the connection.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) ((intptr_t) guac_client_for_owner(client, guac_client_owner_notify_join_callback, joiner));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function that is invokved by guac_client_owner_notify_leave() to
|
||||||
|
* notify the owner of a connection that another user has left the connection,
|
||||||
|
* returning zero if the message is sent successfully, or non-zero
|
||||||
|
* if an error occurs.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The user to send the notification to, which will be the owner of the
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* The data provided to the callback, which is the user that is leaving the
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the message is sent successfully to the owner, otherwise
|
||||||
|
* non-zero, cast as a void*.
|
||||||
|
*/
|
||||||
|
static void* guac_client_owner_notify_leave_callback(guac_user* user, void* data) {
|
||||||
|
|
||||||
|
const guac_user* quitter = (const guac_user *) data;
|
||||||
|
|
||||||
|
if (user == NULL)
|
||||||
|
return (void*) ((intptr_t) -1);
|
||||||
|
|
||||||
|
char* log_owner = "owner";
|
||||||
|
if (user->info.name != NULL)
|
||||||
|
log_owner = (char *) user->info.name;
|
||||||
|
|
||||||
|
char* log_quitter = "anonymous";
|
||||||
|
char* send_quitter = "";
|
||||||
|
if (quitter->info.name != NULL) {
|
||||||
|
log_quitter = (char *) quitter->info.name;
|
||||||
|
send_quitter = (char *) quitter->info.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
guac_user_log(user, GUAC_LOG_DEBUG, "Notifying owner \"%s\" of \"%s\" leaving.",
|
||||||
|
log_owner, log_quitter);
|
||||||
|
|
||||||
|
/* Send user left notification to owner. */
|
||||||
|
const char* args[] = { (const char*)quitter->user_id, (const char*)send_quitter, NULL };
|
||||||
|
return (void*) ((intptr_t) guac_protocol_send_msg(user->socket, GUAC_MESSAGE_USER_LEFT, args));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_client_owner_notify_leave(guac_client* client, guac_user* quitter) {
|
||||||
|
|
||||||
|
/* Don't send msg instruction if client does not support it. */
|
||||||
|
if (!guac_client_owner_supports_msg(client)) {
|
||||||
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"Client does not support the \"msg\" instruction and "
|
||||||
|
"will not be notified of the user leaving the connection.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) ((intptr_t) guac_client_for_owner(client, guac_client_owner_notify_leave_callback, quitter));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_client_supports_webp(guac_client* client) {
|
int guac_client_supports_webp(guac_client* client) {
|
||||||
|
|
||||||
#ifdef ENABLE_WEBP
|
#ifdef ENABLE_WEBP
|
||||||
|
51
src/libguac/fips.c
Normal file
51
src/libguac/fips.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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 "guacamole/fips.h"
|
||||||
|
|
||||||
|
/* If OpenSSL is available, include header for version numbers */
|
||||||
|
#ifdef ENABLE_SSL
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
|
||||||
|
/* OpenSSL versions prior to 0.9.7e did not have FIPS support */
|
||||||
|
#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x00090705f)
|
||||||
|
#define GUAC_FIPS_ENABLED 0
|
||||||
|
|
||||||
|
/* OpenSSL 3+ uses EVP_default_properties_is_fips_enabled() */
|
||||||
|
#elif defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#define GUAC_FIPS_ENABLED EVP_default_properties_is_fips_enabled(NULL)
|
||||||
|
|
||||||
|
/* For OpenSSL versions between 0.9.7e and 3.0, use FIPS_mode() */
|
||||||
|
#else
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#define GUAC_FIPS_ENABLED FIPS_mode()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FIPS support does not exist if OpenSSL is not available. */
|
||||||
|
#else
|
||||||
|
#define GUAC_FIPS_ENABLED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int guac_fips_enabled() {
|
||||||
|
|
||||||
|
return GUAC_FIPS_ENABLED;
|
||||||
|
|
||||||
|
}
|
@ -737,6 +737,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 "msg"
|
||||||
|
* 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 "msg" instruction.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if the owner of the given client supports the "msg"
|
||||||
|
* instruction, zero otherwise.
|
||||||
|
*/
|
||||||
|
int guac_client_owner_supports_msg(guac_client* client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the owner of the given client supports the "required"
|
* Returns whether the owner of the given client supports the "required"
|
||||||
* instruction, returning non-zero if the client owner does support the
|
* instruction, returning non-zero if the client owner does support the
|
||||||
@ -752,6 +767,42 @@ void guac_client_stream_webp(guac_client* client, guac_socket* socket,
|
|||||||
*/
|
*/
|
||||||
int guac_client_owner_supports_required(guac_client* client);
|
int guac_client_owner_supports_required(guac_client* client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the owner of the given client that a user has joined the connection,
|
||||||
|
* and returns zero if the message was sent successfully, or non-zero if the
|
||||||
|
* notification failed.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* The Guacamole Client whose owner should be notified of a user joining
|
||||||
|
* the connection.
|
||||||
|
*
|
||||||
|
* @param joiner
|
||||||
|
* The Guacamole User who joined the connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the notification to the owner was sent successfully, or non-zero
|
||||||
|
* if an error occurred.
|
||||||
|
*/
|
||||||
|
int guac_client_owner_notify_join(guac_client* client, guac_user* joiner);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the owner of the given client that a user has left the connection,
|
||||||
|
* and returns zero if the message was sent successfully, or non-zero if the
|
||||||
|
* notification failed.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* The Guacamole Client whose owner should be notified of a user leaving
|
||||||
|
* the connection.
|
||||||
|
*
|
||||||
|
* @param quitter
|
||||||
|
* The Guacamole User who left the connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the notification to the owner was sent successfully, or non-zero
|
||||||
|
* if an error occurred.
|
||||||
|
*/
|
||||||
|
int guac_client_owner_notify_leave(guac_client* client, guac_user* quitter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
33
src/libguac/guacamole/fips.h
Normal file
33
src/libguac/guacamole/fips.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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_FIPS_H
|
||||||
|
#define GUAC_FIPS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a non-zero value if FIPS mode is enabled, or zero if FIPS mode
|
||||||
|
* is not enabled.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A non-zero value if FIPS mode is enabled, or zero if FIPS mode is
|
||||||
|
* not enabled.
|
||||||
|
*/
|
||||||
|
int guac_fips_enabled();
|
||||||
|
|
||||||
|
#endif
|
@ -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_3_0"
|
#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_5_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
|
||||||
|
@ -306,9 +306,40 @@ typedef enum guac_protocol_version {
|
|||||||
* allowing connections in guacd to request information from the client and
|
* allowing connections in guacd to request information from the client and
|
||||||
* await a response.
|
* await a response.
|
||||||
*/
|
*/
|
||||||
GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300
|
GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol version 1.5.0, which supports the "msg" instruction, allowing
|
||||||
|
* messages to be sent to the client, and adds support for the "name"
|
||||||
|
* handshake instruction.
|
||||||
|
*/
|
||||||
|
GUAC_PROTOCOL_VERSION_1_5_0 = 0x010500
|
||||||
|
|
||||||
} guac_protocol_version;
|
} guac_protocol_version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type that represents codes for human-readable messages sent by the "msg"
|
||||||
|
* instruction to the Client, that will be displayed in the client's browser.
|
||||||
|
* The codes will be interpreted by the client into translatable messages, and
|
||||||
|
* make take arguments, as noted below.
|
||||||
|
*/
|
||||||
|
typedef enum guac_message_type {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that notifies the owner of a connection that another user has
|
||||||
|
* joined their connection. There should be a single argument provided, the
|
||||||
|
* name of the user who has joined.
|
||||||
|
*/
|
||||||
|
GUAC_MESSAGE_USER_JOINED = 0x0001,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that notifies the owner of a connection that another user has
|
||||||
|
* left their connection. There should be a single argument provided, the
|
||||||
|
* name of the user who has left.
|
||||||
|
*/
|
||||||
|
GUAC_MESSAGE_USER_LEFT = 0x0002
|
||||||
|
|
||||||
|
} guac_message_type;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -171,6 +171,27 @@ int guac_protocol_send_log(guac_socket* socket, const char* format, ...);
|
|||||||
int vguac_protocol_send_log(guac_socket* socket, const char* format,
|
int vguac_protocol_send_log(guac_socket* socket, const char* format,
|
||||||
va_list args);
|
va_list args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the given string over the socket to be displayed on the client. Returns
|
||||||
|
* zero if the message was sent successfully or non-zero if an error occurs.
|
||||||
|
*
|
||||||
|
* @param socket
|
||||||
|
* The guac_socket connection to send the message to.
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* The message code to send to the client.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* A null-terminated array of strings that will be provided to the client
|
||||||
|
* as part of the message, that the client may then place in the message,
|
||||||
|
* or null if the message requires no arguments.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the message is sent successfully; otherwise non-zero.
|
||||||
|
*/
|
||||||
|
int guac_protocol_send_msg(guac_socket* socket, guac_message_type msg,
|
||||||
|
const char** args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a mouse instruction over the given guac_socket connection.
|
* Sends a mouse instruction over the given guac_socket connection.
|
||||||
*
|
*
|
||||||
|
@ -102,6 +102,14 @@ struct guac_user_info {
|
|||||||
*/
|
*/
|
||||||
guac_protocol_version protocol_version;
|
guac_protocol_version protocol_version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The human-readable name of the Guacamole user, supplied by the client
|
||||||
|
* during the handshake. This is an arbitrary value, with no requirements or
|
||||||
|
* constraints, including that it need not uniquely identify the user.
|
||||||
|
* If the client does not provide a name then this will be NULL.
|
||||||
|
*/
|
||||||
|
const char* name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct guac_user {
|
struct guac_user {
|
||||||
@ -850,6 +858,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 "msg" instruction.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The Guacamole user to check for support of the "msg" instruction.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if the user supports the "msg" instruction, otherwise zero.
|
||||||
|
*/
|
||||||
|
int guac_user_supports_msg(guac_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given user supports the "required" instruction.
|
* Returns whether the given user supports the "required" instruction.
|
||||||
*
|
*
|
||||||
|
@ -65,6 +65,7 @@ guac_protocol_version_mapping guac_protocol_version_table[] = {
|
|||||||
{ GUAC_PROTOCOL_VERSION_1_0_0, "VERSION_1_0_0" },
|
{ GUAC_PROTOCOL_VERSION_1_0_0, "VERSION_1_0_0" },
|
||||||
{ GUAC_PROTOCOL_VERSION_1_1_0, "VERSION_1_1_0" },
|
{ GUAC_PROTOCOL_VERSION_1_1_0, "VERSION_1_1_0" },
|
||||||
{ GUAC_PROTOCOL_VERSION_1_3_0, "VERSION_1_3_0" },
|
{ GUAC_PROTOCOL_VERSION_1_3_0, "VERSION_1_3_0" },
|
||||||
|
{ GUAC_PROTOCOL_VERSION_1_5_0, "VERSION_1_5_0" },
|
||||||
{ GUAC_PROTOCOL_VERSION_UNKNOWN, NULL }
|
{ GUAC_PROTOCOL_VERSION_UNKNOWN, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -658,6 +659,23 @@ int guac_protocol_send_log(guac_socket* socket, const char* format, ...) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int guac_protocol_send_msg(guac_socket* socket, guac_message_type msg,
|
||||||
|
const char** args) {
|
||||||
|
|
||||||
|
int ret_val;
|
||||||
|
|
||||||
|
guac_socket_instruction_begin(socket);
|
||||||
|
ret_val =
|
||||||
|
guac_socket_write_string(socket, "3.msg,")
|
||||||
|
|| __guac_socket_write_length_int(socket, msg)
|
||||||
|
|| guac_socket_write_array(socket, args)
|
||||||
|
|| guac_socket_write_string(socket, ";");
|
||||||
|
|
||||||
|
guac_socket_instruction_end(socket);
|
||||||
|
return ret_val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream,
|
int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream,
|
||||||
const char* mimetype, const char* name) {
|
const char* mimetype, const char* name) {
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@
|
|||||||
*/
|
*/
|
||||||
void test_guac_protocol__version_to_string() {
|
void test_guac_protocol__version_to_string() {
|
||||||
|
|
||||||
guac_protocol_version version_a = GUAC_PROTOCOL_VERSION_1_3_0;
|
guac_protocol_version version_a = GUAC_PROTOCOL_VERSION_1_5_0;
|
||||||
guac_protocol_version version_b = GUAC_PROTOCOL_VERSION_1_0_0;
|
guac_protocol_version version_b = GUAC_PROTOCOL_VERSION_1_0_0;
|
||||||
guac_protocol_version version_c = GUAC_PROTOCOL_VERSION_UNKNOWN;
|
guac_protocol_version version_c = GUAC_PROTOCOL_VERSION_UNKNOWN;
|
||||||
|
|
||||||
CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_a), "VERSION_1_3_0");
|
CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_a), "VERSION_1_5_0");
|
||||||
CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_b), "VERSION_1_0_0");
|
CU_ASSERT_STRING_EQUAL(guac_protocol_version_to_string(version_b), "VERSION_1_0_0");
|
||||||
CU_ASSERT_PTR_NULL(guac_protocol_version_to_string(version_c));
|
CU_ASSERT_PTR_NULL(guac_protocol_version_to_string(version_c));
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ __guac_instruction_handler_mapping __guac_handshake_handler_map[] = {
|
|||||||
{"video", __guac_handshake_video_handler},
|
{"video", __guac_handshake_video_handler},
|
||||||
{"image", __guac_handshake_image_handler},
|
{"image", __guac_handshake_image_handler},
|
||||||
{"timezone", __guac_handshake_timezone_handler},
|
{"timezone", __guac_handshake_timezone_handler},
|
||||||
|
{"name", __guac_handshake_name_handler},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -684,6 +685,23 @@ int __guac_handshake_image_handler(guac_user* user, int argc, char** argv) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __guac_handshake_name_handler(guac_user* user, int argc, char** argv) {
|
||||||
|
|
||||||
|
/* Free any past value for the user's name */
|
||||||
|
free((char *) user->info.name);
|
||||||
|
|
||||||
|
/* If a value is provided for the name, copy it into guac_user. */
|
||||||
|
if (argc > 0 && strcmp(argv[0], ""))
|
||||||
|
user->info.name = (const char*) strdup(argv[0]);
|
||||||
|
|
||||||
|
/* No or empty value was provided, so make sure this is NULLed out. */
|
||||||
|
else
|
||||||
|
user->info.name = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int __guac_handshake_timezone_handler(guac_user* user, int argc, char** argv) {
|
int __guac_handshake_timezone_handler(guac_user* user, int argc, char** argv) {
|
||||||
|
|
||||||
/* Free any past value */
|
/* Free any past value */
|
||||||
|
@ -218,6 +218,13 @@ __guac_instruction_handler __guac_handshake_video_handler;
|
|||||||
*/
|
*/
|
||||||
__guac_instruction_handler __guac_handshake_image_handler;
|
__guac_instruction_handler __guac_handshake_image_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal handler function that is called when the name instruction is
|
||||||
|
* received during the handshake process, specifying the name of the Guacamole
|
||||||
|
* user establishing the connection.
|
||||||
|
*/
|
||||||
|
__guac_instruction_handler __guac_handshake_name_handler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal handler function that is called when the timezone instruction is
|
* Internal handler function that is called when the timezone instruction is
|
||||||
* received during the handshake process, specifying the timezone of the
|
* received during the handshake process, specifying the timezone of the
|
||||||
|
@ -296,6 +296,7 @@ int guac_user_handle_connection(guac_user* user, int usec_timeout) {
|
|||||||
user->info.audio_mimetypes = NULL;
|
user->info.audio_mimetypes = NULL;
|
||||||
user->info.image_mimetypes = NULL;
|
user->info.image_mimetypes = NULL;
|
||||||
user->info.video_mimetypes = NULL;
|
user->info.video_mimetypes = NULL;
|
||||||
|
user->info.name = NULL;
|
||||||
user->info.timezone = NULL;
|
user->info.timezone = NULL;
|
||||||
|
|
||||||
/* Count number of arguments. */
|
/* Count number of arguments. */
|
||||||
@ -370,7 +371,8 @@ int guac_user_handle_connection(guac_user* user, int usec_timeout) {
|
|||||||
guac_free_mimetypes((char **) user->info.image_mimetypes);
|
guac_free_mimetypes((char **) user->info.image_mimetypes);
|
||||||
guac_free_mimetypes((char **) user->info.video_mimetypes);
|
guac_free_mimetypes((char **) user->info.video_mimetypes);
|
||||||
|
|
||||||
/* Free timezone info. */
|
/* Free name and timezone info. */
|
||||||
|
free((char *) user->info.name);
|
||||||
free((char *) user->info.timezone);
|
free((char *) user->info.timezone);
|
||||||
|
|
||||||
guac_parser_free(parser);
|
guac_parser_free(parser);
|
||||||
|
@ -316,6 +316,15 @@ void guac_user_stream_webp(guac_user* user, guac_socket* socket,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int guac_user_supports_msg(guac_user* user) {
|
||||||
|
|
||||||
|
if (user == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (user->info.protocol_version >= GUAC_PROTOCOL_VERSION_1_5_0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_user_supports_required(guac_user* user) {
|
int guac_user_supports_required(guac_user* user) {
|
||||||
|
|
||||||
if (user == NULL)
|
if (user == NULL)
|
||||||
|
@ -230,6 +230,7 @@ BUILT_SOURCES = \
|
|||||||
rdp_keymaps = \
|
rdp_keymaps = \
|
||||||
$(srcdir)/keymaps/base.keymap \
|
$(srcdir)/keymaps/base.keymap \
|
||||||
$(srcdir)/keymaps/failsafe.keymap \
|
$(srcdir)/keymaps/failsafe.keymap \
|
||||||
|
$(srcdir)/keymaps/cs-cz-qwertz.keymap \
|
||||||
$(srcdir)/keymaps/de_de_qwertz.keymap \
|
$(srcdir)/keymaps/de_de_qwertz.keymap \
|
||||||
$(srcdir)/keymaps/de_ch_qwertz.keymap \
|
$(srcdir)/keymaps/de_ch_qwertz.keymap \
|
||||||
$(srcdir)/keymaps/en_gb_qwerty.keymap \
|
$(srcdir)/keymaps/en_gb_qwerty.keymap \
|
||||||
|
79
src/protocols/rdp/keymaps/cs-cz-qwertz.keymap
Normal file
79
src/protocols/rdp/keymaps/cs-cz-qwertz.keymap
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
parent "base"
|
||||||
|
name "cs-cz-qwertz"
|
||||||
|
freerdp "KBD_CZECH"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Basic keys
|
||||||
|
#
|
||||||
|
|
||||||
|
map -caps -altgr -shift 0x29 0x02..0x0D ~ ";+ěščřžýáíé=´"
|
||||||
|
map -caps -altgr -shift 0x10..0x1B ~ "qwertzuıopú)"
|
||||||
|
map -caps -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjklů§¨"
|
||||||
|
map -caps -altgr -shift 0x2C..0x35 ~ "yxcvbnm,.-"
|
||||||
|
|
||||||
|
map -caps -altgr +shift 0x29 0x02..0x0D ~ "°1234567890%ˇ"
|
||||||
|
map -caps -altgr +shift 0x10..0x1B ~ "QWERTZUIOP/("
|
||||||
|
map -caps -altgr +shift 0x1E..0x28 0x2B ~ "ASDFGHJKL"!'"
|
||||||
|
map -caps -altgr +shift 0x2C..0x35 ~ "YXCVBNM?:_"
|
||||||
|
|
||||||
|
map +caps -altgr -shift 0x29 0x02..0x0D ~ ";+ĚŠČŘŽÝÁÍÉ=´"
|
||||||
|
map +caps -altgr -shift 0x10..0x1B ~ "QWERTZUIOPÚ)"
|
||||||
|
map +caps -altgr -shift 0x1E..0x28 0x2B ~ "ASDFGHJKL٧¨"
|
||||||
|
map +caps -altgr -shift 0x2C..0x35 ~ "YXCVBNM,.-"
|
||||||
|
|
||||||
|
map +caps -altgr +shift 0x29 0x02..0x0D ~ "°1234567890%ˇ"
|
||||||
|
map +caps -altgr +shift 0x10..0x1B ~ "qwertzuiop/("
|
||||||
|
map +caps -altgr +shift 0x1E..0x28 0x2B ~ "asdfghjkl"!'"
|
||||||
|
map +caps -altgr +shift 0x2C..0x35 ~ "yxcvbnm?:_"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Keys requiring AltGr
|
||||||
|
#
|
||||||
|
|
||||||
|
map +altgr -shift 0x02 ~ "~"
|
||||||
|
|
||||||
|
map +altgr -shift 0x10 ~ "\"
|
||||||
|
map +altgr -shift 0x11 ~ "|"
|
||||||
|
map +altgr -shift 0x12 ~ "€"
|
||||||
|
map +altgr -shift 0x1A ~ "÷"
|
||||||
|
map +altgr -shift 0x1B ~ "×"
|
||||||
|
|
||||||
|
map +altgr -shift 0x1F ~ "đ"
|
||||||
|
map +altgr -shift 0x20 ~ "Đ"
|
||||||
|
map +altgr -shift 0x21 ~ "["
|
||||||
|
map +altgr -shift 0x22 ~ "]"
|
||||||
|
map +altgr -shift 0x25 ~ "ł"
|
||||||
|
map +altgr -shift 0x26 ~ "Ł"
|
||||||
|
map +altgr -shift 0x27 ~ "$"
|
||||||
|
map +altgr -shift 0x28 ~ "ß"
|
||||||
|
map +altgr -shift 0x2B ~ "¤"
|
||||||
|
|
||||||
|
map +altgr -shift 0x2D ~ "#"
|
||||||
|
map +altgr -shift 0x2E ~ "&"
|
||||||
|
map +altgr -shift 0x2F ~ "@"
|
||||||
|
map +altgr -shift 0x30 ~ "{"
|
||||||
|
map +altgr -shift 0x31 ~ "}"
|
||||||
|
map +altgr -shift 0x33 ~ "<"
|
||||||
|
map +altgr -shift 0x34 ~ ">"
|
||||||
|
map +altgr -shift 0x35 ~ "*"
|
||||||
|
|
||||||
|
# END
|
@ -28,6 +28,7 @@
|
|||||||
#include <freerdp/settings.h>
|
#include <freerdp/settings.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
|
#include <guacamole/fips.h>
|
||||||
#include <guacamole/string.h>
|
#include <guacamole/string.h>
|
||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
#include <guacamole/wol-constants.h>
|
#include <guacamole/wol-constants.h>
|
||||||
@ -39,6 +40,16 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A warning to log when NLA mode is selected while FIPS mode is active on the
|
||||||
|
* guacd server.
|
||||||
|
*/
|
||||||
|
const char fips_nla_mode_warning[] = (
|
||||||
|
"NLA security mode was selected, but is known to be currently incompatible "
|
||||||
|
"with FIPS mode (see FreeRDP/FreeRDP#3412). Security negotiation with the "
|
||||||
|
"RDP server may fail unless TLS security mode is selected instead."
|
||||||
|
);
|
||||||
|
|
||||||
/* Client plugin arguments */
|
/* Client plugin arguments */
|
||||||
const char* GUAC_RDP_CLIENT_ARGS[] = {
|
const char* GUAC_RDP_CLIENT_ARGS[] = {
|
||||||
"hostname",
|
"hostname",
|
||||||
@ -706,12 +717,27 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user,
|
|||||||
if (strcmp(argv[IDX_SECURITY], "nla") == 0) {
|
if (strcmp(argv[IDX_SECURITY], "nla") == 0) {
|
||||||
guac_user_log(user, GUAC_LOG_INFO, "Security mode: NLA");
|
guac_user_log(user, GUAC_LOG_INFO, "Security mode: NLA");
|
||||||
settings->security_mode = GUAC_SECURITY_NLA;
|
settings->security_mode = GUAC_SECURITY_NLA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NLA is known not to work with FIPS; allow the mode selection but
|
||||||
|
* warn that it will not work.
|
||||||
|
*/
|
||||||
|
if (guac_fips_enabled())
|
||||||
|
guac_user_log(user, GUAC_LOG_WARNING, fips_nla_mode_warning);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extended NLA security */
|
/* Extended NLA security */
|
||||||
else if (strcmp(argv[IDX_SECURITY], "nla-ext") == 0) {
|
else if (strcmp(argv[IDX_SECURITY], "nla-ext") == 0) {
|
||||||
guac_user_log(user, GUAC_LOG_INFO, "Security mode: Extended NLA");
|
guac_user_log(user, GUAC_LOG_INFO, "Security mode: Extended NLA");
|
||||||
settings->security_mode = GUAC_SECURITY_EXTENDED_NLA;
|
settings->security_mode = GUAC_SECURITY_EXTENDED_NLA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NLA is known not to work with FIPS; allow the mode selection but
|
||||||
|
* warn that it will not work.
|
||||||
|
*/
|
||||||
|
if (guac_fips_enabled())
|
||||||
|
guac_user_log(user, GUAC_LOG_WARNING, fips_nla_mode_warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TLS security */
|
/* TLS security */
|
||||||
@ -1529,7 +1555,21 @@ void guac_rdp_push_settings(guac_client* client,
|
|||||||
case GUAC_SECURITY_ANY:
|
case GUAC_SECURITY_ANY:
|
||||||
rdp_settings->RdpSecurity = TRUE;
|
rdp_settings->RdpSecurity = TRUE;
|
||||||
rdp_settings->TlsSecurity = TRUE;
|
rdp_settings->TlsSecurity = TRUE;
|
||||||
rdp_settings->NlaSecurity = guac_settings->username && guac_settings->password;
|
|
||||||
|
/* Explicitly disable NLA if FIPS mode is enabled - it won't work */
|
||||||
|
if (guac_fips_enabled()) {
|
||||||
|
|
||||||
|
guac_client_log(client, GUAC_LOG_INFO,
|
||||||
|
"FIPS mode is enabled. Excluding NLA security mode from security negotiation "
|
||||||
|
"(see: https://github.com/FreeRDP/FreeRDP/issues/3412).");
|
||||||
|
rdp_settings->NlaSecurity = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NLA mode is allowed if FIPS is not enabled */
|
||||||
|
else
|
||||||
|
rdp_settings->NlaSecurity = TRUE;
|
||||||
|
|
||||||
rdp_settings->ExtSecurity = FALSE;
|
rdp_settings->ExtSecurity = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ libguac_terminal_la_LIBADD = \
|
|||||||
@LIBGUAC_LTLIB@
|
@LIBGUAC_LTLIB@
|
||||||
|
|
||||||
libguac_terminal_la_LDFLAGS = \
|
libguac_terminal_la_LDFLAGS = \
|
||||||
|
-version-info 0:0:0 \
|
||||||
|
-no-undefined \
|
||||||
@CAIRO_LIBS@ \
|
@CAIRO_LIBS@ \
|
||||||
@MATH_LIBS@ \
|
@MATH_LIBS@ \
|
||||||
@PANGO_LIBS@ \
|
@PANGO_LIBS@ \
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "common/clipboard.h"
|
#include "common/clipboard.h"
|
||||||
#include "common/cursor.h"
|
#include "common/cursor.h"
|
||||||
|
#include "common/iconv.h"
|
||||||
#include "terminal/buffer.h"
|
#include "terminal/buffer.h"
|
||||||
#include "terminal/color-scheme.h"
|
#include "terminal/color-scheme.h"
|
||||||
#include "terminal/common.h"
|
#include "terminal/common.h"
|
||||||
@ -936,14 +937,13 @@ void guac_terminal_commit_cursor(guac_terminal* term) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int guac_terminal_write(guac_terminal* term, const char* c, int size) {
|
int guac_terminal_write(guac_terminal* term, const char* buffer, int length) {
|
||||||
|
|
||||||
guac_terminal_lock(term);
|
guac_terminal_lock(term);
|
||||||
while (size > 0) {
|
for (int written = 0; written < length; written++) {
|
||||||
|
|
||||||
/* Read and advance to next character */
|
/* Read and advance to next character */
|
||||||
char current = *(c++);
|
char current = *(buffer++);
|
||||||
size--;
|
|
||||||
|
|
||||||
/* Write character to typescript, if any */
|
/* Write character to typescript, if any */
|
||||||
if (term->typescript != NULL)
|
if (term->typescript != NULL)
|
||||||
@ -956,7 +956,7 @@ int guac_terminal_write(guac_terminal* term, const char* c, int size) {
|
|||||||
guac_terminal_unlock(term);
|
guac_terminal_unlock(term);
|
||||||
|
|
||||||
guac_terminal_notify(term);
|
guac_terminal_notify(term);
|
||||||
return 0;
|
return length;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2165,7 +2165,16 @@ void guac_terminal_clipboard_reset(guac_terminal* terminal,
|
|||||||
|
|
||||||
void guac_terminal_clipboard_append(guac_terminal* terminal,
|
void guac_terminal_clipboard_append(guac_terminal* terminal,
|
||||||
const char* data, int length) {
|
const char* data, int length) {
|
||||||
guac_common_clipboard_append(terminal->clipboard, data, length);
|
|
||||||
|
/* Allocate and clear space for the converted data */
|
||||||
|
char output_data[GUAC_COMMON_CLIPBOARD_MAX_LENGTH];
|
||||||
|
char* output = output_data;
|
||||||
|
|
||||||
|
/* Convert clipboard contents */
|
||||||
|
guac_iconv(GUAC_READ_UTF8_NORMALIZED, &data, length,
|
||||||
|
GUAC_WRITE_UTF8, &output, GUAC_COMMON_CLIPBOARD_MAX_LENGTH);
|
||||||
|
|
||||||
|
guac_common_clipboard_append(terminal->clipboard, output_data, output - output_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_terminal_remove_user(guac_terminal* terminal, guac_user* user) {
|
void guac_terminal_remove_user(guac_terminal* terminal, guac_user* user) {
|
||||||
|
@ -29,6 +29,22 @@
|
|||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "typescript.h"
|
#include "typescript.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for characters printed to the terminal. When a character is printed,
|
||||||
|
* the current char handler for the terminal is called and given that
|
||||||
|
* character.
|
||||||
|
*
|
||||||
|
* @param term
|
||||||
|
* The terminal receiving the character.
|
||||||
|
*
|
||||||
|
* @param c
|
||||||
|
* The received character.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the character was handled successfully, non-zero otherwise.
|
||||||
|
*/
|
||||||
|
typedef int guac_terminal_char_handler(guac_terminal* term, unsigned char c);
|
||||||
|
|
||||||
struct guac_terminal {
|
struct guac_terminal {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,19 +141,35 @@ typedef enum guac_terminal_cursor_type {
|
|||||||
} guac_terminal_cursor_type;
|
} guac_terminal_cursor_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for characters printed to the terminal. When a character is printed,
|
* Handler that is invoked whenever the necessary terminal codes are sent to
|
||||||
* the current char handler for the terminal is called and given that
|
* to the given terminal to change the path for future file uploads.
|
||||||
* character.
|
*
|
||||||
*/
|
* @param client
|
||||||
typedef int guac_terminal_char_handler(guac_terminal* term, unsigned char c);
|
* The guac_client associated with the terminal receiving the upload path
|
||||||
|
* change terminal code.
|
||||||
/**
|
*
|
||||||
* Handler for setting the destination path for file uploads.
|
* @param path
|
||||||
|
* The requested path.
|
||||||
*/
|
*/
|
||||||
typedef void guac_terminal_upload_path_handler(guac_client* client, char* path);
|
typedef void guac_terminal_upload_path_handler(guac_client* client, char* path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for creating an outbound file download stream for a specified file.
|
* Handler that is invoked whenever the necessary terminal codes are sent to
|
||||||
|
* initiate a download of a given remote file.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* The guac_client associated with the terminal receiving the file download
|
||||||
|
* terminal code.
|
||||||
|
*
|
||||||
|
* @param filename
|
||||||
|
* The name of the requested file. This may be a relative or absolute path,
|
||||||
|
* and it is up to the implementation to define how this value is
|
||||||
|
* interpreted.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The file stream created for the file download, already configured to
|
||||||
|
* properly handle "ack" responses, etc. from the client, or NULL if the
|
||||||
|
* stream could not be created.
|
||||||
*/
|
*/
|
||||||
typedef guac_stream* guac_terminal_file_download_handler(guac_client* client, char* filename);
|
typedef guac_stream* guac_terminal_file_download_handler(guac_client* client, char* filename);
|
||||||
|
|
||||||
@ -276,11 +292,16 @@ guac_terminal_options* guac_terminal_options_create(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all resources associated with the given terminal.
|
* Frees all resources associated with the given terminal.
|
||||||
|
*
|
||||||
|
* @param term
|
||||||
|
* The terminal to free.
|
||||||
*/
|
*/
|
||||||
void guac_terminal_free(guac_terminal* term);
|
void guac_terminal_free(guac_terminal* term);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the upload path handler for the given terminal.
|
* Sets the upload path handler for the given terminal. The upload path handler
|
||||||
|
* is invoked whenever the terminal codes requesting an upload path change are
|
||||||
|
* sent.
|
||||||
*
|
*
|
||||||
* @param terminal
|
* @param terminal
|
||||||
* The terminal to set the upload path handler for.
|
* The terminal to set the upload path handler for.
|
||||||
@ -293,12 +314,14 @@ void guac_terminal_set_upload_path_handler(guac_terminal* terminal,
|
|||||||
guac_terminal_upload_path_handler* upload_path_handler);
|
guac_terminal_upload_path_handler* upload_path_handler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the file download handler for the given terminal.
|
* Sets the file download handler for the given terminal. The file download
|
||||||
|
* handler is invoked whenever the terminal codes requesting download of a
|
||||||
|
* given remote file are sent.
|
||||||
*
|
*
|
||||||
* @param terminal
|
* @param terminal
|
||||||
* The terminal to set the file download handler for.
|
* The terminal to set the file download handler for.
|
||||||
*
|
*
|
||||||
* @param upload_path_handler
|
* @param file_download_handler
|
||||||
* The handler to be called whenever the necessary terminal codes are sent to
|
* The handler to be called whenever the necessary terminal codes are sent to
|
||||||
* the given terminal to initiate a download of a given remote file.
|
* the given terminal to initiate a download of a given remote file.
|
||||||
*/
|
*/
|
||||||
@ -308,6 +331,13 @@ void guac_terminal_set_file_download_handler(guac_terminal* terminal,
|
|||||||
/**
|
/**
|
||||||
* Renders a single frame of terminal data. If data is not yet available,
|
* Renders a single frame of terminal data. If data is not yet available,
|
||||||
* this function will block until data is written.
|
* this function will block until data is written.
|
||||||
|
*
|
||||||
|
* @param terminal
|
||||||
|
* The terminal that should be rendered.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the frame was rendered successfully, non-zero if an error
|
||||||
|
* occurred.
|
||||||
*/
|
*/
|
||||||
int guac_terminal_render_frame(guac_terminal* terminal);
|
int guac_terminal_render_frame(guac_terminal* terminal);
|
||||||
|
|
||||||
@ -316,6 +346,19 @@ int guac_terminal_render_frame(guac_terminal* terminal);
|
|||||||
* supplied by calls to guac_terminal_send_key(),
|
* supplied by calls to guac_terminal_send_key(),
|
||||||
* guac_terminal_send_mouse(), and guac_terminal_send_stream(). If input is not
|
* guac_terminal_send_mouse(), and guac_terminal_send_stream(). If input is not
|
||||||
* yet available, this function will block.
|
* yet available, this function will block.
|
||||||
|
*
|
||||||
|
* @param terminal
|
||||||
|
* The terminal to read from.
|
||||||
|
*
|
||||||
|
* @param c
|
||||||
|
* The buffer that should receive the bytes read.
|
||||||
|
*
|
||||||
|
* @param size
|
||||||
|
* The number of bytes available within the buffer.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of bytes read into the buffer, zero if end-of-file is reached
|
||||||
|
* (STDIN has been closed), or a negative value if an error occurs.
|
||||||
*/
|
*/
|
||||||
int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size);
|
int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size);
|
||||||
|
|
||||||
@ -377,8 +420,23 @@ char* guac_terminal_prompt(guac_terminal* terminal, const char* title,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the given format string and arguments to this terminal's STDOUT in
|
* Writes the given format string and arguments to this terminal's STDOUT in
|
||||||
* the same manner as printf(). This function may block until space is
|
* the same manner as printf(). The entire populated format string will always
|
||||||
|
* be written unless an error occurs. This function may block until space is
|
||||||
* freed in the output buffer by guac_terminal_render_frame().
|
* freed in the output buffer by guac_terminal_render_frame().
|
||||||
|
*
|
||||||
|
* @param terminal
|
||||||
|
* The terminal to write to.
|
||||||
|
*
|
||||||
|
* @param format
|
||||||
|
* A printf-style format string describing the data to be written to
|
||||||
|
* STDOUT.
|
||||||
|
*
|
||||||
|
* @param ...
|
||||||
|
* Any arguments to use when filling the format string.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of bytes written to STDOUT, or a negative value if an error
|
||||||
|
* occurs preventing the data from being written in its entirety.
|
||||||
*/
|
*/
|
||||||
int guac_terminal_printf(guac_terminal* terminal, const char* format, ...);
|
int guac_terminal_printf(guac_terminal* terminal, const char* format, ...);
|
||||||
|
|
||||||
@ -486,9 +544,24 @@ int guac_terminal_send_data(guac_terminal* term, const char* data, int length);
|
|||||||
int guac_terminal_send_string(guac_terminal* term, const char* data);
|
int guac_terminal_send_string(guac_terminal* term, const char* data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the given string of characters to the terminal.
|
* Writes the given buffer to the given terminal's STDOUT. All requested bytes
|
||||||
|
* will be written unless an error occurs. This function may block until space
|
||||||
|
* is freed in the output buffer by guac_terminal_render_frame().
|
||||||
|
*
|
||||||
|
* @param term
|
||||||
|
* The terminal to write to.
|
||||||
|
*
|
||||||
|
* @param buffer
|
||||||
|
* A buffer containing the characters to be written to the terminal.
|
||||||
|
*
|
||||||
|
* @param length
|
||||||
|
* The number of bytes within the given string to write to the terminal.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The number of bytes written to STDOUT, or a negative value if an error
|
||||||
|
* occurs preventing the data from being written in its entirety.
|
||||||
*/
|
*/
|
||||||
int guac_terminal_write(guac_terminal* term, const char* c, int size);
|
int guac_terminal_write(guac_terminal* term, const char* buffer, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the handlers of the given guac_stream such that it serves as the
|
* Initializes the handlers of the given guac_stream such that it serves as the
|
||||||
@ -532,7 +605,7 @@ int guac_terminal_send_stream(guac_terminal* term, guac_user* user,
|
|||||||
* STDIN.
|
* STDIN.
|
||||||
*
|
*
|
||||||
* @param ...
|
* @param ...
|
||||||
* Any srguments to use when filling the format string.
|
* Any arguments to use when filling the format string.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The number of bytes written to STDIN, or a negative value if an error
|
* The number of bytes written to STDIN, or a negative value if an error
|
||||||
@ -560,7 +633,20 @@ void guac_terminal_dup(guac_terminal* term, guac_user* user,
|
|||||||
guac_socket* socket);
|
guac_socket* socket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize the terminal to the given dimensions.
|
* Resize the client display and terminal to the given pixel dimensions.
|
||||||
|
*
|
||||||
|
* @param term
|
||||||
|
* The terminal to resize.
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* The new terminal width, in pixels.
|
||||||
|
*
|
||||||
|
* @param height
|
||||||
|
* The new terminal height, in pixels.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the terminal was successfully resized to the given dimensions,
|
||||||
|
* non-zero otherwise.
|
||||||
*/
|
*/
|
||||||
int guac_terminal_resize(guac_terminal* term, int width, int height);
|
int guac_terminal_resize(guac_terminal* term, int width, int height);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user