cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

vnc-ws.c (4286B)


      1/*
      2 * QEMU VNC display driver: Websockets support
      3 *
      4 * Copyright (C) 2010 Joel Martin
      5 * Copyright (C) 2012 Tim Hardeck
      6 *
      7 * This is free software; you can redistribute it and/or modify
      8 * it under the terms of the GNU General Public License as published by
      9 * the Free Software Foundation; either version 2 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * This software is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this software; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "qapi/error.h"
     23#include "vnc.h"
     24#include "io/channel-websock.h"
     25#include "qemu/bswap.h"
     26#include "trace.h"
     27
     28static void vncws_tls_handshake_done(QIOTask *task,
     29                                     gpointer user_data)
     30{
     31    VncState *vs = user_data;
     32    Error *err = NULL;
     33
     34    if (qio_task_propagate_error(task, &err)) {
     35        VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err));
     36        vnc_client_error(vs);
     37        error_free(err);
     38    } else {
     39        VNC_DEBUG("TLS handshake complete, starting websocket handshake\n");
     40        if (vs->ioc_tag) {
     41            g_source_remove(vs->ioc_tag);
     42        }
     43        vs->ioc_tag = qio_channel_add_watch(
     44            QIO_CHANNEL(vs->ioc), G_IO_IN | G_IO_HUP | G_IO_ERR,
     45            vncws_handshake_io, vs, NULL);
     46    }
     47}
     48
     49
     50gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED,
     51                                GIOCondition condition,
     52                                void *opaque)
     53{
     54    VncState *vs = opaque;
     55    QIOChannelTLS *tls;
     56    Error *err = NULL;
     57
     58    if (vs->ioc_tag) {
     59        g_source_remove(vs->ioc_tag);
     60        vs->ioc_tag = 0;
     61    }
     62
     63    if (condition & (G_IO_HUP | G_IO_ERR)) {
     64        vnc_client_error(vs);
     65        return TRUE;
     66    }
     67
     68    tls = qio_channel_tls_new_server(
     69        vs->ioc,
     70        vs->vd->tlscreds,
     71        vs->vd->tlsauthzid,
     72        &err);
     73    if (!tls) {
     74        VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
     75        error_free(err);
     76        vnc_client_error(vs);
     77        return TRUE;
     78    }
     79
     80    qio_channel_set_name(QIO_CHANNEL(tls), "vnc-ws-server-tls");
     81
     82    object_unref(OBJECT(vs->ioc));
     83    vs->ioc = QIO_CHANNEL(tls);
     84    trace_vnc_client_io_wrap(vs, vs->ioc, "tls");
     85    vs->tls = qio_channel_tls_get_session(tls);
     86
     87    qio_channel_tls_handshake(tls,
     88                              vncws_tls_handshake_done,
     89                              vs,
     90                              NULL,
     91                              NULL);
     92
     93    return TRUE;
     94}
     95
     96
     97static void vncws_handshake_done(QIOTask *task,
     98                                 gpointer user_data)
     99{
    100    VncState *vs = user_data;
    101    Error *err = NULL;
    102
    103    if (qio_task_propagate_error(task, &err)) {
    104        VNC_DEBUG("Websock handshake failed %s\n", error_get_pretty(err));
    105        vnc_client_error(vs);
    106        error_free(err);
    107    } else {
    108        VNC_DEBUG("Websock handshake complete, starting VNC protocol\n");
    109        vnc_start_protocol(vs);
    110        if (vs->ioc_tag) {
    111            g_source_remove(vs->ioc_tag);
    112        }
    113        vs->ioc_tag = qio_channel_add_watch(
    114            vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR,
    115            vnc_client_io, vs, NULL);
    116    }
    117}
    118
    119
    120gboolean vncws_handshake_io(QIOChannel *ioc G_GNUC_UNUSED,
    121                            GIOCondition condition,
    122                            void *opaque)
    123{
    124    VncState *vs = opaque;
    125    QIOChannelWebsock *wioc;
    126
    127    if (vs->ioc_tag) {
    128        g_source_remove(vs->ioc_tag);
    129        vs->ioc_tag = 0;
    130    }
    131
    132    if (condition & (G_IO_HUP | G_IO_ERR)) {
    133        vnc_client_error(vs);
    134        return TRUE;
    135    }
    136
    137    wioc = qio_channel_websock_new_server(vs->ioc);
    138    qio_channel_set_name(QIO_CHANNEL(wioc), "vnc-ws-server-websock");
    139
    140    object_unref(OBJECT(vs->ioc));
    141    vs->ioc = QIO_CHANNEL(wioc);
    142    trace_vnc_client_io_wrap(vs, vs->ioc, "websock");
    143
    144    qio_channel_websock_handshake(wioc,
    145                                  vncws_handshake_done,
    146                                  vs,
    147                                  NULL);
    148
    149    return TRUE;
    150}