From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Gerd Hoffmann <kraxel@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH v1 RFC 26/34] io: add QIOChannelTLS class
Date: Fri, 17 Apr 2015 15:22:29 +0100 [thread overview]
Message-ID: <1429280557-8887-27-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1429280557-8887-1-git-send-email-berrange@redhat.com>
Add a QIOChannel subclass that can run the TLS protocol over the
top of another QIOChannel instance.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
include/io/channel-tls.h | 142 +++++++++++++++++
io/Makefile.objs | 1 +
io/channel-tls.c | 393 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 536 insertions(+)
create mode 100644 include/io/channel-tls.h
create mode 100644 io/channel-tls.c
diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h
new file mode 100644
index 0000000..7023b0a
--- /dev/null
+++ b/include/io/channel-tls.h
@@ -0,0 +1,142 @@
+/*
+ * QEMU I/O channels TLS driver
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QIO_CHANNEL_TLS_H__
+#define QIO_CHANNEL_TLS_H__
+
+#include "io/channel.h"
+#include "io/task.h"
+#include "crypto/tlssession.h"
+
+#define TYPE_QIO_CHANNEL_TLS "qemu:io-channel-tls"
+#define QIO_CHANNEL_TLS(obj) \
+ OBJECT_CHECK(QIOChannelTLS, (obj), TYPE_QIO_CHANNEL_TLS)
+
+typedef struct QIOChannelTLS QIOChannelTLS;
+
+/**
+ * QIOChannelTLS
+ *
+ * The QIOChannelTLS class provides a channel wrapper which
+ * can transparently run the TLS encryption protocol. It is
+ * usually used over a TCP socket, but there is actually no
+ * technical restriction on which type of master channel is
+ * used as the transport.
+ *
+ * This channel object is capable of running as either a
+ * TLS server or TLS client.
+ */
+
+struct QIOChannelTLS {
+ QIOChannel parent;
+ QIOChannel *master;
+ QCryptoTLSSession *session;
+};
+
+/**
+ * qio_channel_tls_new_server:
+ * @master: the underlying channel object
+ * @creds: the credentials to use for TLS handshake
+ * @aclname: the access control list for validating clients
+ * @errp: pointer to an uninitialized error object
+ *
+ * Create a new TLS channel that runs the server side of
+ * a TLS session. The TLS session handshake will use the
+ * credentials provided in @creds. If the @aclname parameter
+ * is non-NULL, then the client will have to provide
+ * credentials (ie a x509 client certificate) which will
+ * then be validated against the ACL.
+ *
+ * After creating the channel, it is mandatory to call
+ * the qio_channel_tls_handshake() method before attempting
+ * todo any I/O on the channel.
+ *
+ * Once the handshake has completed, all I/O should be done
+ * via the new TLS channel object and not the original
+ * master channel
+ *
+ * Returns: the new TLS channel object, or NULL
+ */
+QIOChannelTLS *
+qio_channel_tls_new_server(QIOChannel *master,
+ QCryptoTLSCreds *creds,
+ const char *aclname,
+ Error **errp);
+
+/**
+ * qio_channel_tls_new_client:
+ * @master: the underlying channel object
+ * @creds: the credentials to use for TLS handshake
+ * @hostname: the user specified server hostname
+ * @errp: pointer to an uninitialized error object
+ *
+ * Create a new TLS channel that runs the client side of
+ * a TLS session. The TLS session handshake will use the
+ * credentials provided in @creds. The @hostname parameter
+ * should provide the user specified hostname of the server
+ * and will be validated against the server's credentials
+ * (ie CommonName of the x509 certificate)
+ *
+ * After creating the channel, it is mandatory to call
+ * the qio_channel_tls_handshake() method before attempting
+ * todo any I/O on the channel.
+ *
+ * Once the handshake has completed, all I/O should be done
+ * via the new TLS channel object and not the original
+ * master channel
+ *
+ * Returns: the new TLS channel object, or NULL
+ */
+QIOChannelTLS *
+qio_channel_tls_new_client(QIOChannel *master,
+ QCryptoTLSCreds *creds,
+ const char *hostname,
+ Error **errp);
+
+/**
+ * qio_channel_tls_handshake:
+ * @ioc: the TLS channel object
+ * @func: the callback to invoke when completed
+ * @opaque: opaque data to pass to @func
+ * @destroy: optional callback to free @opaque
+ *
+ * Perform the TLS session handshake. This method
+ * will return immediately and the handshake will
+ * continue in the background, provided the main
+ * loop is running. When the handshake is complete,
+ * or fails, the @func callback will be invoked.
+ */
+void qio_channel_tls_handshake(QIOChannelTLS *ioc,
+ QIOTaskFunc func,
+ gpointer opaque,
+ GDestroyNotify destroy);
+
+/**
+ * qio_channel_tls_get_session:
+ * @ioc: the TLS channel object
+ *
+ * Get the TLS session used by the channel.
+ *
+ * Returns: the TLS session
+ */
+QCryptoTLSSession *
+qio_channel_tls_get_session(QIOChannelTLS *ioc);
+
+#endif /* QIO_CHANNEL_TLS_H__ */
diff --git a/io/Makefile.objs b/io/Makefile.objs
index b9973ac..3bf7656 100644
--- a/io/Makefile.objs
+++ b/io/Makefile.objs
@@ -3,3 +3,4 @@ util-obj-y += channel.o
util-obj-y += channel-unix.o
util-obj-y += channel-socket.o
util-obj-y += channel-file.o
+util-obj-y += channel-tls.o
diff --git a/io/channel-tls.c b/io/channel-tls.c
new file mode 100644
index 0000000..4f5f2e9
--- /dev/null
+++ b/io/channel-tls.c
@@ -0,0 +1,393 @@
+/*
+ * QEMU I/O channels TLS driver
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "io/channel-tls.h"
+
+#define QIO_DEBUG
+
+#ifdef QIO_DEBUG
+#define DPRINTF(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+
+static ssize_t qio_channel_tls_write_handler(const char *buf,
+ size_t len,
+ void *opaque)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
+ int ret;
+
+ ret = qio_channel_write(tioc->master, buf, len, NULL);
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ errno = EAGAIN;
+ return -1;
+ } else if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return ret;
+}
+
+static ssize_t qio_channel_tls_read_handler(char *buf,
+ size_t len,
+ void *opaque)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
+ int ret;
+
+ ret = qio_channel_read(tioc->master, buf, len, NULL);
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ errno = EAGAIN;
+ return -1;
+ } else if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return ret;
+}
+
+
+QIOChannelTLS *
+qio_channel_tls_new_server(QIOChannel *master,
+ QCryptoTLSCreds *creds,
+ const char *aclname,
+ Error **errp)
+{
+ QIOChannelTLS *ioc;
+
+ ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
+
+ ioc->master = master;
+ object_ref(OBJECT(master));
+
+ ioc->session = qcrypto_tls_session_new(
+ creds,
+ NULL,
+ aclname,
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
+ errp);
+ if (!ioc->session) {
+ goto error;
+ }
+
+ qcrypto_tls_session_set_callbacks(
+ ioc->session,
+ qio_channel_tls_write_handler,
+ qio_channel_tls_read_handler,
+ ioc);
+
+ return ioc;
+
+ error:
+ DPRINTF("Session setup failed %s\n",
+ error_get_pretty(*errp));
+ object_unref(OBJECT(ioc));
+ return NULL;
+}
+
+QIOChannelTLS *
+qio_channel_tls_new_client(QIOChannel *master,
+ QCryptoTLSCreds *creds,
+ const char *hostname,
+ Error **errp)
+{
+ QIOChannelTLS *ioc;
+
+ ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
+
+ ioc->master = master;
+ object_ref(OBJECT(master));
+
+ ioc->session = qcrypto_tls_session_new(
+ creds,
+ hostname,
+ NULL,
+ QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
+ errp);
+ if (!ioc->session) {
+ goto error;
+ }
+
+ qcrypto_tls_session_set_callbacks(
+ ioc->session,
+ qio_channel_tls_write_handler,
+ qio_channel_tls_read_handler,
+ ioc);
+
+ return ioc;
+
+ error:
+ DPRINTF("Session setup failed %s\n",
+ error_get_pretty(*errp));
+ object_unref(OBJECT(ioc));
+ return NULL;
+}
+
+
+static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
+ GIOCondition condition,
+ gpointer user_data);
+
+static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc,
+ QIOTask *task)
+{
+ Error *err = NULL;
+ QCryptoTLSSessionHandshakeStatus status;
+
+ if (qcrypto_tls_session_handshake(ioc->session, &err) < 0) {
+ qio_task_abort(task, err);
+ goto cleanup;
+ }
+
+ status = qcrypto_tls_session_get_handshake_status(ioc->session);
+ if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
+ if (qcrypto_tls_session_check_credentials(ioc->session,
+ &err) < 0) {
+ DPRINTF("Check creds failed session=%p err=%s\n",
+ ioc->session, error_get_pretty(err));
+ qio_task_abort(task, err);
+ goto cleanup;
+ }
+ DPRINTF("Handshake compelte session=%p\n",
+ ioc->session);
+ qio_task_complete(task);
+ } else {
+ GIOCondition condition;
+ DPRINTF("Handshake still running %d\n", status);
+ if (status == QCRYPTO_TLS_HANDSHAKE_SENDING) {
+ condition = G_IO_OUT;
+ } else {
+ condition = G_IO_IN;
+ }
+
+ object_ref(OBJECT(task));
+ qio_channel_add_watch_full(ioc->master,
+ G_PRIORITY_DEFAULT,
+ condition,
+ qio_channel_tls_handshake_io,
+ task,
+ (GDestroyNotify)object_unref);
+ }
+
+ cleanup:
+ error_free(err);
+}
+
+
+static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ QIOTask *task = QIO_TASK(user_data);
+
+ qio_channel_tls_handshake_task(
+ QIO_CHANNEL_TLS(task->source), task);
+
+ return FALSE;
+}
+
+void qio_channel_tls_handshake(QIOChannelTLS *ioc,
+ QIOTaskFunc func,
+ gpointer opaque,
+ GDestroyNotify destroy)
+{
+ QIOTask *task;
+
+ task = qio_task_new(OBJECT(ioc),
+ func, opaque, destroy);
+
+ qio_channel_tls_handshake_task(ioc, task);
+
+ object_unref(OBJECT(task));
+}
+
+
+static void qio_channel_tls_init(Object *obj G_GNUC_UNUSED)
+{
+}
+
+
+static void qio_channel_tls_finalize(Object *obj)
+{
+ QIOChannelTLS *ioc = QIO_CHANNEL_TLS(obj);
+
+ object_unref(OBJECT(ioc->master));
+ qcrypto_tls_session_free(ioc->session);
+}
+
+
+static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
+ const struct iovec *iov,
+ size_t niov,
+ int **fds,
+ size_t *nfds,
+ int flags,
+ Error **errp)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+ size_t i;
+ ssize_t got = 0;
+
+ if (fds || nfds) {
+ error_setg(errp, "%s",
+ _("Cannot receive file descriptors over TLS channel"));
+ return -1;
+ }
+ if (flags) {
+ error_setg(errp, "Flags %x not supported in TLS channel", flags);
+ return -1;
+ }
+
+ for (i = 0 ; i < niov ; i++) {
+ ssize_t ret = qcrypto_tls_session_read(tioc->session,
+ iov->iov_base,
+ iov->iov_len);
+
+ if (ret < 0) {
+ if (errno == EAGAIN) {
+ if (got) {
+ return got;
+ } else {
+ return QIO_CHANNEL_ERR_BLOCK;
+ }
+ }
+
+ error_setg_errno(errp, errno, "%s",
+ _("Cannot read from TLS channel"));
+ return -1;
+ }
+ got += ret;
+ if (ret < iov->iov_len) {
+ break;
+ }
+ }
+ return got;
+}
+
+
+static ssize_t qio_channel_tls_writev(QIOChannel *ioc,
+ const struct iovec *iov,
+ size_t niov,
+ int *fds,
+ size_t nfds,
+ int flags,
+ Error **errp)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+ size_t i;
+ ssize_t done = 0;
+
+ if (fds || nfds) {
+ error_setg(errp, "%s",
+ _("Cannot send file descriptors over TLS channel"));
+ return -1;
+ }
+ if (flags) {
+ error_setg(errp, "Flags %x not supported in TLS channel", flags);
+ return -1;
+ }
+
+ for (i = 0 ; i < niov ; i++) {
+ ssize_t ret = qcrypto_tls_session_write(tioc->session,
+ iov->iov_base,
+ iov->iov_len);
+
+ if (ret <= 0) {
+ if (errno == EAGAIN) {
+ if (done) {
+ return done;
+ } else {
+ return QIO_CHANNEL_ERR_BLOCK;
+ }
+ }
+
+ error_setg_errno(errp, errno, "%s",
+ _("Cannot write to TLS channel"));
+ return -1;
+ }
+ done += ret;
+ if (ret < iov->iov_len) {
+ break;
+ }
+ }
+ return done;
+}
+
+static void qio_channel_tls_set_blocking(QIOChannel *ioc,
+ bool enabled)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+
+ qio_channel_set_blocking(tioc->master, enabled);
+}
+
+static int qio_channel_tls_close(QIOChannel *ioc,
+ Error **errp)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+
+ return qio_channel_close(tioc->master, errp);
+}
+
+static GSource *qio_channel_tls_create_watch(QIOChannel *ioc,
+ GIOCondition condition)
+{
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+
+ return qio_channel_create_watch(tioc->master, condition);
+}
+
+QCryptoTLSSession *
+qio_channel_tls_get_session(QIOChannelTLS *ioc)
+{
+ return ioc->session;
+}
+
+static void qio_channel_tls_class_init(ObjectClass *klass,
+ void *class_data G_GNUC_UNUSED)
+{
+ QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
+
+ ioc_klass->io_writev = qio_channel_tls_writev;
+ ioc_klass->io_readv = qio_channel_tls_readv;
+ ioc_klass->io_set_blocking = qio_channel_tls_set_blocking;
+ ioc_klass->io_close = qio_channel_tls_close;
+ ioc_klass->io_create_watch = qio_channel_tls_create_watch;
+}
+
+static const TypeInfo qio_channel_tls_info = {
+ .parent = TYPE_QIO_CHANNEL,
+ .name = TYPE_QIO_CHANNEL_TLS,
+ .instance_size = sizeof(QIOChannelTLS),
+ .instance_init = qio_channel_tls_init,
+ .instance_finalize = qio_channel_tls_finalize,
+ .class_init = qio_channel_tls_class_init,
+};
+
+static void qio_channel_tls_register_types(void)
+{
+ type_register_static(&qio_channel_tls_info);
+}
+
+type_init(qio_channel_tls_register_types);
--
2.1.0
next prev parent reply other threads:[~2015-04-17 14:25 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-17 14:22 [Qemu-devel] [PATCH v1 RFC 00/34] Generic support for TLS protocol & I/O channels Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 01/34] ui: remove check for failure of qemu_acl_init() Daniel P. Berrange
2015-04-17 15:56 ` Eric Blake
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 02/34] qom: document user creatable object types in help text Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 03/34] qom: create objects in two phases Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 04/34] qom: add object_new_propv / object_new_proplist constructors Daniel P. Berrange
2015-04-17 14:55 ` Paolo Bonzini
2015-04-17 15:16 ` Daniel P. Berrange
2015-04-17 16:11 ` Eric Blake
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 05/34] qom: make enum string tables const-correct Daniel P. Berrange
2015-04-17 14:56 ` Paolo Bonzini
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 06/34] qom: add a object_property_add_enum helper method Daniel P. Berrange
2015-04-17 14:56 ` Paolo Bonzini
2015-04-17 15:01 ` Paolo Bonzini
2015-04-17 15:11 ` Daniel P. Berrange
2015-04-17 15:19 ` Paolo Bonzini
2015-04-17 15:22 ` Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 07/34] qom: don't pass string table to object_get_enum method Daniel P. Berrange
2015-04-17 15:05 ` Paolo Bonzini
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 08/34] crypto: introduce new module for computing hash digests Daniel P. Berrange
2015-05-13 17:04 ` Daniel P. Berrange
2015-05-13 17:12 ` Paolo Bonzini
2015-05-13 17:21 ` Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 09/34] crypto: move built-in AES implementation into crypto/ Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 10/34] crypto: move built-in D3DES " Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 11/34] crypto: introduce generic cipher API & built-in implementation Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 12/34] crypto: add a gcrypt cipher implementation Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 13/34] crypto: add a nettle " Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 14/34] crypto: introduce new module for handling TLS credentials Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 15/34] crypto: add sanity checking of " Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 16/34] crypto: introduce new module for handling TLS sessions Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 17/34] block: convert quorum blockdrv to use crypto APIs Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 18/34] ui: convert VNC websockets " Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 19/34] block: convert qcow/qcow2 to use generic cipher API Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 20/34] ui: convert VNC " Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 21/34] io: add abstract QIOChannel classes Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 22/34] io: add helper module for creating watches on UNIX FDs Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 23/34] io: add QIOChannelSocket class Daniel P. Berrange
2015-04-17 15:28 ` Paolo Bonzini
2015-04-17 15:52 ` Daniel P. Berrange
2015-04-17 16:00 ` Paolo Bonzini
2015-04-20 7:18 ` Gerd Hoffmann
2015-04-23 12:31 ` Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 24/34] io: add QIOChannelFile class Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 25/34] io: add QIOTask class for async operations Daniel P. Berrange
2015-04-17 15:16 ` Paolo Bonzini
2015-04-17 15:49 ` Daniel P. Berrange
2015-04-17 15:57 ` Paolo Bonzini
2015-04-17 16:11 ` Daniel P. Berrange
2015-04-17 17:06 ` Paolo Bonzini
2015-04-17 17:38 ` Daniel P. Berrange
2015-04-17 14:22 ` Daniel P. Berrange [this message]
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 27/34] io: pull Buffer code out of VNC module Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 28/34] io: add QIOChannelWebsock class Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 29/34] ui: convert VNC server to use QEMUIOChannelSocket classes Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 30/34] ui: convert VNC server to use QIOChannelTLS Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 31/34] ui: convert VNC server to use QIOChannelWebsock Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 32/34] char: convert from GIOChannel to QIOChannel Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 33/34] char: don't assume telnet initialization will not block Daniel P. Berrange
2015-04-17 14:22 ` [Qemu-devel] [PATCH v1 RFC 34/34] char: introduce support for TLS encrypted TCP chardev backend Daniel P. Berrange
2015-04-17 18:27 ` Eric Blake
2015-04-23 12:32 ` Daniel P. Berrange
2015-05-04 20:07 ` Kashyap Chamarthy
2015-05-05 13:49 ` Daniel P. Berrange
2015-05-05 13:53 ` Paolo Bonzini
2015-05-05 13:56 ` Daniel P. Berrange
2015-05-05 14:54 ` Kashyap Chamarthy
2015-05-06 8:34 ` Kashyap Chamarthy
2015-05-06 10:18 ` Daniel P. Berrange
2015-05-06 11:38 ` Kashyap Chamarthy
2015-04-23 12:28 ` [Qemu-devel] [PATCH v1 RFC 00/34] Generic support for TLS protocol & I/O channels Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1429280557-8887-27-git-send-email-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=kraxel@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).