mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/berrange/tags/vnc-crypto-v9-for-upstream' into staging
Merge vnc-crypto-v9 # gpg: Signature made Tue 15 Sep 2015 15:32:38 BST using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/vnc-crypto-v9-for-upstream: ui: convert VNC server to use QCryptoTLSSession ui: fix return type for VNC I/O functions to be ssize_t crypto: introduce new module for handling TLS sessions crypto: add sanity checking of TLS x509 credentials crypto: introduce new module for TLS x509 credentials crypto: introduce new module for TLS anonymous credentials crypto: introduce new base module for TLS credentials qom: allow QOM to be linked into tools binaries crypto: move crypto objects out of libqemuutil.la tests: remove repetition in unit test object deps qapi: allow override of default enum prefix naming Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -152,6 +152,9 @@ dummy := $(call unnest-vars,, \
|
||||
qga-vss-dll-obj-y \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
crypto-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
|
||||
@@ -173,6 +176,8 @@ SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
|
||||
|
||||
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(qom-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
|
||||
|
||||
subdir-%:
|
||||
@@ -227,9 +232,9 @@ util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
|
||||
|
||||
qemu-img.o: qemu-img-cmds.h
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
|
||||
qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
|
||||
qemu-io$(EXESUF): qemu-io.o $(block-obj-y) libqemuutil.a libqemustub.a
|
||||
qemu-img$(EXESUF): qemu-img.o $(block-obj-y) $(crypto-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
|
||||
qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) $(crypto-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
|
||||
qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
|
||||
|
||||
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
|
||||
|
||||
|
||||
+10
-1
@@ -2,7 +2,6 @@
|
||||
# Common libraries for tools and emulators
|
||||
stub-obj-y = stubs/
|
||||
util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o qapi-event.o
|
||||
util-obj-y += crypto/
|
||||
|
||||
#######################################################################
|
||||
# block-obj-y is code used by both qemu system emulation and qemu-img
|
||||
@@ -21,6 +20,16 @@ block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
||||
|
||||
block-obj-m = block/
|
||||
|
||||
#######################################################################
|
||||
# crypto-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
crypto-obj-y = crypto/
|
||||
crypto-aes-obj-y = crypto/
|
||||
|
||||
#######################################################################
|
||||
# qom-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
qom-obj-y = qom/
|
||||
|
||||
######################################################################
|
||||
# smartcard
|
||||
|
||||
@@ -170,12 +170,18 @@ target-obj-y-save := $(target-obj-y)
|
||||
dummy := $(call unnest-vars,.., \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
crypto-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
target-obj-y := $(target-obj-y-save)
|
||||
all-obj-y += $(common-obj-y)
|
||||
all-obj-y += $(target-obj-y)
|
||||
all-obj-y += $(qom-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
|
||||
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
|
||||
|
||||
$(QEMU_PROG_BUILD): config-devices.mak
|
||||
|
||||
|
||||
@@ -242,7 +242,6 @@ vnc="yes"
|
||||
sparse="no"
|
||||
uuid=""
|
||||
vde=""
|
||||
vnc_tls=""
|
||||
vnc_sasl=""
|
||||
vnc_jpeg=""
|
||||
vnc_png=""
|
||||
@@ -416,6 +415,9 @@ if test "$debug_info" = "yes"; then
|
||||
LDFLAGS="-g $LDFLAGS"
|
||||
fi
|
||||
|
||||
test_cflags=""
|
||||
test_libs=""
|
||||
|
||||
# make source path absolute
|
||||
source_path=`cd "$source_path"; pwd`
|
||||
|
||||
@@ -880,10 +882,6 @@ for opt do
|
||||
;;
|
||||
--disable-strip) strip_opt="no"
|
||||
;;
|
||||
--disable-vnc-tls) vnc_tls="no"
|
||||
;;
|
||||
--enable-vnc-tls) vnc_tls="yes"
|
||||
;;
|
||||
--disable-vnc-sasl) vnc_sasl="no"
|
||||
;;
|
||||
--enable-vnc-sasl) vnc_sasl="yes"
|
||||
@@ -2249,6 +2247,19 @@ if test "$gnutls_nettle" != "no"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# libtasn1 - only for the TLS creds/session test suite
|
||||
|
||||
tasn1=yes
|
||||
if $pkg_config --exists "libtasn1"; then
|
||||
tasn1_cflags=`$pkg_config --cflags libtasn1`
|
||||
tasn1_libs=`$pkg_config --libs libtasn1`
|
||||
test_cflags="$test_cflags $tasn1_cflags"
|
||||
test_libs="$test_libs $tasn1_libs"
|
||||
else
|
||||
tasn1=no
|
||||
fi
|
||||
|
||||
|
||||
##########################################
|
||||
# VTE probe
|
||||
@@ -2393,28 +2404,6 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# VNC TLS/WS detection
|
||||
if test "$vnc" = "yes" -a "$vnc_tls" != "no" ; then
|
||||
cat > $TMPC <<EOF
|
||||
#include <gnutls/gnutls.h>
|
||||
int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
|
||||
EOF
|
||||
vnc_tls_cflags=`$pkg_config --cflags gnutls 2> /dev/null`
|
||||
vnc_tls_libs=`$pkg_config --libs gnutls 2> /dev/null`
|
||||
if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then
|
||||
if test "$vnc_tls" != "no" ; then
|
||||
vnc_tls=yes
|
||||
fi
|
||||
libs_softmmu="$vnc_tls_libs $libs_softmmu"
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags"
|
||||
else
|
||||
if test "$vnc_tls" = "yes" ; then
|
||||
feature_not_found "vnc-tls" "Install gnutls devel"
|
||||
fi
|
||||
vnc_tls=no
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# VNC SASL detection
|
||||
@@ -4574,6 +4563,7 @@ echo "GNUTLS support $gnutls"
|
||||
echo "GNUTLS hash $gnutls_hash"
|
||||
echo "GNUTLS gcrypt $gnutls_gcrypt"
|
||||
echo "GNUTLS nettle $gnutls_nettle ${gnutls_nettle+($nettle_version)}"
|
||||
echo "libtasn1 $tasn1"
|
||||
echo "VTE support $vte"
|
||||
echo "curses support $curses"
|
||||
echo "curl support $curl"
|
||||
@@ -4584,7 +4574,6 @@ echo "Block whitelist (ro) $block_drv_ro_whitelist"
|
||||
echo "VirtFS support $virtfs"
|
||||
echo "VNC support $vnc"
|
||||
if test "$vnc" = "yes" ; then
|
||||
echo "VNC TLS support $vnc_tls"
|
||||
echo "VNC SASL support $vnc_sasl"
|
||||
echo "VNC JPEG support $vnc_jpeg"
|
||||
echo "VNC PNG support $vnc_png"
|
||||
@@ -4793,9 +4782,6 @@ echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
|
||||
if test "$vnc" = "yes" ; then
|
||||
echo "CONFIG_VNC=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$vnc_tls" = "yes" ; then
|
||||
echo "CONFIG_VNC_TLS=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$vnc_sasl" = "yes" ; then
|
||||
echo "CONFIG_VNC_SASL=y" >> $config_host_mak
|
||||
fi
|
||||
@@ -4945,6 +4931,9 @@ if test "$gnutls_nettle" = "yes" ; then
|
||||
echo "CONFIG_GNUTLS_NETTLE=y" >> $config_host_mak
|
||||
echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak
|
||||
fi
|
||||
if test "$tasn1" = "yes" ; then
|
||||
echo "CONFIG_TASN1=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$vte" = "yes" ; then
|
||||
echo "CONFIG_VTE=y" >> $config_host_mak
|
||||
echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak
|
||||
@@ -5268,6 +5257,8 @@ echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||
echo "DSOSUF=$DSOSUF" >> $config_host_mak
|
||||
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak
|
||||
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
|
||||
echo "TEST_LIBS=$test_libs" >> $config_host_mak
|
||||
echo "TEST_CFLAGS=$test_cflags" >> $config_host_mak
|
||||
echo "POD2MAN=$POD2MAN" >> $config_host_mak
|
||||
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
|
||||
if test "$gcov" = "yes" ; then
|
||||
|
||||
+12
-5
@@ -1,5 +1,12 @@
|
||||
util-obj-y += init.o
|
||||
util-obj-y += hash.o
|
||||
util-obj-y += aes.o
|
||||
util-obj-y += desrfb.o
|
||||
util-obj-y += cipher.o
|
||||
crypto-obj-y = init.o
|
||||
crypto-obj-y += hash.o
|
||||
crypto-obj-y += aes.o
|
||||
crypto-obj-y += desrfb.o
|
||||
crypto-obj-y += cipher.o
|
||||
crypto-obj-y += tlscreds.o
|
||||
crypto-obj-y += tlscredsanon.o
|
||||
crypto-obj-y += tlscredsx509.o
|
||||
crypto-obj-y += tlssession.o
|
||||
|
||||
# Let the userspace emulators avoid linking gnutls/etc
|
||||
crypto-aes-obj-y = aes.o
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* QEMU crypto TLS credential support
|
||||
*
|
||||
* 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 "crypto/tlscredspriv.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define DH_BITS 2048
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
int
|
||||
qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
gnutls_dh_params_t *dh_params,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");
|
||||
|
||||
if (filename == NULL) {
|
||||
ret = gnutls_dh_params_init(dh_params);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to initialize DH parameters: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
|
||||
if (ret < 0) {
|
||||
gnutls_dh_params_deinit(*dh_params);
|
||||
*dh_params = NULL;
|
||||
error_setg(errp, "Unable to generate DH parameters: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
GError *gerr = NULL;
|
||||
gchar *contents;
|
||||
gsize len;
|
||||
gnutls_datum_t data;
|
||||
if (!g_file_get_contents(filename,
|
||||
&contents,
|
||||
&len,
|
||||
&gerr)) {
|
||||
|
||||
error_setg(errp, "%s", gerr->message);
|
||||
g_error_free(gerr);
|
||||
return -1;
|
||||
}
|
||||
data.data = (unsigned char *)contents;
|
||||
data.size = len;
|
||||
ret = gnutls_dh_params_init(dh_params);
|
||||
if (ret < 0) {
|
||||
g_free(contents);
|
||||
error_setg(errp, "Unable to initialize DH parameters: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
ret = gnutls_dh_params_import_pkcs3(*dh_params,
|
||||
&data,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
g_free(contents);
|
||||
if (ret < 0) {
|
||||
gnutls_dh_params_deinit(*dh_params);
|
||||
*dh_params = NULL;
|
||||
error_setg(errp, "Unable to load DH parameters from %s: %s",
|
||||
filename, gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
bool required,
|
||||
char **cred,
|
||||
Error **errp)
|
||||
{
|
||||
struct stat sb;
|
||||
int ret = -1;
|
||||
|
||||
if (!creds->dir) {
|
||||
if (required) {
|
||||
error_setg(errp, "Missing 'dir' property value");
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*cred = g_strdup_printf("%s/%s", creds->dir, filename);
|
||||
|
||||
if (stat(*cred, &sb) < 0) {
|
||||
if (errno == ENOENT && !required) {
|
||||
ret = 0;
|
||||
} else {
|
||||
error_setg_errno(errp, errno,
|
||||
"Unable to access credentials %s",
|
||||
*cred);
|
||||
}
|
||||
g_free(*cred);
|
||||
*cred = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
trace_qcrypto_tls_creds_get_path(creds, filename,
|
||||
*cred ? *cred : "<none>");
|
||||
ret = 0;
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_prop_set_verify(Object *obj,
|
||||
bool value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
creds->verifyPeer = value;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_tls_creds_prop_get_verify(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
return creds->verifyPeer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_prop_set_dir(Object *obj,
|
||||
const char *value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
creds->dir = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_tls_creds_prop_get_dir(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
return g_strdup(creds->dir);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_prop_set_endpoint(Object *obj,
|
||||
int value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
creds->endpoint = value;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qcrypto_tls_creds_prop_get_endpoint(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
return creds->endpoint;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_init(Object *obj)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
creds->verifyPeer = true;
|
||||
|
||||
object_property_add_bool(obj, "verify-peer",
|
||||
qcrypto_tls_creds_prop_get_verify,
|
||||
qcrypto_tls_creds_prop_set_verify,
|
||||
NULL);
|
||||
object_property_add_str(obj, "dir",
|
||||
qcrypto_tls_creds_prop_get_dir,
|
||||
qcrypto_tls_creds_prop_set_dir,
|
||||
NULL);
|
||||
object_property_add_enum(obj, "endpoint",
|
||||
"QCryptoTLSCredsEndpoint",
|
||||
QCryptoTLSCredsEndpoint_lookup,
|
||||
qcrypto_tls_creds_prop_get_endpoint,
|
||||
qcrypto_tls_creds_prop_set_endpoint,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
g_free(creds->dir);
|
||||
}
|
||||
|
||||
|
||||
static const TypeInfo qcrypto_tls_creds_info = {
|
||||
.parent = TYPE_OBJECT,
|
||||
.name = TYPE_QCRYPTO_TLS_CREDS,
|
||||
.instance_size = sizeof(QCryptoTLSCreds),
|
||||
.instance_init = qcrypto_tls_creds_init,
|
||||
.instance_finalize = qcrypto_tls_creds_finalize,
|
||||
.class_size = sizeof(QCryptoTLSCredsClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_register_types(void)
|
||||
{
|
||||
type_register_static(&qcrypto_tls_creds_info);
|
||||
}
|
||||
|
||||
|
||||
type_init(qcrypto_tls_creds_register_types);
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* QEMU crypto TLS anonymous credential support
|
||||
*
|
||||
* 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 "crypto/tlscredsanon.h"
|
||||
#include "crypto/tlscredspriv.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
|
||||
static int
|
||||
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
||||
Error **errp)
|
||||
{
|
||||
char *dhparams = NULL;
|
||||
int ret;
|
||||
int rv = -1;
|
||||
|
||||
trace_qcrypto_tls_creds_anon_load(creds,
|
||||
creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
|
||||
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
if (qcrypto_tls_creds_get_path(&creds->parent_obj,
|
||||
QCRYPTO_TLS_CREDS_DH_PARAMS,
|
||||
false, &dhparams, errp) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_anon_allocate_server_credentials(&creds->data.server);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
|
||||
&creds->parent_obj.dh_params,
|
||||
errp) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gnutls_anon_set_server_dh_params(creds->data.server,
|
||||
creds->parent_obj.dh_params);
|
||||
} else {
|
||||
ret = gnutls_anon_allocate_client_credentials(&creds->data.client);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
cleanup:
|
||||
g_free(dhparams);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds)
|
||||
{
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
||||
if (creds->data.client) {
|
||||
gnutls_anon_free_client_credentials(creds->data.client);
|
||||
creds->data.client = NULL;
|
||||
}
|
||||
} else {
|
||||
if (creds->data.server) {
|
||||
gnutls_anon_free_server_credentials(creds->data.server);
|
||||
creds->data.server = NULL;
|
||||
}
|
||||
}
|
||||
if (creds->parent_obj.dh_params) {
|
||||
gnutls_dh_params_deinit(creds->parent_obj.dh_params);
|
||||
creds->parent_obj.dh_params = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED,
|
||||
Error **errp)
|
||||
{
|
||||
error_setg(errp, "TLS credentials support requires GNUTLS");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED)
|
||||
{
|
||||
/* nada */
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_prop_set_loaded(Object *obj,
|
||||
bool value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
|
||||
|
||||
if (value) {
|
||||
qcrypto_tls_creds_anon_load(creds, errp);
|
||||
} else {
|
||||
qcrypto_tls_creds_anon_unload(creds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_tls_creds_anon_prop_get_loaded(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
|
||||
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
return creds->data.server != NULL;
|
||||
} else {
|
||||
return creds->data.client != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_tls_creds_anon_prop_get_loaded(Object *obj G_GNUC_UNUSED,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
object_property_set_bool(OBJECT(uc), true, "loaded", errp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_init(Object *obj)
|
||||
{
|
||||
object_property_add_bool(obj, "loaded",
|
||||
qcrypto_tls_creds_anon_prop_get_loaded,
|
||||
qcrypto_tls_creds_anon_prop_set_loaded,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
|
||||
|
||||
qcrypto_tls_creds_anon_unload(creds);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
||||
|
||||
ucc->complete = qcrypto_tls_creds_anon_complete;
|
||||
}
|
||||
|
||||
|
||||
static const TypeInfo qcrypto_tls_creds_anon_info = {
|
||||
.parent = TYPE_QCRYPTO_TLS_CREDS,
|
||||
.name = TYPE_QCRYPTO_TLS_CREDS_ANON,
|
||||
.instance_size = sizeof(QCryptoTLSCredsAnon),
|
||||
.instance_init = qcrypto_tls_creds_anon_init,
|
||||
.instance_finalize = qcrypto_tls_creds_anon_finalize,
|
||||
.class_size = sizeof(QCryptoTLSCredsAnonClass),
|
||||
.class_init = qcrypto_tls_creds_anon_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_register_types(void)
|
||||
{
|
||||
type_register_static(&qcrypto_tls_creds_anon_info);
|
||||
}
|
||||
|
||||
|
||||
type_init(qcrypto_tls_creds_anon_register_types);
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* QEMU crypto TLS credential support private helpers
|
||||
*
|
||||
* 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 QCRYPTO_TLSCRED_PRIV_H__
|
||||
#define QCRYPTO_TLSCRED_PRIV_H__
|
||||
|
||||
#include "crypto/tlscreds.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
int qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
bool required,
|
||||
char **cred,
|
||||
Error **errp);
|
||||
|
||||
int qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
gnutls_dh_params_t *dh_params,
|
||||
Error **errp);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* QCRYPTO_TLSCRED_PRIV_H__ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -236,6 +236,7 @@ both fields like this:
|
||||
=== Enumeration types ===
|
||||
|
||||
Usage: { 'enum': STRING, 'data': ARRAY-OF-STRING }
|
||||
{ 'enum': STRING, '*prefix': STRING, 'data': ARRAY-OF-STRING }
|
||||
|
||||
An enumeration type is a dictionary containing a single 'data' key
|
||||
whose value is a list of strings. An example enumeration is:
|
||||
@@ -247,6 +248,13 @@ useful. The list of strings should be lower case; if an enum name
|
||||
represents multiple words, use '-' between words. The string 'max' is
|
||||
not allowed as an enum value, and values should not be repeated.
|
||||
|
||||
The enum constants will be named by using a heuristic to turn the
|
||||
type name into a set of underscore separated words. For the example
|
||||
above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name
|
||||
of 'MY_ENUM_VALUE1' for the first value. If the default heuristic
|
||||
does not result in a desirable name, the optional 'prefix' field
|
||||
can be used when defining the enum.
|
||||
|
||||
The enumeration values are passed as strings over the Client JSON
|
||||
Protocol, but are encoded as C enum integral values in generated code.
|
||||
While the C code starts numbering at 0, it is better to use explicit
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* QEMU crypto TLS credential support
|
||||
*
|
||||
* 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 QCRYPTO_TLSCRED_H__
|
||||
#define QCRYPTO_TLSCRED_H__
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
#define TYPE_QCRYPTO_TLS_CREDS "tls-creds"
|
||||
#define QCRYPTO_TLS_CREDS(obj) \
|
||||
OBJECT_CHECK(QCryptoTLSCreds, (obj), TYPE_QCRYPTO_TLS_CREDS)
|
||||
|
||||
typedef struct QCryptoTLSCreds QCryptoTLSCreds;
|
||||
typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass;
|
||||
|
||||
#define QCRYPTO_TLS_CREDS_DH_PARAMS "dh-params.pem"
|
||||
|
||||
|
||||
/**
|
||||
* QCryptoTLSCreds:
|
||||
*
|
||||
* The QCryptoTLSCreds object is an abstract base for different
|
||||
* types of TLS handshake credentials. Most commonly the
|
||||
* QCryptoTLSCredsX509 subclass will be used to provide x509
|
||||
* certificate credentials.
|
||||
*/
|
||||
|
||||
struct QCryptoTLSCreds {
|
||||
Object parent_obj;
|
||||
char *dir;
|
||||
QCryptoTLSCredsEndpoint endpoint;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
gnutls_dh_params_t dh_params;
|
||||
#endif
|
||||
bool verifyPeer;
|
||||
};
|
||||
|
||||
|
||||
struct QCryptoTLSCredsClass {
|
||||
ObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#endif /* QCRYPTO_TLSCRED_H__ */
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* QEMU crypto TLS anonymous credential support
|
||||
*
|
||||
* 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 QCRYPTO_TLSCRED_ANON_H__
|
||||
#define QCRYPTO_TLSCRED_ANON_H__
|
||||
|
||||
#include "crypto/tlscreds.h"
|
||||
|
||||
#define TYPE_QCRYPTO_TLS_CREDS_ANON "tls-creds-anon"
|
||||
#define QCRYPTO_TLS_CREDS_ANON(obj) \
|
||||
OBJECT_CHECK(QCryptoTLSCredsAnon, (obj), TYPE_QCRYPTO_TLS_CREDS_ANON)
|
||||
|
||||
|
||||
typedef struct QCryptoTLSCredsAnon QCryptoTLSCredsAnon;
|
||||
typedef struct QCryptoTLSCredsAnonClass QCryptoTLSCredsAnonClass;
|
||||
|
||||
/**
|
||||
* QCryptoTLSCredsAnon:
|
||||
*
|
||||
* The QCryptoTLSCredsAnon object provides a representation
|
||||
* of anonymous credentials used perform a TLS handshake.
|
||||
* This is primarily provided for backwards compatibility and
|
||||
* its use is discouraged as it has poor security characteristics
|
||||
* due to lacking MITM attack protection amongst other problems.
|
||||
*
|
||||
* This is a user creatable object, which can be instantiated
|
||||
* via object_new_propv():
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating anonymous TLS credential objects in code</title>
|
||||
* <programlisting>
|
||||
* Object *obj;
|
||||
* Error *err = NULL;
|
||||
* obj = object_new_propv(TYPE_QCRYPTO_TLS_CREDS_ANON,
|
||||
* "tlscreds0",
|
||||
* &err,
|
||||
* "endpoint", "server",
|
||||
* "dir", "/path/x509/cert/dir",
|
||||
* "verify-peer", "yes",
|
||||
* NULL);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* Or via QMP:
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating anonymous TLS credential objects via QMP</title>
|
||||
* <programlisting>
|
||||
* {
|
||||
* "execute": "object-add", "arguments": {
|
||||
* "id": "tlscreds0",
|
||||
* "qom-type": "tls-creds-anon",
|
||||
* "props": {
|
||||
* "endpoint": "server",
|
||||
* "dir": "/path/to/x509/cert/dir",
|
||||
* "verify-peer": false
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
*
|
||||
* Or via the CLI:
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating anonymous TLS credential objects via CLI</title>
|
||||
* <programlisting>
|
||||
* qemu-system-x86_64 -object tls-creds-anon,id=tlscreds0,\
|
||||
* endpoint=server,verify-peer=off,\
|
||||
* dir=/path/to/x509/certdir/
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
struct QCryptoTLSCredsAnon {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
union {
|
||||
gnutls_anon_server_credentials_t server;
|
||||
gnutls_anon_client_credentials_t client;
|
||||
} data;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct QCryptoTLSCredsAnonClass {
|
||||
QCryptoTLSCredsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#endif /* QCRYPTO_TLSCRED_H__ */
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* QEMU crypto TLS x509 credential support
|
||||
*
|
||||
* 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 QCRYPTO_TLSCRED_X509_H__
|
||||
#define QCRYPTO_TLSCRED_X509_H__
|
||||
|
||||
#include "crypto/tlscreds.h"
|
||||
|
||||
#define TYPE_QCRYPTO_TLS_CREDS_X509 "tls-creds-x509"
|
||||
#define QCRYPTO_TLS_CREDS_X509(obj) \
|
||||
OBJECT_CHECK(QCryptoTLSCredsX509, (obj), TYPE_QCRYPTO_TLS_CREDS_X509)
|
||||
|
||||
typedef struct QCryptoTLSCredsX509 QCryptoTLSCredsX509;
|
||||
typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class;
|
||||
|
||||
#define QCRYPTO_TLS_CREDS_X509_CA_CERT "ca-cert.pem"
|
||||
#define QCRYPTO_TLS_CREDS_X509_CA_CRL "ca-crl.pem"
|
||||
#define QCRYPTO_TLS_CREDS_X509_SERVER_KEY "server-key.pem"
|
||||
#define QCRYPTO_TLS_CREDS_X509_SERVER_CERT "server-cert.pem"
|
||||
#define QCRYPTO_TLS_CREDS_X509_CLIENT_KEY "client-key.pem"
|
||||
#define QCRYPTO_TLS_CREDS_X509_CLIENT_CERT "client-cert.pem"
|
||||
|
||||
|
||||
/**
|
||||
* QCryptoTLSCredsX509:
|
||||
*
|
||||
* The QCryptoTLSCredsX509 object provides a representation
|
||||
* of x509 credentials used to perform a TLS handshake.
|
||||
*
|
||||
* This is a user creatable object, which can be instantiated
|
||||
* via object_new_propv():
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating x509 TLS credential objects in code</title>
|
||||
* <programlisting>
|
||||
* Object *obj;
|
||||
* Error *err = NULL;
|
||||
* obj = object_new_propv(TYPE_QCRYPTO_TLS_CREDS_X509,
|
||||
* "tlscreds0",
|
||||
* &err,
|
||||
* "endpoint", "server",
|
||||
* "dir", "/path/x509/cert/dir",
|
||||
* "verify-peer", "yes",
|
||||
* NULL);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* Or via QMP:
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating x509 TLS credential objects via QMP</title>
|
||||
* <programlisting>
|
||||
* {
|
||||
* "execute": "object-add", "arguments": {
|
||||
* "id": "tlscreds0",
|
||||
* "qom-type": "tls-creds-x509",
|
||||
* "props": {
|
||||
* "endpoint": "server",
|
||||
* "dir": "/path/to/x509/cert/dir",
|
||||
* "verify-peer": false
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
*
|
||||
* Or via the CLI:
|
||||
*
|
||||
* <example>
|
||||
* <title>Creating x509 TLS credential objects via CLI</title>
|
||||
* <programlisting>
|
||||
* qemu-system-x86_64 -object tls-creds-x509,id=tlscreds0,\
|
||||
* endpoint=server,verify-peer=off,\
|
||||
* dir=/path/to/x509/certdir/
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
*/
|
||||
|
||||
struct QCryptoTLSCredsX509 {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
gnutls_certificate_credentials_t data;
|
||||
#endif
|
||||
bool sanityCheck;
|
||||
};
|
||||
|
||||
|
||||
struct QCryptoTLSCredsX509Class {
|
||||
QCryptoTLSCredsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#endif /* QCRYPTO_TLSCRED_X509_H__ */
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* QEMU crypto TLS session support
|
||||
*
|
||||
* 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 QCRYPTO_TLS_SESSION_H__
|
||||
#define QCRYPTO_TLS_SESSION_H__
|
||||
|
||||
#include "crypto/tlscreds.h"
|
||||
|
||||
/**
|
||||
* QCryptoTLSSession:
|
||||
*
|
||||
* The QCryptoTLSSession object encapsulates the
|
||||
* logic to integrate with a TLS providing library such
|
||||
* as GNUTLS, to setup and run TLS sessions.
|
||||
*
|
||||
* The API is designed such that it has no assumption about
|
||||
* the type of transport it is running over. It may be a
|
||||
* traditional TCP socket, or something else entirely. The
|
||||
* only requirement is a full-duplex stream of some kind.
|
||||
*
|
||||
* <example>
|
||||
* <title>Using TLS session objects</title>
|
||||
* <programlisting>
|
||||
* static ssize_t mysock_send(const char *buf, size_t len,
|
||||
* void *opaque)
|
||||
* {
|
||||
* int fd = GPOINTER_TO_INT(opaque);
|
||||
*
|
||||
* return write(*fd, buf, len);
|
||||
* }
|
||||
*
|
||||
* static ssize_t mysock_recv(const char *buf, size_t len,
|
||||
* void *opaque)
|
||||
* {
|
||||
* int fd = GPOINTER_TO_INT(opaque);
|
||||
*
|
||||
* return read(*fd, buf, len);
|
||||
* }
|
||||
*
|
||||
* static int mysock_run_tls(int sockfd,
|
||||
* QCryptoTLSCreds *creds,
|
||||
* Error *erp)
|
||||
* {
|
||||
* QCryptoTLSSession *sess;
|
||||
*
|
||||
* sess = qcrypto_tls_session_new(creds,
|
||||
* "vnc.example.com",
|
||||
* NULL,
|
||||
* QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
|
||||
* errp);
|
||||
* if (sess == NULL) {
|
||||
* return -1;
|
||||
* }
|
||||
*
|
||||
* qcrypto_tls_session_set_callbacks(sess,
|
||||
* mysock_send,
|
||||
* mysock_recv
|
||||
* GINT_TO_POINTER(fd));
|
||||
*
|
||||
* while (1) {
|
||||
* if (qcrypto_tls_session_handshake(sess, errp) < 0) {
|
||||
* qcrypto_tls_session_free(sess);
|
||||
* return -1;
|
||||
* }
|
||||
*
|
||||
* switch(qcrypto_tls_session_get_handshake_status(sess)) {
|
||||
* case QCRYPTO_TLS_HANDSHAKE_COMPLETE:
|
||||
* if (qcrypto_tls_session_check_credentials(sess, errp) < )) {
|
||||
* qcrypto_tls_session_free(sess);
|
||||
* return -1;
|
||||
* }
|
||||
* goto done;
|
||||
* case QCRYPTO_TLS_HANDSHAKE_RECVING:
|
||||
* ...wait for GIO_IN event on fd...
|
||||
* break;
|
||||
* case QCRYPTO_TLS_HANDSHAKE_SENDING:
|
||||
* ...wait for GIO_OUT event on fd...
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* done:
|
||||
*
|
||||
* ....send/recv payload data on sess...
|
||||
*
|
||||
* qcrypto_tls_session_free(sess):
|
||||
* }
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*/
|
||||
|
||||
typedef struct QCryptoTLSSession QCryptoTLSSession;
|
||||
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_new:
|
||||
* @creds: pointer to a TLS credentials object
|
||||
* @hostname: optional hostname to validate
|
||||
* @aclname: optional ACL to validate peer credentials against
|
||||
* @endpoint: role of the TLS session, client or server
|
||||
* @errp: pointer to an uninitialized error object
|
||||
*
|
||||
* Create a new TLS session object that will be used to
|
||||
* negotiate a TLS session over an arbitrary data channel.
|
||||
* The session object can operate as either the server or
|
||||
* client, according to the value of the @endpoint argument.
|
||||
*
|
||||
* For clients, the @hostname parameter should hold the full
|
||||
* unmodified hostname as requested by the user. This will
|
||||
* be used to verify the against the hostname reported in
|
||||
* the server's credentials (aka x509 certificate).
|
||||
*
|
||||
* The @aclname parameter (optionally) specifies the name
|
||||
* of an access control list that will be used to validate
|
||||
* the peer's credentials. For x509 credentials, the ACL
|
||||
* will be matched against the CommonName shown in the peer's
|
||||
* certificate. If the session is acting as a server, setting
|
||||
* an ACL will require that the client provide a validate
|
||||
* x509 client certificate.
|
||||
*
|
||||
* After creating the session object, the I/O callbacks
|
||||
* must be set using the qcrypto_tls_session_set_callbacks()
|
||||
* method. A TLS handshake sequence must then be completed
|
||||
* using qcrypto_tls_session_handshake(), before payload
|
||||
* data is permitted to be sent/received.
|
||||
*
|
||||
* The session object must be released by calling
|
||||
* qcrypto_tls_session_free() when no longer required
|
||||
*
|
||||
* Returns: a TLS session object, or NULL on error.
|
||||
*/
|
||||
QCryptoTLSSession *qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
const char *hostname,
|
||||
const char *aclname,
|
||||
QCryptoTLSCredsEndpoint endpoint,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_free:
|
||||
* @sess: the TLS session object
|
||||
*
|
||||
* Release all memory associated with the TLS session
|
||||
* object previously allocated by qcrypto_tls_session_new()
|
||||
*/
|
||||
void qcrypto_tls_session_free(QCryptoTLSSession *sess);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_check_credentials:
|
||||
* @sess: the TLS session object
|
||||
* @errp: pointer to an uninitialized error object
|
||||
*
|
||||
* Validate the peer's credentials after a successful
|
||||
* TLS handshake. It is an error to call this before
|
||||
* qcrypto_tls_session_get_handshake_status() returns
|
||||
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
|
||||
*
|
||||
* Returns 0 if the credentials validated, -1 on error
|
||||
*/
|
||||
int qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess,
|
||||
Error **errp);
|
||||
|
||||
typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const char *buf,
|
||||
size_t len,
|
||||
void *opaque);
|
||||
typedef ssize_t (*QCryptoTLSSessionReadFunc)(char *buf,
|
||||
size_t len,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_set_callbacks:
|
||||
* @sess: the TLS session object
|
||||
* @writeFunc: callback for sending data
|
||||
* @readFunc: callback to receiving data
|
||||
* @opaque: data to pass to callbacks
|
||||
*
|
||||
* Sets the callback functions that are to be used for sending
|
||||
* and receiving data on the underlying data channel. Typically
|
||||
* the callbacks to write/read to/from a TCP socket, but there
|
||||
* is no assumption made about the type of channel used.
|
||||
*
|
||||
* The @writeFunc callback will be passed the encrypted
|
||||
* data to send to the remote peer.
|
||||
*
|
||||
* The @readFunc callback will be passed a pointer to fill
|
||||
* with encrypted data received from the remote peer
|
||||
*/
|
||||
void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
|
||||
QCryptoTLSSessionWriteFunc writeFunc,
|
||||
QCryptoTLSSessionReadFunc readFunc,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_write:
|
||||
* @sess: the TLS session object
|
||||
* @buf: the plain text to send
|
||||
* @len: the length of @buf
|
||||
*
|
||||
* Encrypt @len bytes of the data in @buf and send
|
||||
* it to the remote peer using the callback previously
|
||||
* registered with qcrypto_tls_session_set_callbacks()
|
||||
*
|
||||
* It is an error to call this before
|
||||
* qcrypto_tls_session_get_handshake_status() returns
|
||||
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
|
||||
*
|
||||
* Returns: the number of bytes sent, or -1 on error
|
||||
*/
|
||||
ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess,
|
||||
const char *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_read:
|
||||
* @sess: the TLS session object
|
||||
* @buf: to fill with plain text received
|
||||
* @len: the length of @buf
|
||||
*
|
||||
* Receive up to @len bytes of data from the remote peer
|
||||
* using the callback previously registered with
|
||||
* qcrypto_tls_session_set_callbacks(), decrypt it and
|
||||
* store it in @buf.
|
||||
*
|
||||
* It is an error to call this before
|
||||
* qcrypto_tls_session_get_handshake_status() returns
|
||||
* QCRYPTO_TLS_HANDSHAKE_COMPLETE
|
||||
*
|
||||
* Returns: the number of bytes received, or -1 on error
|
||||
*/
|
||||
ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess,
|
||||
char *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_handshake:
|
||||
* @sess: the TLS session object
|
||||
* @errp: pointer to an uninitialized error object
|
||||
*
|
||||
* Start, or continue, a TLS handshake sequence. If
|
||||
* the underlying data channel is non-blocking, then
|
||||
* this method may return control before the handshake
|
||||
* is complete. On non-blocking channels the
|
||||
* qcrypto_tls_session_get_handshake_status() method
|
||||
* should be used to determine whether the handshake
|
||||
* has completed, or is waiting to send or receive
|
||||
* data. In the latter cases, the caller should setup
|
||||
* an event loop watch and call this method again
|
||||
* once the underlying data channel is ready to read
|
||||
* or write again
|
||||
*/
|
||||
int qcrypto_tls_session_handshake(QCryptoTLSSession *sess,
|
||||
Error **errp);
|
||||
|
||||
typedef enum {
|
||||
QCRYPTO_TLS_HANDSHAKE_COMPLETE,
|
||||
QCRYPTO_TLS_HANDSHAKE_SENDING,
|
||||
QCRYPTO_TLS_HANDSHAKE_RECVING,
|
||||
} QCryptoTLSSessionHandshakeStatus;
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_get_handshake_status:
|
||||
* @sess: the TLS session object
|
||||
*
|
||||
* Check the status of the TLS handshake. This
|
||||
* is used with non-blocking data channels to
|
||||
* determine whether the handshake is waiting
|
||||
* to send or receive further data to/from the
|
||||
* remote peer.
|
||||
*
|
||||
* Once this returns QCRYPTO_TLS_HANDSHAKE_COMPLETE
|
||||
* it is permitted to send/receive payload data on
|
||||
* the channel
|
||||
*/
|
||||
QCryptoTLSSessionHandshakeStatus
|
||||
qcrypto_tls_session_get_handshake_status(QCryptoTLSSession *sess);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_get_key_size:
|
||||
* @sess: the TLS session object
|
||||
* @errp: pointer to an uninitialized error object
|
||||
*
|
||||
* Check the size of the data channel encryption key
|
||||
*
|
||||
* Returns: the length in bytes of the encryption key
|
||||
* or -1 on error
|
||||
*/
|
||||
int qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qcrypto_tls_session_get_peer_name:
|
||||
* @sess: the TLS session object
|
||||
*
|
||||
* Get the identified name of the remote peer. If the
|
||||
* TLS session was negotiated using x509 certificate
|
||||
* credentials, this will return the CommonName from
|
||||
* the peer's certificate. If no identified name is
|
||||
* available it will return NULL.
|
||||
*
|
||||
* The returned data must be released with g_free()
|
||||
* when no longer required.
|
||||
*
|
||||
* Returns: the peer's name or NULL.
|
||||
*/
|
||||
char *qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess);
|
||||
|
||||
#endif /* QCRYPTO_TLS_SESSION_H__ */
|
||||
@@ -5,6 +5,9 @@
|
||||
# QAPI common definitions
|
||||
{ 'include': 'qapi/common.json' }
|
||||
|
||||
# QAPI crypto definitions
|
||||
{ 'include': 'qapi/crypto.json' }
|
||||
|
||||
# QAPI block definitions
|
||||
{ 'include': 'qapi/block.json' }
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# -*- Mode: Python -*-
|
||||
#
|
||||
# QAPI crypto definitions
|
||||
|
||||
##
|
||||
# QCryptoTLSCredsEndpoint:
|
||||
#
|
||||
# The type of network endpoint that will be using the credentials.
|
||||
# Most types of credential require different setup / structures
|
||||
# depending on whether they will be used in a server versus a
|
||||
# client.
|
||||
#
|
||||
# @client: the network endpoint is acting as the client
|
||||
#
|
||||
# @server: the network endpoint is acting as the server
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'enum': 'QCryptoTLSCredsEndpoint',
|
||||
'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT',
|
||||
'data': ['client', 'server']}
|
||||
+73
-2
@@ -1217,8 +1217,9 @@ By definition the Websocket port is 5700+@var{display}. If @var{host} is
|
||||
specified connections will only be allowed from this host.
|
||||
As an alternative the Websocket port could be specified by using
|
||||
@code{websocket}=@var{port}.
|
||||
TLS encryption for the Websocket connection is supported if the required
|
||||
certificates are specified with the VNC option @option{x509}.
|
||||
If no TLS credentials are provided, the websocket connection runs in
|
||||
unencrypted mode. If TLS credentials are provided, the websocket connection
|
||||
requires encrypted client connections.
|
||||
|
||||
@item password
|
||||
|
||||
@@ -1239,6 +1240,20 @@ date and time).
|
||||
You can also use keywords "now" or "never" for the expiration time to
|
||||
allow <protocol> password to expire immediately or never expire.
|
||||
|
||||
@item tls-creds=@var{ID}
|
||||
|
||||
Provides the ID of a set of TLS credentials to use to secure the
|
||||
VNC server. They will apply to both the normal VNC server socket
|
||||
and the websocket socket (if enabled). Setting TLS credentials
|
||||
will cause the VNC server socket to enable the VeNCrypt auth
|
||||
mechanism. The credentials should have been previously created
|
||||
using the @option{-object tls-creds} argument.
|
||||
|
||||
The @option{tls-creds} parameter obsoletes the @option{tls},
|
||||
@option{x509}, and @option{x509verify} options, and as such
|
||||
it is not permitted to set both new and old type options at
|
||||
the same time.
|
||||
|
||||
@item tls
|
||||
|
||||
Require that client use TLS when communicating with the VNC server. This
|
||||
@@ -1246,6 +1261,9 @@ uses anonymous TLS credentials so is susceptible to a man-in-the-middle
|
||||
attack. It is recommended that this option be combined with either the
|
||||
@option{x509} or @option{x509verify} options.
|
||||
|
||||
This option is now deprecated in favor of using the @option{tls-creds}
|
||||
argument.
|
||||
|
||||
@item x509=@var{/path/to/certificate/dir}
|
||||
|
||||
Valid if @option{tls} is specified. Require that x509 credentials are used
|
||||
@@ -1255,6 +1273,9 @@ to provide authentication of the client when this is used. The path following
|
||||
this option specifies where the x509 certificates are to be loaded from.
|
||||
See the @ref{vnc_security} section for details on generating certificates.
|
||||
|
||||
This option is now deprecated in favour of using the @option{tls-creds}
|
||||
argument.
|
||||
|
||||
@item x509verify=@var{/path/to/certificate/dir}
|
||||
|
||||
Valid if @option{tls} is specified. Require that x509 credentials are used
|
||||
@@ -1268,6 +1289,9 @@ path following this option specifies where the x509 certificates are to
|
||||
be loaded from. See the @ref{vnc_security} section for details on generating
|
||||
certificates.
|
||||
|
||||
This option is now deprecated in favour of using the @option{tls-creds}
|
||||
argument.
|
||||
|
||||
@item sasl
|
||||
|
||||
Require that the client use SASL to authenticate with the VNC server.
|
||||
@@ -3571,6 +3595,53 @@ the @option{virtio-rng} device. The @option{chardev} parameter is
|
||||
the unique ID of a character device backend that provides the connection
|
||||
to the RNG daemon.
|
||||
|
||||
@item -object tls-creds-anon,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off}
|
||||
|
||||
Creates a TLS anonymous credentials object, which can be used to provide
|
||||
TLS support on network backends. The @option{id} parameter is a unique
|
||||
ID which network backends will use to access the credentials. The
|
||||
@option{endpoint} is either @option{server} or @option{client} depending
|
||||
on whether the QEMU network backend that uses the credentials will be
|
||||
acting as a client or as a server. If @option{verify-peer} is enabled
|
||||
(the default) then once the handshake is completed, the peer credentials
|
||||
will be verified, though this is a no-op for anonymous credentials.
|
||||
|
||||
The @var{dir} parameter tells QEMU where to find the credential
|
||||
files. For server endpoints, this directory may contain a file
|
||||
@var{dh-params.pem} providing diffie-hellman parameters to use
|
||||
for the TLS server. If the file is missing, QEMU will generate
|
||||
a set of DH parameters at startup. This is a computationally
|
||||
expensive operation that consumes random pool entropy, so it is
|
||||
recommended that a persistent set of parameters be generated
|
||||
upfront and saved.
|
||||
|
||||
@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off}
|
||||
|
||||
Creates a TLS anonymous credentials object, which can be used to provide
|
||||
TLS support on network backends. The @option{id} parameter is a unique
|
||||
ID which network backends will use to access the credentials. The
|
||||
@option{endpoint} is either @option{server} or @option{client} depending
|
||||
on whether the QEMU network backend that uses the credentials will be
|
||||
acting as a client or as a server. If @option{verify-peer} is enabled
|
||||
(the default) then once the handshake is completed, the peer credentials
|
||||
will be verified. With x509 certificates, this implies that the clients
|
||||
must be provided with valid client certificates too.
|
||||
|
||||
The @var{dir} parameter tells QEMU where to find the credential
|
||||
files. For server endpoints, this directory may contain a file
|
||||
@var{dh-params.pem} providing diffie-hellman parameters to use
|
||||
for the TLS server. If the file is missing, QEMU will generate
|
||||
a set of DH parameters at startup. This is a computationally
|
||||
expensive operation that consumes random pool entropy, so it is
|
||||
recommended that a persistent set of parameters be generated
|
||||
upfront and saved.
|
||||
|
||||
For x509 certificate credentials the directory will contain further files
|
||||
providing the x509 certificates. The certificates must be stored
|
||||
in PEM format, in filenames @var{ca-cert.pem}, @var{ca-crl.pem} (optional),
|
||||
@var{server-cert.pem} (only servers), @var{server-key.pem} (only servers),
|
||||
@var{client-cert.pem} (only clients), and @var{client-key.pem} (only clients).
|
||||
|
||||
@end table
|
||||
|
||||
ETEXI
|
||||
|
||||
+4
-3
@@ -1,3 +1,4 @@
|
||||
common-obj-y = object.o container.o qom-qobject.o
|
||||
common-obj-y += cpu.o
|
||||
common-obj-y += object_interfaces.o
|
||||
qom-obj-y = object.o container.o qom-qobject.o
|
||||
qom-obj-y += object_interfaces.o
|
||||
|
||||
common-obj-y = cpu.o
|
||||
|
||||
@@ -101,20 +101,20 @@ struct %(name)s {
|
||||
|
||||
return ret
|
||||
|
||||
def generate_enum_lookup(name, values):
|
||||
def generate_enum_lookup(name, values, prefix=None):
|
||||
ret = mcgen('''
|
||||
|
||||
const char *const %(name)s_lookup[] = {
|
||||
''',
|
||||
name=c_name(name))
|
||||
for value in values:
|
||||
index = c_enum_const(name, value)
|
||||
index = c_enum_const(name, value, prefix)
|
||||
ret += mcgen('''
|
||||
[%(index)s] = "%(value)s",
|
||||
''',
|
||||
index = index, value = value)
|
||||
|
||||
max_index = c_enum_const(name, 'MAX')
|
||||
max_index = c_enum_const(name, 'MAX', prefix)
|
||||
ret += mcgen('''
|
||||
[%(max_index)s] = NULL,
|
||||
};
|
||||
@@ -122,7 +122,7 @@ const char *const %(name)s_lookup[] = {
|
||||
max_index=max_index)
|
||||
return ret
|
||||
|
||||
def generate_enum(name, values):
|
||||
def generate_enum(name, values, prefix=None):
|
||||
name = c_name(name)
|
||||
lookup_decl = mcgen('''
|
||||
|
||||
@@ -141,7 +141,7 @@ typedef enum %(name)s {
|
||||
|
||||
i = 0
|
||||
for value in enum_values:
|
||||
enum_full_value = c_enum_const(name, value)
|
||||
enum_full_value = c_enum_const(name, value, prefix)
|
||||
enum_decl += mcgen('''
|
||||
%(enum_full_value)s = %(i)d,
|
||||
''',
|
||||
@@ -348,9 +348,11 @@ for expr in exprs:
|
||||
if expr.has_key('struct'):
|
||||
ret += generate_fwd_struct(expr['struct'])
|
||||
elif expr.has_key('enum'):
|
||||
ret += generate_enum(expr['enum'], expr['data'])
|
||||
ret += generate_enum(expr['enum'], expr['data'],
|
||||
expr.get('prefix'))
|
||||
ret += generate_fwd_enum_struct(expr['enum'])
|
||||
fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
|
||||
fdef.write(generate_enum_lookup(expr['enum'], expr['data'],
|
||||
expr.get('prefix')))
|
||||
elif expr.has_key('union'):
|
||||
ret += generate_fwd_struct(expr['union'])
|
||||
enum_define = discriminator_find_enum_define(expr)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user