Merge 1.1.0 changes back to master.
diff --git a/Dockerfile b/Dockerfile
index f5f7a42..094842c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -75,7 +75,7 @@
         > ${PREFIX_DIR}/DEPENDENCIES
 
 # Use same Debian as the base for the runtime image
-FROM debian:${DEBIAN_VERSION}
+FROM debian:${DEBIAN_VERSION}-slim
 
 # Base directory for installed build artifacts.
 # Due to limitations of the Docker image build process, this value is
diff --git a/configure.ac b/configure.ac
index e1950ef..7fc7d33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -528,11 +528,39 @@
 fi
 
 #
+# TLS Locking Support within libVNCServer
+#
+
+if test "x${have_libvncserver}" = "xyes"
+then
+
+    have_vnc_tls_locking=yes
+    AC_CHECK_MEMBERS([rfbClient.LockWriteToTLS, rfbClient.UnlockWriteToTLS],
+                     [], [have_vnc_tls_locking=no],
+                     [[#include <rfb/rfbclient.h>]])
+
+    if test "x${have_vnc_tls_locking}" = "xno"
+    then
+        AC_MSG_WARN([
+      --------------------------------------------
+       This version of libvncclient lacks support
+       for TLS locking.  VNC connections that use
+       TLS may experience instability as documented
+       in GUACAMOLE-414])
+    else
+        AC_DEFINE([ENABLE_VNC_TLS_LOCKING],,
+                  [Whether support for TLS locking within VNC is enabled.])
+    fi
+
+fi
+
+#
 # FreeRDP
 #
 
 have_freerdp=disabled
 RDP_LIBS=
+WINPR_LIBS=
 AC_ARG_WITH([rdp],
             [AS_HELP_STRING([--with-rdp],
                             [support RDP @<:@default=check@:>@])],
@@ -734,6 +762,21 @@
                                   [#include <freerdp/utils/stream.h>])])
 fi
 
+# Find location of Stream_New and Stream_free
+if test "x${have_freerdp}" = "xyes" -a "x${have_winpr}" = "xyes"
+then
+    AC_CHECK_LIB([winpr], [Stream_New, Stream_Free],
+                 [WINPR_LIBS="$WINPR_LIBS -lwinpr"],
+                 [AC_CHECK_LIB([winpr-utils], [Stream_New, Stream_Free],
+                               [WINPR_LIBS="$WINPR_LIBS -lwinpr-utils"],
+                               [AC_MSG_WARN([
+  ------------------------------------------
+  Unable to locate stream functions in winpr
+  libraries.  RDP will be disabled.
+  ------------------------------------------])
+                                    have_freerdp=no])])
+fi
+
 # Check for types in WinPR
 if test "x${have_freerdp}" = "xyes"
 then
@@ -1042,6 +1085,7 @@
 AM_CONDITIONAL([ENABLE_RDP],   [test "x${have_freerdp}" = "xyes"])
 
 AC_SUBST(RDP_LIBS)
+AC_SUBST(WINPR_LIBS)
 
 #
 # libssh2
diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c
index bd84f6c..7158a98 100644
--- a/src/protocols/kubernetes/kubernetes.c
+++ b/src/protocols/kubernetes/kubernetes.c
@@ -239,7 +239,7 @@
 
     /* Create terminal */
     kubernetes_client->term = guac_terminal_create(client,
-            kubernetes_client->clipboard,
+            kubernetes_client->clipboard, settings->disable_copy,
             settings->max_scrollback, settings->font_name, settings->font_size,
             settings->resolution, settings->width, settings->height,
             settings->color_scheme, settings->backspace);
diff --git a/src/protocols/kubernetes/settings.c b/src/protocols/kubernetes/settings.c
index 0ae3dc2..4ed5f51 100644
--- a/src/protocols/kubernetes/settings.c
+++ b/src/protocols/kubernetes/settings.c
@@ -50,6 +50,8 @@
     "read-only",
     "backspace",
     "scrollback",
+    "disable-copy",
+    "disable-paste",
     NULL
 };
 
@@ -216,6 +218,20 @@
      */
     IDX_SCROLLBACK,
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set to "true",
+     * it will not be possible to copy data from the terminal to the client
+     * using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_COPY,
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set to "true", it
+     * will not be possible to paste data from the client to the terminal using
+     * the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_PASTE,
+
     KUBERNETES_ARGS_COUNT
 };
 
@@ -364,6 +380,16 @@
         guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
                 IDX_BACKSPACE, 127);
 
+    /* Parse clipboard copy disable flag */
+    settings->disable_copy =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_DISABLE_COPY, false);
+
+    /* Parse clipboard paste disable flag */
+    settings->disable_paste =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_DISABLE_PASTE, false);
+
     /* Parsing was successful */
     return settings;
 
