static void vncws_send_handshake_response(VncState *vs, const char* key) { char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; unsigned char hash[SHA1_DIGEST_LEN]; size_t hash_size = sizeof(hash); char *accept = NULL, *response = NULL; gnutls_datum_t in; int ret; g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); /* hash and encode it */ in.data = (void *)combined_key; in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN; ret = gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size); if (ret == GNUTLS_E_SUCCESS && hash_size <= SHA1_DIGEST_LEN) { accept = g_base64_encode(hash, hash_size); } if (accept == NULL) { VNC_DEBUG("Hashing Websocket combined key failed\n"); vnc_client_error(vs); return; } response = g_strdup_printf(WS_HANDSHAKE, accept); vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response)); g_free(accept); g_free(response); vs->encode_ws = 1; vnc_init_state(vs); }
static void vncws_send_handshake_response(VncState *vs, const char* key) { char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; char *accept = NULL, *response = NULL; Error *err = NULL; g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); /* hash and encode it */ if (qcrypto_hash_base64(QCRYPTO_HASH_ALG_SHA1, combined_key, WS_CLIENT_KEY_LEN + WS_GUID_LEN, &accept, &err) < 0) { VNC_DEBUG("Hashing Websocket combined key failed %s\n", error_get_pretty(err)); error_free(err); vnc_client_error(vs); return; } response = g_strdup_printf(WS_HANDSHAKE, accept); vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response)); g_free(accept); g_free(response); vs->encode_ws = 1; vnc_init_state(vs); }
long vnc_client_write_sasl(VncState *vs) { long ret; VNC_DEBUG("Write SASL: Pending output %p size %zd offset %zd " "Encoded: %p size %d offset %d\n", vs->output.buffer, vs->output.capacity, vs->output.offset, vs->sasl.encoded, vs->sasl.encodedLength, vs->sasl.encodedOffset); if (!vs->sasl.encoded) { int err; err = sasl_encode(vs->sasl.conn, (char *)vs->output.buffer, vs->output.offset, (const char **)&vs->sasl.encoded, &vs->sasl.encodedLength); if (err != SASL_OK) return vnc_client_io_error(vs, -1, NULL); vs->sasl.encodedOffset = 0; } ret = vnc_client_write_buf(vs, vs->sasl.encoded + vs->sasl.encodedOffset, vs->sasl.encodedLength - vs->sasl.encodedOffset); if (!ret) return 0; vs->sasl.encodedOffset += ret; if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { vs->output.offset = 0; vs->sasl.encoded = NULL; vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; } /* Can't merge this block with one above, because * someone might have written more unencrypted * data in vs->output while we were processing * SASL encoded output */ if (vs->output.offset == 0) { if (vs->ioc_tag) { g_source_remove(vs->ioc_tag); } vs->ioc_tag = qio_channel_add_watch( vs->ioc, G_IO_IN, vnc_client_io, vs, NULL); } return ret; }
long vnc_client_write_sasl(VncState *vs) { long ret; VNC_DEBUG("Write SASL: Pending output %p size %d offset %d Encoded: %p size %d offset %d\n", vs->output.buffer, vs->output.capacity, vs->output.offset, vs->sasl.encoded, vs->sasl.encodedLength, vs->sasl.encodedOffset); if (!vs->sasl.encoded) { int err; err = sasl_encode(vs->sasl.conn, (char *)vs->output.buffer, vs->output.offset, (const char **)&vs->sasl.encoded, &vs->sasl.encodedLength); if (err != SASL_OK) return vnc_client_io_error(vs, -1, EIO); vs->sasl.encodedOffset = 0; } ret = vnc_client_write_buf(vs, vs->sasl.encoded + vs->sasl.encodedOffset, vs->sasl.encodedLength - vs->sasl.encodedOffset); if (!ret) return 0; vs->sasl.encodedOffset += ret; if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { vs->output.offset = 0; vs->sasl.encoded = NULL; vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; } /* Can't merge this block with one above, because * someone might have written more unencrypted * data in vs->output while we were processing * SASL encoded output */ if (vs->output.offset == 0) { qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); } return ret; }
long vnc_client_write_ws(VncState *vs) { long ret; VNC_DEBUG("Write WS: Pending output %p size %zd offset %zd\n", vs->output.buffer, vs->output.capacity, vs->output.offset); vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset); buffer_reset(&vs->output); ret = vnc_client_write_buf(vs, vs->ws_output.buffer, vs->ws_output.offset); if (!ret) { return 0; } buffer_advance(&vs->ws_output, ret); if (vs->ws_output.offset == 0) { qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); } return ret; }