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) { trace_qio_channel_tls_handshake_fail(ioc); qio_task_abort(task, err); goto cleanup; } status = qcrypto_tls_session_get_handshake_status(ioc->session); if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) { trace_qio_channel_tls_handshake_complete(ioc); if (qcrypto_tls_session_check_credentials(ioc->session, &err) < 0) { trace_qio_channel_tls_credentials_deny(ioc); qio_task_abort(task, err); goto cleanup; } trace_qio_channel_tls_credentials_allow(ioc); qio_task_complete(task); } else { GIOCondition condition; if (status == QCRYPTO_TLS_HANDSHAKE_SENDING) { condition = G_IO_OUT; } else { condition = G_IO_IN; } trace_qio_channel_tls_handshake_pending(ioc, status); qio_channel_add_watch(ioc->master, condition, qio_channel_tls_handshake_io, task, NULL); } cleanup: error_free(err); }
static int vncws_start_tls_handshake(VncState *vs) { Error *err = NULL; if (qcrypto_tls_session_handshake(vs->tls, &err) < 0) { goto error; } switch (qcrypto_tls_session_get_handshake_status(vs->tls)) { case QCRYPTO_TLS_HANDSHAKE_COMPLETE: VNC_DEBUG("Handshake done, checking credentials\n"); if (qcrypto_tls_session_check_credentials(vs->tls, &err) < 0) { goto error; } VNC_DEBUG("Client verification passed, starting TLS I/O\n"); qemu_set_fd_handler(vs->csock, vncws_handshake_read, NULL, vs); break; case QCRYPTO_TLS_HANDSHAKE_RECVING: VNC_DEBUG("Handshake interrupted (blocking read)\n"); qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, NULL, vs); break; case QCRYPTO_TLS_HANDSHAKE_SENDING: VNC_DEBUG("Handshake interrupted (blocking write)\n"); qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, vs); break; } return 0; error: VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err)); error_free(err); vnc_client_error(vs); return -1; }