diff --git a/src/protocols/kubernetes/settings.h b/src/protocols/kubernetes/settings.h
index 6267a18..eef4973 100644
--- a/src/protocols/kubernetes/settings.h
+++ b/src/protocols/kubernetes/settings.h
@@ -171,6 +171,20 @@
     int resolution;
 
     /**
+     * Whether outbound clipboard access should be blocked. If set, it will not
+     * be possible to copy data from the terminal to the client using the
+     * clipboard.
+     */
+    bool disable_copy;
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set, it will not
+     * be possible to paste data from the client to the terminal using the
+     * clipboard.
+     */
+    bool disable_paste;
+
+    /**
      * The path in which the typescript should be saved, if enabled. If no
      * typescript should be saved, this will be NULL.
      */
diff --git a/src/protocols/kubernetes/user.c b/src/protocols/kubernetes/user.c
index e7f6d8f..d1fcd5d 100644
--- a/src/protocols/kubernetes/user.c
+++ b/src/protocols/kubernetes/user.c
@@ -81,10 +81,13 @@
     /* Only handle events if not read-only */
     if (!settings->read_only) {
 
-        /* General mouse/keyboard/clipboard events */
-        user->key_handler       = guac_kubernetes_user_key_handler;
-        user->mouse_handler     = guac_kubernetes_user_mouse_handler;
-        user->clipboard_handler = guac_kubernetes_clipboard_handler;
+        /* General mouse/keyboard events */
+        user->key_handler = guac_kubernetes_user_key_handler;
+        user->mouse_handler = guac_kubernetes_user_mouse_handler;
+
+        /* Inbound (client to server) clipboard transfer */
+        if (!settings->disable_paste)
+            user->clipboard_handler = guac_kubernetes_clipboard_handler;
 
         /* STDIN redirection */
         user->pipe_handler = guac_kubernetes_pipe_handler;
diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am
index 1ba406c..d679a71 100644
--- a/src/protocols/rdp/Makefile.am
+++ b/src/protocols/rdp/Makefile.am
@@ -156,7 +156,8 @@
     -version-info 0:0:0         \
     @CAIRO_LIBS@                \
     @PTHREAD_LIBS@              \
-    @RDP_LIBS@
+    @RDP_LIBS@                  \
+    @WINPR_LIBS@
 
 libguac_client_rdp_la_LIBADD =     \
     @COMMON_LTLIB@                 \
@@ -175,7 +176,8 @@
 guacdr_ldflags =                   \
     -module -avoid-version -shared \
     @PTHREAD_LIBS@                 \
-    @RDP_LIBS@
+    @RDP_LIBS@                     \
+    @WINPR_LIBS@
 
 guacdr_libadd =     \
     @COMMON_LTLIB@  \
@@ -194,7 +196,8 @@
 guacai_ldflags =                   \
     -module -avoid-version -shared \
     @PTHREAD_LIBS@                 \
-    @RDP_LIBS@
+    @RDP_LIBS@                     \
+    @WINPR_LIBS@
 
 guacai_libadd =     \
     @COMMON_LTLIB@  \
@@ -213,7 +216,8 @@
 guacsnd_ldflags =                  \
     -module -avoid-version -shared \
     @PTHREAD_LIBS@                 \
-    @RDP_LIBS@
+    @RDP_LIBS@                     \
+    @WINPR_LIBS@
 
 guacsnd_libadd =    \
     @COMMON_LTLIB@  \
@@ -232,7 +236,8 @@
 guacsvc_ldflags =                  \
     -module -avoid-version -shared \
     @PTHREAD_LIBS@                 \
-    @RDP_LIBS@
+    @RDP_LIBS@                     \
+    @WINPR_LIBS@
 
 guacsvc_libadd =    \
     @COMMON_LTLIB@  \
@@ -265,6 +270,7 @@
     $(srcdir)/keymaps/es_es_qwerty.keymap \
     $(srcdir)/keymaps/fr_fr_azerty.keymap \
     $(srcdir)/keymaps/fr_ch_qwertz.keymap \
+    $(srcdir)/keymaps/hu_hu_qwertz.keymap \
     $(srcdir)/keymaps/it_it_qwerty.keymap \
     $(srcdir)/keymaps/ja_jp_qwerty.keymap \
     $(srcdir)/keymaps/pt_br_qwerty.keymap \
diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
index cc367c4..45de442 100644
--- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
+++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c
@@ -110,35 +110,36 @@
      * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously),
      * ignore the header and parse as a Wave PDU.
      */
-    if (rdpsnd->next_pdu_is_wave) {
+    if (rdpsnd->next_pdu_is_wave)
         guac_rdpsnd_wave_handler(rdpsnd, input_stream, &header);
-        return;
-    }
-
+    
     /* Dispatch message to standard handlers */
-    switch (header.message_type) {
+    else {
+        switch (header.message_type) {
 
-        /* Server Audio Formats and Version PDU */
-        case SNDC_FORMATS:
-            guac_rdpsnd_formats_handler(rdpsnd, input_stream, &header);
-            break;
+            /* Server Audio Formats and Version PDU */
+            case SNDC_FORMATS:
+                guac_rdpsnd_formats_handler(rdpsnd, input_stream, &header);
+                break;
 
-        /* Training PDU */
-        case SNDC_TRAINING:
-            guac_rdpsnd_training_handler(rdpsnd, input_stream, &header);
-            break;
+            /* Training PDU */
+            case SNDC_TRAINING:
+                guac_rdpsnd_training_handler(rdpsnd, input_stream, &header);
+                break;
 
-        /* WaveInfo PDU */
-        case SNDC_WAVE:
-            guac_rdpsnd_wave_info_handler(rdpsnd, input_stream, &header);
-            break;
+            /* WaveInfo PDU */
+            case SNDC_WAVE:
+                guac_rdpsnd_wave_info_handler(rdpsnd, input_stream, &header);
+                break;
 
-        /* Close PDU */
-        case SNDC_CLOSE:
-            guac_rdpsnd_close_handler(rdpsnd, input_stream, &header);
-            break;
+            /* Close PDU */
+            case SNDC_CLOSE:
+                guac_rdpsnd_close_handler(rdpsnd, input_stream, &header);
+                break;
 
+        }
     }
 
+    Stream_Free(input_stream, TRUE);
 }
 
diff --git a/src/protocols/rdp/keymaps/hu_hu_qwertz.keymap b/src/protocols/rdp/keymaps/hu_hu_qwertz.keymap
new file mode 100644
index 0000000..bcb6a67
--- /dev/null
+++ b/src/protocols/rdp/keymaps/hu_hu_qwertz.keymap
@@ -0,0 +1,100 @@
+#
+# 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    "hu-hu-qwertz"
+freerdp "KBD_HUNGARIAN"
+
+#
+# Basic keys
+#
+
+map -altgr -shift 0x29 0x02..0x0D      ~ "0123456789öüó"
+map -altgr -shift      0x10..0x1B      ~ "qwertzuıopőú"
+map -altgr -shift      0x1E..0x28 0x2B ~ "asdfghjkléáű"
+map -altgr -shift 0x56 0x2C..0x35      ~ "íyxcvbnm,.-"
+
+map -altgr +shift 0x29 0x02..0x0D      ~ "§'"+!%/=()ÖÜÓ"
+map -altgr +shift      0x10..0x1B      ~ "QWERTZUIOPŐÚ"
+map -altgr +shift      0x1E..0x28 0x2B ~ "ASDFGHJKLÉÁŰ"
+map -altgr +shift 0x56 0x2C..0x35      ~ "ÍYXCVBNM?:_"
+
+
+#
+# Keys requiring AltGr
+#
+
+map +altgr -shift 0x02 ~ "~"
+map +altgr -shift 0x08 ~ "`"
+
+map +altgr -shift 0x10 ~ "\"
+map +altgr -shift 0x11 ~ "|"
+map +altgr -shift 0x12 ~ "Ä"
+map +altgr -shift 0x16 ~ "€"
+map +altgr -shift 0x17 ~ "Í"
+map +altgr -shift 0x1A ~ "÷"
+map +altgr -shift 0x1B ~ "×"
+
+map +altgr -shift 0x1E ~ "ä"
+map +altgr -shift 0x1F ~ "đ"
+map +altgr -shift 0x20 ~ "Đ"
+map +altgr -shift 0x21 ~ "["
+map +altgr -shift 0x22 ~ "]"
+map +altgr -shift 0x24 ~ "í"
+map +altgr -shift 0x25 ~ "ł"
+map +altgr -shift 0x26 ~ "Ł"
+map +altgr -shift 0x27 ~ "$"
+map +altgr -shift 0x28 ~ "ß"
+map +altgr -shift 0x2B ~ "¤"
+
+map +altgr -shift 0x56 ~ "<"
+map +altgr -shift 0x2C ~ ">"
+map +altgr -shift 0x2D ~ "#"
+map +altgr -shift 0x2E ~ "&"
+map +altgr -shift 0x2F ~ "@"
+map +altgr -shift 0x30 ~ "{"
+map +altgr -shift 0x31 ~ "}"
+map +altgr -shift 0x32 ~ "<"
+map +altgr -shift 0x33 ~ ";"
+map +altgr -shift 0x34 ~ ">"
+map +altgr -shift 0x35 ~ "*"
+
+
+#
+# Keys requiring AltGr & Shift
+#
+
+
+#
+# Dead keys
+#
+
+map +altgr -shift 0x03 ~ 0xFE5A # Dead caron
+map +altgr -shift 0x04 ~ 0xFE52 # Dead circumflex
+map +altgr -shift 0x05 ~ 0xFE55 # Dead breve
+map +altgr -shift 0x06 ~ 0xFE58 # Dead abovering
+map +altgr -shift 0x07 ~ 0xFE5C # Dead ogonek
+map +altgr -shift 0x09 ~ 0xFE56 # Dead abovedot
+map +altgr -shift 0x0A ~ 0xFE51 # Dead acute
+map +altgr -shift 0x0B ~ 0xFE59 # Dead doubleacute
+map +altgr -shift 0x0C ~ 0xFE57 # Dead diaeresis
+map +altgr -shift 0x0D ~ 0xFE5B # Dead cedilla
+
+
+# END
diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
index 86f5096..d0df053 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -240,11 +240,13 @@
         guac_rdp_audio_load_plugin(instance->context, dvc_list);
     }
 
-    /* Load clipboard plugin */
-    if (freerdp_channels_load_plugin(channels, instance->settings,
-                "cliprdr", NULL))
+    /* Load clipboard plugin if not disabled */
+    if (!(settings->disable_copy && settings->disable_paste)
+            && freerdp_channels_load_plugin(channels, instance->settings,
+                "cliprdr", NULL)) {
         guac_client_log(client, GUAC_LOG_WARNING,
                 "Failed to load cliprdr plugin. Clipboard will not work.");
+    }
 
     /* If RDPSND/RDPDR required, load them */
     if (settings->printing_enabled
diff --git a/src/protocols/rdp/rdp_cliprdr.c b/src/protocols/rdp/rdp_cliprdr.c
index 5301911..903752c 100644
--- a/src/protocols/rdp/rdp_cliprdr.c
+++ b/src/protocols/rdp/rdp_cliprdr.c
@@ -230,6 +230,10 @@
     guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
     char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
 
+    /* Ignore received text if outbound clipboard transfer is disabled */
+    if (rdp_client->settings->disable_copy)
+        return;
+
     guac_iconv_read* reader;
     const char* input = (char*) event->data;
     char* output = received_data;
diff --git a/src/protocols/rdp/rdp_fs.c b/src/protocols/rdp/rdp_fs.c
index 0e7345f..24d7c3e 100644
--- a/src/protocols/rdp/rdp_fs.c
+++ b/src/protocols/rdp/rdp_fs.c
@@ -403,7 +403,7 @@
 
 }
 
-int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, int offset,
+int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, uint64_t offset,
         void* buffer, int length) {
 
     int bytes_read;
@@ -427,7 +427,7 @@
 
 }
 
-int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, int offset,
+int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, uint64_t offset,
         void* buffer, int length) {
 
     int bytes_written;
diff --git a/src/protocols/rdp/rdp_fs.h b/src/protocols/rdp/rdp_fs.h
index 7ceb5ff..e8299ef 100644
--- a/src/protocols/rdp/rdp_fs.h
+++ b/src/protocols/rdp/rdp_fs.h
@@ -492,7 +492,7 @@
  *     error occurs. All error codes are negative values and correspond to
  *     GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT.
  */
-int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, int offset,
+int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, uint64_t offset,
         void* buffer, int length);
 
 /**
@@ -520,7 +520,7 @@
  *     occurs. All error codes are negative values and correspond to
  *     GUAC_RDP_FS constants, such as GUAC_RDP_FS_ENOENT.
  */
-int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, int offset,
+int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, uint64_t offset,
         void* buffer, int length);
 
 /**
diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c
index 51214a6..11cc861 100644
--- a/src/protocols/rdp/rdp_settings.c
+++ b/src/protocols/rdp/rdp_settings.c
@@ -119,6 +119,8 @@
     "load-balance-info",
 #endif
 
+    "disable-copy",
+    "disable-paste",
     NULL
 };
 
@@ -546,6 +548,20 @@
     IDX_LOAD_BALANCE_INFO,
 #endif
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set to "true",
+     * it will not be possible to copy data from the remote desktop to the
+     * client using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_COPY,
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set to "true", it
+     * will not be possible to paste data from the client to the remote desktop
+     * using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_PASTE,
+
     RDP_ARGS_COUNT
 };
 
@@ -1008,6 +1024,16 @@
                 IDX_LOAD_BALANCE_INFO, NULL);
 #endif
 
+    /* Parse clipboard copy disable flag */
+    settings->disable_copy =
+        guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,
+                IDX_DISABLE_COPY, 0);
+
+    /* Parse clipboard paste disable flag */
+    settings->disable_paste =
+        guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,
+                IDX_DISABLE_PASTE, 0);
+
     /* Success */
     return settings;
 
diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h
index 6955ed5..9edbede 100644
--- a/src/protocols/rdp/rdp_settings.h
+++ b/src/protocols/rdp/rdp_settings.h
@@ -269,6 +269,20 @@
     char** svc_names;
 
     /**
+     * Whether outbound clipboard access should be blocked. If set, it will not
+     * be possible to copy data from the remote desktop to the client using the
+     * clipboard.
+     */
+    int disable_copy;
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set, it will not
+     * be possible to paste data from the client to the remote desktop using
+     * the clipboard.
+     */
+    int disable_paste;
+
+    /**
      * Whether the desktop wallpaper should be visible. If unset, the desktop
      * wallpaper will be hidden, reducing the amount of bandwidth required.
      */
diff --git a/src/protocols/rdp/rdp_stream.h b/src/protocols/rdp/rdp_stream.h
index c9c3838..deec4f9 100644
--- a/src/protocols/rdp/rdp_stream.h
+++ b/src/protocols/rdp/rdp_stream.h
@@ -57,7 +57,7 @@
      * The overall offset within the file that the next write should
      * occur at.
      */
