diff options
Diffstat (limited to 'qemu/tests/test-io-channel-tls.c')
-rw-r--r-- | qemu/tests/test-io-channel-tls.c | 340 |
1 files changed, 0 insertions, 340 deletions
diff --git a/qemu/tests/test-io-channel-tls.c b/qemu/tests/test-io-channel-tls.c deleted file mode 100644 index 3c361a7be..000000000 --- a/qemu/tests/test-io-channel-tls.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * QEMU I/O channel TLS test - * - * 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.1 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/>. - * - * Author: Daniel P. Berrange <berrange@redhat.com> - */ - - -#include "qemu/osdep.h" - -#include "crypto-tls-x509-helpers.h" -#include "io/channel-tls.h" -#include "io/channel-socket.h" -#include "io-channel-helpers.h" -#include "crypto/tlscredsx509.h" -#include "qemu/acl.h" -#include "qom/object_interfaces.h" - -#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT - -#define WORKDIR "tests/test-io-channel-tls-work/" -#define KEYFILE WORKDIR "key-ctx.pem" - -struct QIOChannelTLSTestData { - const char *servercacrt; - const char *clientcacrt; - const char *servercrt; - const char *clientcrt; - bool expectServerFail; - bool expectClientFail; - const char *hostname; - const char *const *wildcards; -}; - -struct QIOChannelTLSHandshakeData { - bool finished; - bool failed; -}; - -static void test_tls_handshake_done(Object *source, - Error *err, - gpointer opaque) -{ - struct QIOChannelTLSHandshakeData *data = opaque; - - data->finished = true; - data->failed = err != NULL; -} - - -static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint, - const char *certdir, - Error **errp) -{ - Object *parent = object_get_objects_root(); - Object *creds = object_new_with_props( - TYPE_QCRYPTO_TLS_CREDS_X509, - parent, - (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ? - "testtlscredsserver" : "testtlscredsclient"), - errp, - "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ? - "server" : "client"), - "dir", certdir, - "verify-peer", "yes", - /* We skip initial sanity checks here because we - * want to make sure that problems are being - * detected at the TLS session validation stage, - * and the test-crypto-tlscreds test already - * validate the sanity check code. - */ - "sanity-check", "no", - NULL - ); - - if (*errp) { - return NULL; - } - return QCRYPTO_TLS_CREDS(creds); -} - - -/* - * This tests validation checking of peer certificates - * - * This is replicating the checks that are done for an - * active TLS session after handshake completes. To - * simulate that we create our TLS contexts, skipping - * sanity checks. When then get a socketpair, and - * initiate a TLS session across them. Finally do - * do actual cert validation tests - */ -static void test_io_channel_tls(const void *opaque) -{ - struct QIOChannelTLSTestData *data = - (struct QIOChannelTLSTestData *)opaque; - QCryptoTLSCreds *clientCreds; - QCryptoTLSCreds *serverCreds; - QIOChannelTLS *clientChanTLS; - QIOChannelTLS *serverChanTLS; - QIOChannelSocket *clientChanSock; - QIOChannelSocket *serverChanSock; - qemu_acl *acl; - const char * const *wildcards; - int channel[2]; - struct QIOChannelTLSHandshakeData clientHandshake = { false, false }; - struct QIOChannelTLSHandshakeData serverHandshake = { false, false }; - Error *err = NULL; - QIOChannelTest *test; - GMainContext *mainloop; - - /* We'll use this for our fake client-server connection */ - g_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == 0); - -#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/" -#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/" - mkdir(CLIENT_CERT_DIR, 0700); - mkdir(SERVER_CERT_DIR, 0700); - - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY); - - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT); - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY); - - g_assert(link(data->servercacrt, - SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0); - g_assert(link(data->servercrt, - SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0); - g_assert(link(KEYFILE, - SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0); - - g_assert(link(data->clientcacrt, - CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0); - g_assert(link(data->clientcrt, - CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0); - g_assert(link(KEYFILE, - CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0); - - clientCreds = test_tls_creds_create( - QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, - CLIENT_CERT_DIR, - &err); - g_assert(clientCreds != NULL); - - serverCreds = test_tls_creds_create( - QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, - SERVER_CERT_DIR, - &err); - g_assert(serverCreds != NULL); - - acl = qemu_acl_init("channeltlsacl"); - qemu_acl_reset(acl); - wildcards = data->wildcards; - while (wildcards && *wildcards) { - qemu_acl_append(acl, 0, *wildcards); - wildcards++; - } - - clientChanSock = qio_channel_socket_new_fd( - channel[0], &err); - g_assert(clientChanSock != NULL); - serverChanSock = qio_channel_socket_new_fd( - channel[1], &err); - g_assert(serverChanSock != NULL); - - /* - * We have an evil loop to do the handshake in a single - * thread, so we need these non-blocking to avoid deadlock - * of ourselves - */ - qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, NULL); - qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, NULL); - - /* Now the real part of the test, setup the sessions */ - clientChanTLS = qio_channel_tls_new_client( - QIO_CHANNEL(clientChanSock), clientCreds, - data->hostname, &err); - g_assert(clientChanTLS != NULL); - - serverChanTLS = qio_channel_tls_new_server( - QIO_CHANNEL(serverChanSock), serverCreds, - "channeltlsacl", &err); - g_assert(serverChanTLS != NULL); - - qio_channel_tls_handshake(clientChanTLS, - test_tls_handshake_done, - &clientHandshake, - NULL); - qio_channel_tls_handshake(serverChanTLS, - test_tls_handshake_done, - &serverHandshake, - NULL); - - /* - * Finally we loop around & around doing handshake on each - * session until we get an error, or the handshake completes. - * This relies on the socketpair being nonblocking to avoid - * deadlocking ourselves upon handshake - */ - mainloop = g_main_context_default(); - do { - g_main_context_iteration(mainloop, TRUE); - } while (!clientHandshake.finished && - !serverHandshake.finished); - - g_assert(clientHandshake.failed == data->expectClientFail); - g_assert(serverHandshake.failed == data->expectServerFail); - - test = qio_channel_test_new(); - qio_channel_test_run_threads(test, false, - QIO_CHANNEL(clientChanTLS), - QIO_CHANNEL(serverChanTLS)); - qio_channel_test_validate(test); - - test = qio_channel_test_new(); - qio_channel_test_run_threads(test, true, - QIO_CHANNEL(clientChanTLS), - QIO_CHANNEL(serverChanTLS)); - qio_channel_test_validate(test); - - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); - unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY); - - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT); - unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY); - - rmdir(CLIENT_CERT_DIR); - rmdir(SERVER_CERT_DIR); - - object_unparent(OBJECT(serverCreds)); - object_unparent(OBJECT(clientCreds)); - - object_unref(OBJECT(serverChanTLS)); - object_unref(OBJECT(clientChanTLS)); - - object_unref(OBJECT(serverChanSock)); - object_unref(OBJECT(clientChanSock)); - - close(channel[0]); - close(channel[1]); -} - - -int main(int argc, char **argv) -{ - int ret; - - module_call_init(MODULE_INIT_QOM); - g_test_init(&argc, &argv, NULL); - setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - - mkdir(WORKDIR, 0700); - - test_tls_init(KEYFILE); - -# define TEST_CHANNEL(name, caCrt, \ - serverCrt, clientCrt, \ - expectServerFail, expectClientFail, \ - hostname, wildcards) \ - struct QIOChannelTLSTestData name = { \ - caCrt, caCrt, serverCrt, clientCrt, \ - expectServerFail, expectClientFail, \ - hostname, wildcards \ - }; \ - g_test_add_data_func("/qio/channel/tls/" # name, \ - &name, test_io_channel_tls); - - /* A perfect CA, perfect client & perfect server */ - - /* Basic:CA:critical */ - TLS_ROOT_REQ(cacertreq, - "UK", "qemu CA", NULL, NULL, NULL, NULL, - true, true, true, - true, true, GNUTLS_KEY_KEY_CERT_SIGN, - false, false, NULL, NULL, - 0, 0); - TLS_CERT_REQ(servercertreq, cacertreq, - "UK", "qemu.org", NULL, NULL, NULL, NULL, - true, true, false, - true, true, - GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, - true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, - 0, 0); - TLS_CERT_REQ(clientcertreq, cacertreq, - "UK", "qemu", NULL, NULL, NULL, NULL, - true, true, false, - true, true, - GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, - true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, - 0, 0); - - const char *const wildcards[] = { - "C=UK,CN=qemu*", - NULL, - }; - TEST_CHANNEL(basic, cacertreq.filename, servercertreq.filename, - clientcertreq.filename, false, false, - "qemu.org", wildcards); - - ret = g_test_run(); - - test_tls_discard_cert(&clientcertreq); - test_tls_discard_cert(&servercertreq); - test_tls_discard_cert(&cacertreq); - - test_tls_cleanup(KEYFILE); - rmdir(WORKDIR); - - return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} - -#else /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */ - -int -main(void) -{ - return EXIT_SUCCESS; -} - -#endif /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */ |