Exemplo n.º 1
0
void migration_tls_set_outgoing_channel(MigrationState *s,
                                        QIOChannel *ioc,
                                        const char *hostname,
                                        Error **errp)
{
    QCryptoTLSCreds *creds;
    QIOChannelTLS *tioc;

    creds = migration_tls_get_creds(
        s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp);
    if (!creds) {
        return;
    }

    if (s->parameters.tls_hostname) {
        hostname = s->parameters.tls_hostname;
    }
    if (!hostname) {
        error_setg(errp, "No hostname available for TLS");
        return;
    }

    tioc = qio_channel_tls_new_client(
        ioc, creds, hostname, errp);
    if (!tioc) {
        return;
    }

    trace_migration_tls_outgoing_handshake_start(hostname);
    qio_channel_tls_handshake(tioc,
                              migration_tls_outgoing_handshake,
                              s,
                              NULL);
}
Exemplo n.º 2
0
Arquivo: client.c Projeto: 8tab/qemu
static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
                                        QCryptoTLSCreds *tlscreds,
                                        const char *hostname, Error **errp)
{
    nbd_opt_reply reply;
    QIOChannelTLS *tioc;
    struct NBDTLSHandshakeData data = { 0 };

    trace_nbd_receive_starttls_request();
    if (nbd_send_option_request(ioc, NBD_OPT_STARTTLS, 0, NULL, errp) < 0) {
        return NULL;
    }

    trace_nbd_receive_starttls_reply();
    if (nbd_receive_option_reply(ioc, NBD_OPT_STARTTLS, &reply, errp) < 0) {
        return NULL;
    }

    if (reply.type != NBD_REP_ACK) {
        error_setg(errp, "Server rejected request to start TLS %" PRIx32,
                   reply.type);
        nbd_send_opt_abort(ioc);
        return NULL;
    }

    if (reply.length != 0) {
        error_setg(errp, "Start TLS response was not zero %" PRIu32,
                   reply.length);
        nbd_send_opt_abort(ioc);
        return NULL;
    }

    trace_nbd_receive_starttls_new_client();
    tioc = qio_channel_tls_new_client(ioc, tlscreds, hostname, errp);
    if (!tioc) {
        return NULL;
    }
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-client-tls");
    data.loop = g_main_loop_new(g_main_context_default(), FALSE);
    trace_nbd_receive_starttls_tls_handshake();
    qio_channel_tls_handshake(tioc,
                              nbd_tls_handshake,
                              &data,
                              NULL);

    if (!data.complete) {
        g_main_loop_run(data.loop);
    }
    g_main_loop_unref(data.loop);
    if (data.error) {
        error_propagate(errp, data.error);
        object_unref(OBJECT(tioc));
        return NULL;
    }

    return QIO_CHANNEL(tioc);
}
Exemplo n.º 3
0
static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
                                        QCryptoTLSCreds *tlscreds,
                                        const char *hostname, Error **errp)
{
    int ret;
    QIOChannelTLS *tioc;
    struct NBDTLSHandshakeData data = { 0 };

    ret = nbd_request_simple_option(ioc, NBD_OPT_STARTTLS, errp);
    if (ret <= 0) {
        if (ret == 0) {
            error_setg(errp, "Server don't support STARTTLS option");
            nbd_send_opt_abort(ioc);
        }
        return NULL;
    }

    trace_nbd_receive_starttls_new_client();
    tioc = qio_channel_tls_new_client(ioc, tlscreds, hostname, errp);
    if (!tioc) {
        return NULL;
    }
    qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-client-tls");
    data.loop = g_main_loop_new(g_main_context_default(), FALSE);
    trace_nbd_receive_starttls_tls_handshake();
    qio_channel_tls_handshake(tioc,
                              nbd_tls_handshake,
                              &data,
                              NULL);

    if (!data.complete) {
        g_main_loop_run(data.loop);
    }
    g_main_loop_unref(data.loop);
    if (data.error) {
        error_propagate(errp, data.error);
        object_unref(OBJECT(tioc));
        return NULL;
    }

    return QIO_CHANNEL(tioc);
}
Exemplo n.º 4
0
static void tcp_chr_tls_init(Chardev *chr)
{
    SocketChardev *s = SOCKET_CHARDEV(chr);
    QIOChannelTLS *tioc;
    Error *err = NULL;
    gchar *name;

    if (s->is_listen) {
        tioc = qio_channel_tls_new_server(
            s->ioc, s->tls_creds,
            NULL, /* XXX Use an ACL */
            &err);
    } else {
        tioc = qio_channel_tls_new_client(
            s->ioc, s->tls_creds,
            s->addr->u.inet.data->host,
            &err);
    }
    if (tioc == NULL) {
        error_free(err);
        tcp_chr_disconnect(chr);
        return;
    }
    name = g_strdup_printf("chardev-tls-%s-%s",
                           s->is_listen ? "server" : "client",
                           chr->label);
    qio_channel_set_name(QIO_CHANNEL(tioc), name);
    g_free(name);
    object_unref(OBJECT(s->ioc));
    s->ioc = QIO_CHANNEL(tioc);

    qio_channel_tls_handshake(tioc,
                              tcp_chr_tls_handshake,
                              chr,
                              NULL);
}
Exemplo n.º 5
0
/*
 * 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]);
}