-    int offset;
+    uint64_t offset;
 
     /**
      * The ID of the file being written to.
diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c
index 6aa71ae..025848a 100644
--- a/src/protocols/rdp/user.c
+++ b/src/protocols/rdp/user.c
@@ -97,10 +97,13 @@
     /* Only handle events if not read-only */
     if (!settings->read_only) {
 
-        /* General mouse/keyboard/clipboard events */
-        user->mouse_handler     = guac_rdp_user_mouse_handler;
-        user->key_handler       = guac_rdp_user_key_handler;
-        user->clipboard_handler = guac_rdp_clipboard_handler;
+        /* General mouse/keyboard events */
+        user->mouse_handler = guac_rdp_user_mouse_handler;
+        user->key_handler = guac_rdp_user_key_handler;
+
+        /* Inbound (client to server) clipboard transfer */
+        if (!settings->disable_paste)
+            user->clipboard_handler = guac_rdp_clipboard_handler;
 
         /* Display size change events */
         user->size_handler = guac_rdp_user_size_handler;
diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c
index a0af9f9..7dab321 100644
--- a/src/protocols/ssh/settings.c
+++ b/src/protocols/ssh/settings.c
@@ -62,6 +62,8 @@
     "scrollback",
     "locale",
     "timezone",
+    "disable-copy",
+    "disable-paste",
     NULL
 };
 
@@ -258,6 +260,20 @@
      */
     IDX_TIMEZONE,
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set to "true",
+     * it will not be possible to copy data from the terminal to the client
+     * using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_COPY,
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set to "true", it
+     * will not be possible to paste data from the client to the terminal using
+     * the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_PASTE,
+
     SSH_ARGS_COUNT
 };
 
@@ -426,6 +442,16 @@
         guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
                 IDX_TIMEZONE, user->info.timezone);
 
+    /* Parse clipboard copy disable flag */
+    settings->disable_copy =
+        guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
+                IDX_DISABLE_COPY, false);
+
+    /* Parse clipboard paste disable flag */
+    settings->disable_paste =
+        guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
+                IDX_DISABLE_PASTE, false);
+
     /* Parsing was successful */
     return settings;
 
diff --git a/src/protocols/ssh/settings.h b/src/protocols/ssh/settings.h
index baa634a..bab21bd 100644
--- a/src/protocols/ssh/settings.h
+++ b/src/protocols/ssh/settings.h
@@ -156,6 +156,20 @@
     int resolution;
 
     /**
+     * Whether outbound clipboard access should be blocked. If set, it will not
+     * be possible to copy data from the terminal to the client using the
+     * clipboard.
+     */
+    bool disable_copy;
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set, it will not
+     * be possible to paste data from the client to the terminal using the
+     * clipboard.
+     */
+    bool disable_paste;
+
+    /**
      * Whether SFTP is enabled.
      */
     bool enable_sftp;
diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c
index 456c214..8957205 100644
--- a/src/protocols/ssh/ssh.c
+++ b/src/protocols/ssh/ssh.c
@@ -223,9 +223,10 @@
 
     /* Create terminal */
     ssh_client->term = guac_terminal_create(client, ssh_client->clipboard,
-            settings->max_scrollback, settings->font_name, settings->font_size,
-            settings->resolution, settings->width, settings->height,
-            settings->color_scheme, settings->backspace);
+            settings->disable_copy, settings->max_scrollback,
+            settings->font_name, settings->font_size, settings->resolution,
+            settings->width, settings->height, settings->color_scheme,
+            settings->backspace);
 
     /* Fail if terminal init failed */
     if (ssh_client->term == NULL) {
diff --git a/src/protocols/ssh/user.c b/src/protocols/ssh/user.c
index ccf2447..8ea30a4 100644
--- a/src/protocols/ssh/user.c
+++ b/src/protocols/ssh/user.c
@@ -81,10 +81,13 @@
     /* Only handle events if not read-only */
     if (!settings->read_only) {
 
-        /* General mouse/keyboard/clipboard events */
-        user->key_handler       = guac_ssh_user_key_handler;
-        user->mouse_handler     = guac_ssh_user_mouse_handler;
-        user->clipboard_handler = guac_ssh_clipboard_handler;
+        /* General mouse/keyboard events */
+        user->key_handler = guac_ssh_user_key_handler;
+        user->mouse_handler = guac_ssh_user_mouse_handler;
+
+        /* Inbound (client to server) clipboard transfer */
+        if (!settings->disable_paste)
+            user->clipboard_handler = guac_ssh_clipboard_handler;
 
         /* STDIN redirection */
         user->pipe_handler = guac_ssh_pipe_handler;
diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c
index 85b4fb8..e72359c 100644
--- a/src/protocols/telnet/settings.c
+++ b/src/protocols/telnet/settings.c
@@ -55,6 +55,8 @@
     "scrollback",
     "login-success-regex",
     "login-failure-regex",
+    "disable-copy",
+    "disable-paste",
     NULL
 };
 
@@ -216,6 +218,20 @@
      */
     IDX_LOGIN_FAILURE_REGEX,
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set to "true",
+     * it will not be possible to copy data from the terminal to the client
+     * using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_COPY,
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set to "true", it
+     * will not be possible to paste data from the client to the terminal using
+     * the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_PASTE,
+
     TELNET_ARGS_COUNT
 };
 
@@ -428,6 +444,16 @@
         guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
                 IDX_TERMINAL_TYPE, "linux");
 
+    /* Parse clipboard copy disable flag */
+    settings->disable_copy =
+        guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
+                IDX_DISABLE_COPY, false);
+
+    /* Parse clipboard paste disable flag */
+    settings->disable_paste =
+        guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
+                IDX_DISABLE_PASTE, false);
+
     /* Parsing was successful */
     return settings;
 
diff --git a/src/protocols/telnet/settings.h b/src/protocols/telnet/settings.h
index 86302b7..691669c 100644
--- a/src/protocols/telnet/settings.h
+++ b/src/protocols/telnet/settings.h
@@ -172,6 +172,20 @@
     int resolution;
 
     /**
+     * Whether outbound clipboard access should be blocked. If set, it will not
+     * be possible to copy data from the terminal to the client using the
+     * clipboard.
+     */
+    bool disable_copy;
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set, it will not
+     * be possible to paste data from the client to the terminal using the
+     * clipboard.
+     */
+    bool disable_paste;
+
+    /**
      * The path in which the typescript should be saved, if enabled. If no
      * typescript should be saved, this will be NULL.
      */
diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c
index e100fae..5a5ca30 100644
--- a/src/protocols/telnet/telnet.c
+++ b/src/protocols/telnet/telnet.c
@@ -570,7 +570,7 @@
 
     /* Create terminal */
     telnet_client->term = guac_terminal_create(client,
-            telnet_client->clipboard,
+            telnet_client->clipboard, settings->disable_copy,
             settings->max_scrollback, settings->font_name, settings->font_size,
             settings->resolution, settings->width, settings->height,
             settings->color_scheme, settings->backspace);
diff --git a/src/protocols/telnet/user.c b/src/protocols/telnet/user.c
index 08cfc6f..63408cc 100644
--- a/src/protocols/telnet/user.c
+++ b/src/protocols/telnet/user.c
@@ -80,10 +80,13 @@
     /* Only handle events if not read-only */
     if (!settings->read_only) {
 
-        /* General mouse/keyboard/clipboard events */
-        user->key_handler       = guac_telnet_user_key_handler;
-        user->mouse_handler     = guac_telnet_user_mouse_handler;
-        user->clipboard_handler = guac_telnet_clipboard_handler;
+        /* General mouse/keyboard events */
+        user->key_handler = guac_telnet_user_key_handler;
+        user->mouse_handler = guac_telnet_user_mouse_handler;
+
+        /* Inbound (client to server) clipboard transfer */
+        if (!settings->disable_paste)
+            user->clipboard_handler = guac_telnet_clipboard_handler;
 
         /* STDIN redirection */
         user->pipe_handler = guac_telnet_pipe_handler;
diff --git a/src/protocols/vnc/client.c b/src/protocols/vnc/client.c
index 9cc85a1..cee1d4d 100644
--- a/src/protocols/vnc/client.c
+++ b/src/protocols/vnc/client.c
@@ -36,6 +36,7 @@
 
 #include <guacamole/client.h>
 
+#include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -48,6 +49,11 @@
     guac_vnc_client* vnc_client = calloc(1, sizeof(guac_vnc_client));
     client->data = vnc_client;
 
+#ifdef ENABLE_VNC_TLS_LOCKING
+    /* Initialize the write lock */
+    pthread_mutex_init(&(vnc_client->tls_lock), NULL);
+#endif
+
     /* Init clipboard */
     vnc_client->clipboard = guac_common_clipboard_alloc(GUAC_VNC_CLIPBOARD_MAX_LENGTH);
 
@@ -125,6 +131,11 @@
     if (settings != NULL)
         guac_vnc_settings_free(settings);
 
+#ifdef ENABLE_VNC_TLS_LOCKING
+    /* Clean up TLS lock mutex. */
+    pthread_mutex_destroy(&(vnc_client->tls_lock));
+#endif
+
     /* Free generic data struct */
     free(client->data);
 
diff --git a/src/protocols/vnc/clipboard.c b/src/protocols/vnc/clipboard.c
index a49f565..c3b1bd1 100644
--- a/src/protocols/vnc/clipboard.c
+++ b/src/protocols/vnc/clipboard.c
@@ -125,6 +125,10 @@
     guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
     guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;
 
+    /* Ignore received text if outbound clipboard transfer is disabled */
+    if (vnc_client->settings->disable_copy)
+        return;
+
     char received_data[GUAC_VNC_CLIPBOARD_MAX_LENGTH];
 
     const char* input = text;
diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c
index 623e668..a21aea8 100644
--- a/src/protocols/vnc/settings.c
+++ b/src/protocols/vnc/settings.c
@@ -77,7 +77,8 @@
     "recording-exclude-mouse",
     "recording-include-keys",
     "create-recording-path",
-
+    "disable-copy",
+    "disable-paste",
     NULL
 };
 
