aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 1 | /* |
| 2 | * QEMU VNC display driver: VeNCrypt authentication setup |
| 3 | * |
| 4 | * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> |
| 5 | * Copyright (C) 2006 Fabrice Bellard |
| 6 | * Copyright (C) 2009 Red Hat, Inc |
| 7 | * |
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 9 | * of this software and associated documentation files (the "Software"), to deal |
| 10 | * in the Software without restriction, including without limitation the rights |
| 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 12 | * copies of the Software, and to permit persons to whom the Software is |
| 13 | * furnished to do so, subject to the following conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be included in |
| 16 | * all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 24 | * THE SOFTWARE. |
| 25 | */ |
| 26 | |
Peter Maydell | e16f4c8 | 2016-01-29 17:49:51 +0000 | [diff] [blame] | 27 | #include "qemu/osdep.h" |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 28 | #include "vnc.h" |
Markus Armbruster | da34e65 | 2016-03-14 09:01:28 +0100 | [diff] [blame] | 29 | #include "qapi/error.h" |
Alex Bligh | 6a1751b | 2013-08-21 16:02:47 +0100 | [diff] [blame] | 30 | #include "qemu/main-loop.h" |
Daniel P. Berrange | ad6374c | 2017-09-21 13:15:27 +0100 | [diff] [blame] | 31 | #include "trace.h" |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 32 | |
| 33 | static void start_auth_vencrypt_subauth(VncState *vs) |
| 34 | { |
Daniel P. Berrange | 7e7e2eb | 2011-06-23 13:31:41 +0100 | [diff] [blame] | 35 | switch (vs->subauth) { |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 36 | case VNC_AUTH_VENCRYPT_TLSNONE: |
| 37 | case VNC_AUTH_VENCRYPT_X509NONE: |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 38 | vnc_write_u32(vs, 0); /* Accept auth completion */ |
| 39 | start_client_init(vs); |
| 40 | break; |
| 41 | |
| 42 | case VNC_AUTH_VENCRYPT_TLSVNC: |
| 43 | case VNC_AUTH_VENCRYPT_X509VNC: |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 44 | start_auth_vnc(vs); |
| 45 | break; |
| 46 | |
| 47 | #ifdef CONFIG_VNC_SASL |
| 48 | case VNC_AUTH_VENCRYPT_TLSSASL: |
| 49 | case VNC_AUTH_VENCRYPT_X509SASL: |
Blue Swirl | 0ed8b6f | 2012-07-08 06:56:53 +0000 | [diff] [blame] | 50 | start_auth_sasl(vs); |
| 51 | break; |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 52 | #endif /* CONFIG_VNC_SASL */ |
| 53 | |
| 54 | default: /* Should not be possible, but just in case */ |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 55 | trace_vnc_auth_fail(vs, vs->auth, "Unhandled VeNCrypt subauth", ""); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 56 | vnc_write_u8(vs, 1); |
| 57 | if (vs->minor >= 8) { |
| 58 | static const char err[] = "Unsupported authentication type"; |
| 59 | vnc_write_u32(vs, sizeof(err)); |
| 60 | vnc_write(vs, err, sizeof(err)); |
| 61 | } |
| 62 | vnc_client_error(vs); |
| 63 | } |
| 64 | } |
| 65 | |
Daniel P. Berrange | 60e705c | 2016-08-11 15:20:58 +0100 | [diff] [blame] | 66 | static void vnc_tls_handshake_done(QIOTask *task, |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 67 | gpointer user_data) |
Chih-Min Chao | 494cb81 | 2015-04-09 02:04:11 +0800 | [diff] [blame] | 68 | { |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 69 | VncState *vs = user_data; |
Daniel P. Berrange | 60e705c | 2016-08-11 15:20:58 +0100 | [diff] [blame] | 70 | Error *err = NULL; |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 71 | |
Daniel P. Berrange | 60e705c | 2016-08-11 15:20:58 +0100 | [diff] [blame] | 72 | if (qio_task_propagate_error(task, &err)) { |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 73 | trace_vnc_auth_fail(vs, vs->auth, "TLS handshake failed", |
| 74 | error_get_pretty(err)); |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 75 | vnc_client_error(vs); |
Daniel P. Berrange | 60e705c | 2016-08-11 15:20:58 +0100 | [diff] [blame] | 76 | error_free(err); |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 77 | } else { |
Brandon Carpenter | a75d6f0 | 2017-09-12 08:21:47 -0700 | [diff] [blame] | 78 | if (vs->ioc_tag) { |
| 79 | g_source_remove(vs->ioc_tag); |
| 80 | } |
Daniel P. Berrange | 04d2529 | 2015-02-27 16:20:57 +0000 | [diff] [blame] | 81 | vs->ioc_tag = qio_channel_add_watch( |
| 82 | vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); |
Daniel P. Berrange | 3e305e4 | 2015-08-06 14:39:32 +0100 | [diff] [blame] | 83 | start_auth_vencrypt_subauth(vs); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 84 | } |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 88 | static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len) |
| 89 | { |
| 90 | int auth = read_u32(data, 0); |
| 91 | |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 92 | trace_vnc_auth_vencrypt_subauth(vs, auth); |
Daniel P. Berrange | 7e7e2eb | 2011-06-23 13:31:41 +0100 | [diff] [blame] | 93 | if (auth != vs->subauth) { |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 94 | trace_vnc_auth_fail(vs, vs->auth, "Unsupported sub-auth version", ""); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 95 | vnc_write_u8(vs, 0); /* Reject auth */ |
| 96 | vnc_flush(vs); |
| 97 | vnc_client_error(vs); |
| 98 | } else { |
Daniel P. Berrange | 3e305e4 | 2015-08-06 14:39:32 +0100 | [diff] [blame] | 99 | Error *err = NULL; |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 100 | QIOChannelTLS *tls; |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 101 | vnc_write_u8(vs, 1); /* Accept auth */ |
| 102 | vnc_flush(vs); |
| 103 | |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 104 | if (vs->ioc_tag) { |
| 105 | g_source_remove(vs->ioc_tag); |
| 106 | vs->ioc_tag = 0; |
| 107 | } |
| 108 | |
| 109 | tls = qio_channel_tls_new_server( |
| 110 | vs->ioc, |
| 111 | vs->vd->tlscreds, |
Daniel P. Berrange | b76806d | 2016-02-18 18:40:24 +0000 | [diff] [blame] | 112 | vs->vd->tlsauthzid, |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 113 | &err); |
| 114 | if (!tls) { |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 115 | trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed", |
| 116 | error_get_pretty(err)); |
Daniel P. Berrange | 3e305e4 | 2015-08-06 14:39:32 +0100 | [diff] [blame] | 117 | error_free(err); |
| 118 | vnc_client_error(vs); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 119 | return 0; |
| 120 | } |
| 121 | |
Daniel P. Berrange | 10bcfe5 | 2016-09-30 11:57:14 +0100 | [diff] [blame] | 122 | qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls"); |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 123 | object_unref(OBJECT(vs->ioc)); |
| 124 | vs->ioc = QIO_CHANNEL(tls); |
Daniel P. Berrange | ad6374c | 2017-09-21 13:15:27 +0100 | [diff] [blame] | 125 | trace_vnc_client_io_wrap(vs, vs->ioc, "tls"); |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 126 | vs->tls = qio_channel_tls_get_session(tls); |
| 127 | |
| 128 | qio_channel_tls_handshake(tls, |
| 129 | vnc_tls_handshake_done, |
| 130 | vs, |
Peter Xu | 1939ccd | 2018-03-05 14:43:24 +0800 | [diff] [blame] | 131 | NULL, |
Daniel P. Berrange | 2cc4522 | 2015-03-02 19:01:05 +0000 | [diff] [blame] | 132 | NULL); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 133 | } |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len) |
| 138 | { |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 139 | trace_vnc_auth_vencrypt_version(vs, (int)data[0], (int)data[1]); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 140 | if (data[0] != 0 || |
| 141 | data[1] != 2) { |
Daniel P. Berrange | 7364dbd | 2017-09-21 13:15:28 +0100 | [diff] [blame] | 142 | trace_vnc_auth_fail(vs, vs->auth, "Unsupported version", ""); |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 143 | vnc_write_u8(vs, 1); /* Reject version */ |
| 144 | vnc_flush(vs); |
| 145 | vnc_client_error(vs); |
| 146 | } else { |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 147 | vnc_write_u8(vs, 0); /* Accept version */ |
| 148 | vnc_write_u8(vs, 1); /* Number of sub-auths */ |
Daniel P. Berrange | 7e7e2eb | 2011-06-23 13:31:41 +0100 | [diff] [blame] | 149 | vnc_write_u32(vs, vs->subauth); /* The supported auth */ |
aliguori | 274b6fc | 2009-03-06 23:44:29 +0000 | [diff] [blame] | 150 | vnc_flush(vs); |
| 151 | vnc_read_when(vs, protocol_client_vencrypt_auth, 4); |
| 152 | } |
| 153 | return 0; |
| 154 | } |
| 155 | |
| 156 | |
| 157 | void start_auth_vencrypt(VncState *vs) |
| 158 | { |
| 159 | /* Send VeNCrypt version 0.2 */ |
| 160 | vnc_write_u8(vs, 0); |
| 161 | vnc_write_u8(vs, 2); |
| 162 | |
| 163 | vnc_read_when(vs, protocol_client_vencrypt_init, 2); |
| 164 | } |
| 165 | |