13e230dd2SCorentin Chary /* 23e230dd2SCorentin Chary * QEMU VNC display driver: VeNCrypt authentication setup 33e230dd2SCorentin Chary * 43e230dd2SCorentin Chary * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> 53e230dd2SCorentin Chary * Copyright (C) 2006 Fabrice Bellard 63e230dd2SCorentin Chary * Copyright (C) 2009 Red Hat, Inc 73e230dd2SCorentin Chary * 83e230dd2SCorentin Chary * Permission is hereby granted, free of charge, to any person obtaining a copy 93e230dd2SCorentin Chary * of this software and associated documentation files (the "Software"), to deal 103e230dd2SCorentin Chary * in the Software without restriction, including without limitation the rights 113e230dd2SCorentin Chary * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 123e230dd2SCorentin Chary * copies of the Software, and to permit persons to whom the Software is 133e230dd2SCorentin Chary * furnished to do so, subject to the following conditions: 143e230dd2SCorentin Chary * 153e230dd2SCorentin Chary * The above copyright notice and this permission notice shall be included in 163e230dd2SCorentin Chary * all copies or substantial portions of the Software. 173e230dd2SCorentin Chary * 183e230dd2SCorentin Chary * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 193e230dd2SCorentin Chary * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 203e230dd2SCorentin Chary * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 213e230dd2SCorentin Chary * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 223e230dd2SCorentin Chary * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 233e230dd2SCorentin Chary * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 243e230dd2SCorentin Chary * THE SOFTWARE. 253e230dd2SCorentin Chary */ 263e230dd2SCorentin Chary 27e16f4c87SPeter Maydell #include "qemu/osdep.h" 283e230dd2SCorentin Chary #include "vnc.h" 29da34e65cSMarkus Armbruster #include "qapi/error.h" 306a1751b7SAlex Bligh #include "qemu/main-loop.h" 31*ad6374c4SDaniel P. Berrange #include "trace.h" 323e230dd2SCorentin Chary 333e230dd2SCorentin Chary static void start_auth_vencrypt_subauth(VncState *vs) 343e230dd2SCorentin Chary { 357e7e2ebcSDaniel P. Berrange switch (vs->subauth) { 363e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSNONE: 373e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509NONE: 383e230dd2SCorentin Chary VNC_DEBUG("Accept TLS auth none\n"); 393e230dd2SCorentin Chary vnc_write_u32(vs, 0); /* Accept auth completion */ 403e230dd2SCorentin Chary start_client_init(vs); 413e230dd2SCorentin Chary break; 423e230dd2SCorentin Chary 433e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSVNC: 443e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509VNC: 453e230dd2SCorentin Chary VNC_DEBUG("Start TLS auth VNC\n"); 463e230dd2SCorentin Chary start_auth_vnc(vs); 473e230dd2SCorentin Chary break; 483e230dd2SCorentin Chary 493e230dd2SCorentin Chary #ifdef CONFIG_VNC_SASL 503e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_TLSSASL: 513e230dd2SCorentin Chary case VNC_AUTH_VENCRYPT_X509SASL: 523e230dd2SCorentin Chary VNC_DEBUG("Start TLS auth SASL\n"); 530ed8b6f6SBlue Swirl start_auth_sasl(vs); 540ed8b6f6SBlue Swirl break; 553e230dd2SCorentin Chary #endif /* CONFIG_VNC_SASL */ 563e230dd2SCorentin Chary 573e230dd2SCorentin Chary default: /* Should not be possible, but just in case */ 587e7e2ebcSDaniel P. Berrange VNC_DEBUG("Reject subauth %d server bug\n", vs->auth); 593e230dd2SCorentin Chary vnc_write_u8(vs, 1); 603e230dd2SCorentin Chary if (vs->minor >= 8) { 613e230dd2SCorentin Chary static const char err[] = "Unsupported authentication type"; 623e230dd2SCorentin Chary vnc_write_u32(vs, sizeof(err)); 633e230dd2SCorentin Chary vnc_write(vs, err, sizeof(err)); 643e230dd2SCorentin Chary } 653e230dd2SCorentin Chary vnc_client_error(vs); 663e230dd2SCorentin Chary } 673e230dd2SCorentin Chary } 683e230dd2SCorentin Chary 6960e705c5SDaniel P. Berrange static void vnc_tls_handshake_done(QIOTask *task, 702cc45228SDaniel P. Berrange gpointer user_data) 71494cb817SChih-Min Chao { 722cc45228SDaniel P. Berrange VncState *vs = user_data; 7360e705c5SDaniel P. Berrange Error *err = NULL; 743e230dd2SCorentin Chary 7560e705c5SDaniel P. Berrange if (qio_task_propagate_error(task, &err)) { 762cc45228SDaniel P. Berrange VNC_DEBUG("Handshake failed %s\n", 772cc45228SDaniel P. Berrange error_get_pretty(err)); 782cc45228SDaniel P. Berrange vnc_client_error(vs); 7960e705c5SDaniel P. Berrange error_free(err); 802cc45228SDaniel P. Berrange } else { 8104d2529dSDaniel P. Berrange vs->ioc_tag = qio_channel_add_watch( 8204d2529dSDaniel P. Berrange vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); 833e230dd2SCorentin Chary start_auth_vencrypt_subauth(vs); 8404d2529dSDaniel P. Berrange } 853e230dd2SCorentin Chary } 863e230dd2SCorentin Chary 873e230dd2SCorentin Chary 883e230dd2SCorentin Chary static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len) 893e230dd2SCorentin Chary { 903e230dd2SCorentin Chary int auth = read_u32(data, 0); 913e230dd2SCorentin Chary 927e7e2ebcSDaniel P. Berrange if (auth != vs->subauth) { 933e230dd2SCorentin Chary VNC_DEBUG("Rejecting auth %d\n", auth); 943e230dd2SCorentin Chary vnc_write_u8(vs, 0); /* Reject auth */ 953e230dd2SCorentin Chary vnc_flush(vs); 963e230dd2SCorentin Chary vnc_client_error(vs); 973e230dd2SCorentin Chary } else { 983e305e4aSDaniel P. Berrange Error *err = NULL; 992cc45228SDaniel P. Berrange QIOChannelTLS *tls; 1003e230dd2SCorentin Chary VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth); 1013e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* Accept auth */ 1023e230dd2SCorentin Chary vnc_flush(vs); 1033e230dd2SCorentin Chary 1042cc45228SDaniel P. Berrange if (vs->ioc_tag) { 1052cc45228SDaniel P. Berrange g_source_remove(vs->ioc_tag); 1062cc45228SDaniel P. Berrange vs->ioc_tag = 0; 1072cc45228SDaniel P. Berrange } 1082cc45228SDaniel P. Berrange 1092cc45228SDaniel P. Berrange tls = qio_channel_tls_new_server( 1102cc45228SDaniel P. Berrange vs->ioc, 1112cc45228SDaniel P. Berrange vs->vd->tlscreds, 1123e305e4aSDaniel P. Berrange vs->vd->tlsaclname, 1133e305e4aSDaniel P. Berrange &err); 1142cc45228SDaniel P. Berrange if (!tls) { 1152cc45228SDaniel P. Berrange VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err)); 1163e305e4aSDaniel P. Berrange error_free(err); 1173e305e4aSDaniel P. Berrange vnc_client_error(vs); 1183e230dd2SCorentin Chary return 0; 1193e230dd2SCorentin Chary } 1203e230dd2SCorentin Chary 12110bcfe58SDaniel P. Berrange qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls"); 1223e230dd2SCorentin Chary VNC_DEBUG("Start TLS VeNCrypt handshake process\n"); 1232cc45228SDaniel P. Berrange object_unref(OBJECT(vs->ioc)); 1242cc45228SDaniel P. Berrange vs->ioc = QIO_CHANNEL(tls); 125*ad6374c4SDaniel P. Berrange trace_vnc_client_io_wrap(vs, vs->ioc, "tls"); 1262cc45228SDaniel P. Berrange vs->tls = qio_channel_tls_get_session(tls); 1272cc45228SDaniel P. Berrange 1282cc45228SDaniel P. Berrange qio_channel_tls_handshake(tls, 1292cc45228SDaniel P. Berrange vnc_tls_handshake_done, 1302cc45228SDaniel P. Berrange vs, 1312cc45228SDaniel P. Berrange NULL); 1323e230dd2SCorentin Chary } 1333e230dd2SCorentin Chary return 0; 1343e230dd2SCorentin Chary } 1353e230dd2SCorentin Chary 1363e230dd2SCorentin Chary static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len) 1373e230dd2SCorentin Chary { 1383e230dd2SCorentin Chary if (data[0] != 0 || 1393e230dd2SCorentin Chary data[1] != 2) { 1403e230dd2SCorentin Chary VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]); 1413e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* Reject version */ 1423e230dd2SCorentin Chary vnc_flush(vs); 1433e230dd2SCorentin Chary vnc_client_error(vs); 1443e230dd2SCorentin Chary } else { 1457e7e2ebcSDaniel P. Berrange VNC_DEBUG("Sending allowed auth %d\n", vs->subauth); 1463e230dd2SCorentin Chary vnc_write_u8(vs, 0); /* Accept version */ 1473e230dd2SCorentin Chary vnc_write_u8(vs, 1); /* Number of sub-auths */ 1487e7e2ebcSDaniel P. Berrange vnc_write_u32(vs, vs->subauth); /* The supported auth */ 1493e230dd2SCorentin Chary vnc_flush(vs); 1503e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_vencrypt_auth, 4); 1513e230dd2SCorentin Chary } 1523e230dd2SCorentin Chary return 0; 1533e230dd2SCorentin Chary } 1543e230dd2SCorentin Chary 1553e230dd2SCorentin Chary 1563e230dd2SCorentin Chary void start_auth_vencrypt(VncState *vs) 1573e230dd2SCorentin Chary { 1583e230dd2SCorentin Chary /* Send VeNCrypt version 0.2 */ 1593e230dd2SCorentin Chary vnc_write_u8(vs, 0); 1603e230dd2SCorentin Chary vnc_write_u8(vs, 2); 1613e230dd2SCorentin Chary 1623e230dd2SCorentin Chary vnc_read_when(vs, protocol_client_vencrypt_init, 2); 1633e230dd2SCorentin Chary } 1643e230dd2SCorentin Chary 165