@@ -298,6 +299,20 @@
      */
     IDX_CREATE_RECORDING_PATH,
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set to "true",
+     * it will not be possible to copy data from the remote desktop to the
+     * client using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_COPY,
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set to "true", it
+     * will not be possible to paste data from the client to the remote desktop
+     * using the clipboard. By default, clipboard access is not blocked.
+     */
+    IDX_DISABLE_PASTE,
+
     VNC_ARGS_COUNT
 };
 
@@ -493,6 +508,16 @@
         guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv,
                 IDX_CREATE_RECORDING_PATH, false);
 
+    /* Parse clipboard copy disable flag */
+    settings->disable_copy =
+        guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv,
+                IDX_DISABLE_COPY, false);
+
+    /* Parse clipboard paste disable flag */
+    settings->disable_paste =
+        guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv,
+                IDX_DISABLE_PASTE, false);
+
     return settings;
 
 }
diff --git a/src/protocols/vnc/settings.h b/src/protocols/vnc/settings.h
index 3e2ebd5..13a3d87 100644
--- a/src/protocols/vnc/settings.h
+++ b/src/protocols/vnc/settings.h
@@ -127,6 +127,20 @@
      */
     char* clipboard_encoding;
 
+    /**
+     * Whether outbound clipboard access should be blocked. If set, it will not
+     * be possible to copy data from the remote desktop to the client using the
+     * clipboard.
+     */
+    bool disable_copy;
+
+    /**
+     * Whether inbound clipboard access should be blocked. If set, it will not
+     * be possible to paste data from the client to the remote desktop using
+     * the clipboard.
+     */
+    bool disable_paste;
+
 #ifdef ENABLE_COMMON_SSH
     /**
      * Whether SFTP should be enabled for the VNC connection.
diff --git a/src/protocols/vnc/user.c b/src/protocols/vnc/user.c
index da3b843..0dee504 100644
--- a/src/protocols/vnc/user.c
+++ b/src/protocols/vnc/user.c
@@ -91,10 +91,13 @@
     /* Only handle events if not read-only */
     if (!settings->read_only) {
 
-        /* General mouse/keyboard/clipboard events */
-        user->mouse_handler     = guac_vnc_user_mouse_handler;
-        user->key_handler       = guac_vnc_user_key_handler;
-        user->clipboard_handler = guac_vnc_clipboard_handler;
+        /* General mouse/keyboard events */
+        user->mouse_handler = guac_vnc_user_mouse_handler;
+        user->key_handler = guac_vnc_user_key_handler;
+
+        /* Inbound (client to server) clipboard transfer */
+        if (!settings->disable_paste)
+            user->clipboard_handler = guac_vnc_clipboard_handler;
 
 #ifdef ENABLE_COMMON_SSH
         /* Set generic (non-filesystem) file upload handler */
diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c
index afffaac..17033a6 100644
--- a/src/protocols/vnc/vnc.c
+++ b/src/protocols/vnc/vnc.c
@@ -55,6 +55,66 @@
 
 char* GUAC_VNC_CLIENT_KEY = "GUAC_VNC";
 
+#ifdef ENABLE_VNC_TLS_LOCKING
+/**
+ * A callback function that is called by the VNC library prior to writing
+ * data to a TLS-encrypted socket.  This returns the rfbBool FALSE value
+ * if there's an error locking the mutex, or rfbBool TRUE otherwise.
+ * 
+ * @param rfb_client
+ *     The rfbClient for which to lock the TLS mutex.
+ *
+ * @returns
+ *     rfbBool FALSE if an error occurs locking the mutex, otherwise
+ *     TRUE.
+ */
+static rfbBool guac_vnc_lock_write_to_tls(rfbClient* rfb_client) {
+
+    /* Retrieve the Guacamole data structures */
+    guac_client* gc = rfbClientGetClientData(rfb_client, GUAC_VNC_CLIENT_KEY);
+    guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;
+
+    /* Lock write access */
+    int retval = pthread_mutex_lock(&(vnc_client->tls_lock));
+    if (retval) {
+        guac_client_log(gc, GUAC_LOG_ERROR, "Error locking TLS write mutex: %s",
+                strerror(retval));
+        return FALSE;
+    }
+    return TRUE;
+
+}
+
+/**
+ * A callback function for use by the VNC library that is called once
+ * the client is finished writing to a TLS-encrypted socket. A rfbBool
+ * FALSE value is returned if an error occurs unlocking the mutex,
+ * otherwise TRUE is returned.
+ *
+ * @param rfb_client
+ *     The rfbClient for which to unlock the TLS mutex.
+ *
+ * @returns
+ *     rfbBool FALSE if an error occurs unlocking the mutex, otherwise
+ *     TRUE.
+ */
+static rfbBool guac_vnc_unlock_write_to_tls(rfbClient* rfb_client) {
+
+    /* Retrieve the Guacamole data structures */
+    guac_client* gc = rfbClientGetClientData(rfb_client, GUAC_VNC_CLIENT_KEY);
+    guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;
+
+    /* Unlock write access */
+    int retval = pthread_mutex_unlock(&(vnc_client->tls_lock));
+    if (retval) {
+        guac_client_log(gc, GUAC_LOG_ERROR, "Error unlocking TLS write mutex: %s",
+                strerror(retval));
+        return FALSE;
+    }
+    return TRUE;
+}
+#endif
+
 rfbClient* guac_vnc_get_client(guac_client* client) {
 
     rfbClient* rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */
@@ -68,6 +128,12 @@
     rfb_client->GotFrameBufferUpdate = guac_vnc_update;
     rfb_client->GotCopyRect = guac_vnc_copyrect;
 
+#ifdef ENABLE_VNC_TLS_LOCKING
+    /* TLS Locking and Unlocking */
+    rfb_client->LockWriteToTLS = guac_vnc_lock_write_to_tls;
+    rfb_client->UnlockWriteToTLS = guac_vnc_unlock_write_to_tls;
+#endif
+
     /* Do not handle clipboard and local cursor if read-only */
     if (vnc_settings->read_only == 0) {
 
@@ -403,4 +469,3 @@
     return NULL;
 
 }
-
diff --git a/src/protocols/vnc/vnc.h b/src/protocols/vnc/vnc.h
index ce2d20a..7c189cf 100644
--- a/src/protocols/vnc/vnc.h
+++ b/src/protocols/vnc/vnc.h
@@ -55,6 +55,13 @@
      */
     pthread_t client_thread;
 
+#ifdef ENABLE_VNC_TLS_LOCKING
+    /**
+     * The TLS mutex lock for the client.
+     */
+    pthread_mutex_t tls_lock;
+#endif
+
     /**
      * The underlying VNC client.
      */
diff --git a/src/terminal/select.c b/src/terminal/select.c
index 20fc3cd..0a075eb 100644
--- a/src/terminal/select.c
+++ b/src/terminal/select.c
@@ -375,8 +375,10 @@
     }
 
     /* Send data */
-    guac_common_clipboard_send(terminal->clipboard, client);
-    guac_socket_flush(socket);
+    if (!terminal->disable_copy) {
+        guac_common_clipboard_send(terminal->clipboard, client);
+        guac_socket_flush(socket);
+    }
 
     guac_terminal_notify(terminal);
 
diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c
index 05bf720..b76a6ea 100644
--- a/src/terminal/terminal.c
+++ b/src/terminal/terminal.c
@@ -306,8 +306,8 @@
 }
 
 guac_terminal* guac_terminal_create(guac_client* client,
-        guac_common_clipboard* clipboard, int max_scrollback,
-        const char* font_name, int font_size, int dpi,
+        guac_common_clipboard* clipboard, bool disable_copy,
+        int max_scrollback, const char* font_name, int font_size, int dpi,
         int width, int height, const char* color_scheme,
         const int backspace) {
 
@@ -392,6 +392,7 @@
     term->current_attributes = default_char.attributes;
     term->default_char = default_char;
     term->clipboard = clipboard;
+    term->disable_copy = disable_copy;
 
     /* Calculate character size */
     int rows    = height / term->display->char_height;
diff --git a/src/terminal/terminal/terminal.h b/src/terminal/terminal/terminal.h
index e7746cb..4185837 100644
--- a/src/terminal/terminal/terminal.h
+++ b/src/terminal/terminal/terminal.h
@@ -530,6 +530,14 @@
      */
     char backspace;
 
+    /**
+     * Whether copying from the terminal clipboard should be blocked. If set,
+     * the contents of the terminal can still be copied, but will be usable
+     * only within the terminal itself. The clipboard contents will not be
+     * automatically streamed to the client.
+     */
+    bool disable_copy;
+
 };
 
 /**
@@ -552,6 +560,12 @@
  *     clipboard instructions. This clipboard will not be automatically
  *     freed when this terminal is freed.
  *
+ * @param disable_copy
+ *     Whether copying from the terminal clipboard should be blocked. If set,
+ *     the contents of the terminal can still be copied, but will be usable
+ *     only within the terminal itself. The clipboard contents will not be
+ *     automatically streamed to the client.
+ *
  * @param max_scrollback
  *     The maximum number of rows to allow within the scrollback buffer. The
  *     user may still alter the size of the scrollback buffer using terminal
@@ -591,8 +605,8 @@
  *     which renders all text to the given client.
  */
 guac_terminal* guac_terminal_create(guac_client* client,
-        guac_common_clipboard* clipboard, int max_scrollback,
-        const char* font_name, int font_size, int dpi,
+        guac_common_clipboard* clipboard, bool disable_copy,
+        int max_scrollback, const char* font_name, int font_size, int dpi,
         int width, int height, const char* color_scheme,
         const int backspace);