]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/pve/0017-vnc-PVE-VNC-authentication.patch
bump version to 2.11.1-1
[pve-qemu.git] / debian / patches / pve / 0017-vnc-PVE-VNC-authentication.patch
CommitLineData
23102ed6 1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
95259824
WB
2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3Date: Mon, 11 Jan 2016 10:40:31 +0100
23102ed6 4Subject: [PATCH] vnc: PVE VNC authentication
95259824
WB
5
6---
6838f038 7 crypto/tlscreds.c | 47 ++++++++++++
95259824 8 crypto/tlscredspriv.h | 2 +
6838f038 9 crypto/tlscredsx509.c | 13 ++--
95259824
WB
10 crypto/tlssession.c | 1 +
11 include/crypto/tlscreds.h | 1 +
12 include/ui/console.h | 1 +
6838f038 13 qapi-schema.json | 1 +
95259824 14 qemu-options.hx | 3 +
6838f038
WB
15 ui/vnc-auth-vencrypt.c | 182 ++++++++++++++++++++++++++++++++++++++--------
16 ui/vnc.c | 140 ++++++++++++++++++++++++++++++++++-
95259824
WB
17 ui/vnc.h | 4 +
18 vl.c | 9 +++
6838f038 19 12 files changed, 364 insertions(+), 40 deletions(-)
95259824
WB
20
21diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
6838f038 22index 3cd41035bb..e982da3451 100644
95259824
WB
23--- a/crypto/tlscreds.c
24+++ b/crypto/tlscreds.c
25@@ -158,6 +158,33 @@ qcrypto_tls_creds_prop_get_verify(Object *obj,
26
27
28 static void
29+qcrypto_tls_creds_prop_set_pve(Object *obj,
30+ bool value,
31+ Error **errp G_GNUC_UNUSED)
32+{
33+ QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
34+
35+ creds->pve = value;
36+}
37+
38+
39+static bool
40+qcrypto_tls_creds_prop_get_pve(Object *obj,
41+ Error **errp G_GNUC_UNUSED)
42+{
43+ QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
44+
45+ return creds->pve;
46+}
47+
48+bool qcrypto_tls_creds_is_pve(QCryptoTLSCreds *creds)
49+{
50+ Error *errp = NULL;
51+ return qcrypto_tls_creds_prop_get_pve((Object*)creds, &errp);
52+}
53+
54+
55+static void
56 qcrypto_tls_creds_prop_set_dir(Object *obj,
57 const char *value,
58 Error **errp G_GNUC_UNUSED)
59@@ -250,6 +277,26 @@ qcrypto_tls_creds_init(Object *obj)
60 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
61
62 creds->verifyPeer = true;
63+ creds->pve = false;
64+
65+ object_property_add_bool(obj, "verify-peer",
66+ qcrypto_tls_creds_prop_get_verify,
67+ qcrypto_tls_creds_prop_set_verify,
68+ NULL);
69+ object_property_add_bool(obj, "pve",
70+ qcrypto_tls_creds_prop_get_pve,
71+ qcrypto_tls_creds_prop_set_pve,
72+ NULL);
73+ object_property_add_str(obj, "dir",
74+ qcrypto_tls_creds_prop_get_dir,
75+ qcrypto_tls_creds_prop_set_dir,
76+ NULL);
77+ object_property_add_enum(obj, "endpoint",
78+ "QCryptoTLSCredsEndpoint",
6838f038 79+ &QCryptoTLSCredsEndpoint_lookup,
95259824
WB
80+ qcrypto_tls_creds_prop_get_endpoint,
81+ qcrypto_tls_creds_prop_set_endpoint,
82+ NULL);
83 }
84
85
86diff --git a/crypto/tlscredspriv.h b/crypto/tlscredspriv.h
45169293 87index 13e9b6c0b2..0356acc2c9 100644
95259824
WB
88--- a/crypto/tlscredspriv.h
89+++ b/crypto/tlscredspriv.h
90@@ -36,6 +36,8 @@ int qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
91 gnutls_dh_params_t *dh_params,
92 Error **errp);
93
94+bool qcrypto_tls_creds_is_pve(QCryptoTLSCreds *creds);
95+
96 #endif
97
98 #endif /* QCRYPTO_TLSCREDSPRIV_H */
99diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
45169293 100index 50eb54f6bb..09f7364001 100644
95259824
WB
101--- a/crypto/tlscredsx509.c
102+++ b/crypto/tlscredsx509.c
103@@ -555,22 +555,23 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
104 *key = NULL, *dhparams = NULL;
105 int ret;
106 int rv = -1;
107+ bool pve = qcrypto_tls_creds_is_pve(&creds->parent_obj);
108
109 trace_qcrypto_tls_creds_x509_load(creds,
110 creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
111
112 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
113 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
114- QCRYPTO_TLS_CREDS_X509_CA_CERT,
115+ pve ? "pve-root-ca.pem" : QCRYPTO_TLS_CREDS_X509_CA_CERT,
116 true, &cacert, errp) < 0 ||
117 qcrypto_tls_creds_get_path(&creds->parent_obj,
118 QCRYPTO_TLS_CREDS_X509_CA_CRL,
119 false, &cacrl, errp) < 0 ||
120 qcrypto_tls_creds_get_path(&creds->parent_obj,
121- QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
122+ pve ? "local/pve-ssl.pem" : QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
123 true, &cert, errp) < 0 ||
124 qcrypto_tls_creds_get_path(&creds->parent_obj,
125- QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
126+ pve ? "local/pve-ssl.key" : QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
127 true, &key, errp) < 0 ||
128 qcrypto_tls_creds_get_path(&creds->parent_obj,
129 QCRYPTO_TLS_CREDS_DH_PARAMS,
130@@ -579,13 +580,13 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
131 }
132 } else {
133 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
134- QCRYPTO_TLS_CREDS_X509_CA_CERT,
135+ pve ? "pve-root-ca.pem" : QCRYPTO_TLS_CREDS_X509_CA_CERT,
136 true, &cacert, errp) < 0 ||
137 qcrypto_tls_creds_get_path(&creds->parent_obj,
138- QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
139+ pve ? "local/pve-ssl.pem" : QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
140 false, &cert, errp) < 0 ||
141 qcrypto_tls_creds_get_path(&creds->parent_obj,
142- QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
143+ pve ? "local/pve-ssl.key" : QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
144 false, &key, errp) < 0) {
145 goto cleanup;
146 }
147diff --git a/crypto/tlssession.c b/crypto/tlssession.c
45169293 148index 96a02deb69..c453e29cad 100644
95259824
WB
149--- a/crypto/tlssession.c
150+++ b/crypto/tlssession.c
151@@ -23,6 +23,7 @@
152 #include "crypto/tlscredsanon.h"
153 #include "crypto/tlscredsx509.h"
154 #include "qapi/error.h"
155+#include "crypto/tlscredspriv.h"
156 #include "qemu/acl.h"
157 #include "trace.h"
158
159diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
45169293 160index ad47d88be7..f86d379f26 100644
95259824
WB
161--- a/include/crypto/tlscreds.h
162+++ b/include/crypto/tlscreds.h
163@@ -55,6 +55,7 @@ struct QCryptoTLSCreds {
164 #endif
165 bool verifyPeer;
166 char *priority;
167+ bool pve;
168 };
169
170
171diff --git a/include/ui/console.h b/include/ui/console.h
6838f038 172index 580dfc57ee..383e5c88bd 100644
95259824
WB
173--- a/include/ui/console.h
174+++ b/include/ui/console.h
6838f038 175@@ -466,6 +466,7 @@ static inline void cocoa_display_init(DisplayState *ds, int full_screen)
95259824
WB
176 #endif
177
178 /* vnc.c */
179+void pve_auth_setup(int vmid);
180 void vnc_display_init(const char *id);
181 void vnc_display_open(const char *id, Error **errp);
182 void vnc_display_add_client(const char *id, int csock, bool skipauth);
6838f038
WB
183diff --git a/qapi-schema.json b/qapi-schema.json
184index 348b527681..d2155cb00f 100644
185--- a/qapi-schema.json
186+++ b/qapi-schema.json
187@@ -56,6 +56,7 @@
188 { 'pragma': {
189 # Commands allowed to return a non-dictionary:
190 'returns-whitelist': [
191+ 'get_link_status',
192 'human-monitor-command',
193 'qom-get',
194 'query-migrate-cache-size',
95259824 195diff --git a/qemu-options.hx b/qemu-options.hx
6838f038 196index 7c054af8f9..07129d55bc 100644
95259824
WB
197--- a/qemu-options.hx
198+++ b/qemu-options.hx
6838f038 199@@ -583,6 +583,9 @@ STEXI
95259824
WB
200 @table @option
201 ETEXI
202
203+DEF("id", HAS_ARG, QEMU_OPTION_id,
204+ "-id n set the VMID\n", QEMU_ARCH_ALL)
205+
206 DEF("fda", HAS_ARG, QEMU_OPTION_fda,
207 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
208 DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
209diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
6838f038 210index 7833631275..c42acd3714 100644
95259824
WB
211--- a/ui/vnc-auth-vencrypt.c
212+++ b/ui/vnc-auth-vencrypt.c
6838f038 213@@ -29,6 +29,108 @@
95259824
WB
214 #include "qapi/error.h"
215 #include "qemu/main-loop.h"
6838f038 216 #include "trace.h"
67af0fa4 217+#include "io/channel-socket.h"
95259824
WB
218+
219+static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
220+{
67af0fa4 221+ Error *err = NULL;
95259824
WB
222+ char username[256];
223+ char passwd[512];
224+
67af0fa4
WB
225+ SocketAddress *clientip = qio_channel_socket_get_remote_address(vs->sioc, &err);
226+ if (err) {
227+ goto err;
95259824
WB
228+ }
229+
230+ if ((len != (vs->username_len + vs->password_len)) ||
231+ (vs->username_len >= (sizeof(username)-1)) ||
232+ (vs->password_len >= (sizeof(passwd)-1)) ) {
67af0fa4 233+ error_setg(&err, "Got unexpected data length");
95259824
WB
234+ goto err;
235+ }
236+
237+ strncpy(username, (char *)data, vs->username_len);
238+ username[vs->username_len] = 0;
239+ strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
240+ passwd[vs->password_len] = 0;
241+
242+ VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
243+
6838f038 244+ if (pve_auth_verify(clientip->u.inet.host, username, passwd) == 0) {
95259824
WB
245+ vnc_write_u32(vs, 0); /* Accept auth completion */
246+ start_client_init(vs);
67af0fa4 247+ qapi_free_SocketAddress(clientip);
95259824
WB
248+ return 0;
249+ }
250+
67af0fa4 251+ error_setg(&err, "Authentication failed");
95259824
WB
252+err:
253+ if (err) {
67af0fa4
WB
254+ const char *err_msg = error_get_pretty(err);
255+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err_msg);
95259824
WB
256+ vnc_write_u32(vs, 1); /* Reject auth */
257+ if (vs->minor >= 8) {
67af0fa4 258+ int elen = strlen(err_msg);
95259824 259+ vnc_write_u32(vs, elen);
67af0fa4 260+ vnc_write(vs, err_msg, elen);
95259824 261+ }
67af0fa4 262+ error_free(err);
95259824
WB
263+ }
264+ vnc_flush(vs);
265+ vnc_client_error(vs);
266+
67af0fa4
WB
267+ qapi_free_SocketAddress(clientip);
268+
95259824
WB
269+ return 0;
270+
271+}
272+
273+static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
274+{
275+ uint32_t ulen = read_u32(data, 0);
276+ uint32_t pwlen = read_u32(data, 4);
277+ const char *err = NULL;
278+
279+ VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
280+
281+ if (!ulen) {
282+ err = "No User name.";
283+ goto err;
284+ }
285+ if (ulen >= 255) {
286+ err = "User name too long.";
287+ goto err;
288+ }
289+ if (!pwlen) {
290+ err = "Password too short";
291+ goto err;
292+ }
293+ if (pwlen >= 511) {
294+ err = "Password too long.";
295+ goto err;
296+ }
297+
298+ vs->username_len = ulen;
299+ vs->password_len = pwlen;
300+
301+ vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
302+
303+ return 0;
304+err:
305+ if (err) {
306+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
307+ vnc_write_u32(vs, 1); /* Reject auth */
308+ if (vs->minor >= 8) {
309+ int elen = strlen(err);
310+ vnc_write_u32(vs, elen);
311+ vnc_write(vs, err, elen);
312+ }
313+ }
314+ vnc_flush(vs);
315+ vnc_client_error(vs);
316+
317+ return 0;
318+}
319
320 static void start_auth_vencrypt_subauth(VncState *vs)
321 {
67af0fa4 322@@ -39,6 +141,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
95259824
WB
323 start_client_init(vs);
324 break;
325
326+ case VNC_AUTH_VENCRYPT_TLSPLAIN:
327+ case VNC_AUTH_VENCRYPT_X509PLAIN:
328+ VNC_DEBUG("Start TLS auth PLAIN\n");
329+ vnc_read_when(vs, protocol_client_auth_plain_start, 8);
330+ break;
331+
332+ case VNC_AUTH_VENCRYPT_PLAIN:
333+ VNC_DEBUG("Start auth PLAIN\n");
334+ vnc_read_when(vs, protocol_client_auth_plain_start, 8);
335+ break;
336+
337 case VNC_AUTH_VENCRYPT_TLSVNC:
338 case VNC_AUTH_VENCRYPT_X509VNC:
6838f038
WB
339 start_auth_vnc(vs);
340@@ -90,45 +203,51 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
95259824
WB
341 int auth = read_u32(data, 0);
342
6838f038 343 trace_vnc_auth_vencrypt_subauth(vs, auth);
95259824
WB
344- if (auth != vs->subauth) {
345+ if (auth != vs->subauth && auth != VNC_AUTH_VENCRYPT_PLAIN) {
6838f038 346 trace_vnc_auth_fail(vs, vs->auth, "Unsupported sub-auth version", "");
95259824
WB
347 vnc_write_u8(vs, 0); /* Reject auth */
348 vnc_flush(vs);
349 vnc_client_error(vs);
350 } else {
351- Error *err = NULL;
352- QIOChannelTLS *tls;
95259824
WB
353- vnc_write_u8(vs, 1); /* Accept auth */
354- vnc_flush(vs);
355-
356- if (vs->ioc_tag) {
357- g_source_remove(vs->ioc_tag);
358- vs->ioc_tag = 0;
359+ if (auth == VNC_AUTH_VENCRYPT_PLAIN) {
360+ vs->subauth = auth;
361+ start_auth_vencrypt_subauth(vs);
362 }
363+ else
364+ {
365+ Error *err = NULL;
366+ QIOChannelTLS *tls;
95259824
WB
367+ vnc_write_u8(vs, 1); /* Accept auth */
368+ vnc_flush(vs);
369
370- tls = qio_channel_tls_new_server(
371- vs->ioc,
372- vs->vd->tlscreds,
373- vs->vd->tlsaclname,
374- &err);
375- if (!tls) {
6838f038
WB
376- trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
377- error_get_pretty(err));
95259824
WB
378- error_free(err);
379- vnc_client_error(vs);
380- return 0;
381- }
382+ if (vs->ioc_tag) {
383+ g_source_remove(vs->ioc_tag);
384+ vs->ioc_tag = 0;
385+ }
95259824
WB
386+ tls = qio_channel_tls_new_server(
387+ vs->ioc,
388+ vs->vd->tlscreds,
389+ vs->vd->tlsaclname,
390+ &err);
391+ if (!tls) {
6838f038
WB
392+ trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
393+ error_get_pretty(err));
95259824
WB
394+ error_free(err);
395+ vnc_client_error(vs);
396+ return 0;
95259824 397+ }
6838f038
WB
398
399- qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
400- object_unref(OBJECT(vs->ioc));
401- vs->ioc = QIO_CHANNEL(tls);
402- trace_vnc_client_io_wrap(vs, vs->ioc, "tls");
403- vs->tls = qio_channel_tls_get_session(tls);
a544966d 404+ qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
6838f038
WB
405+ object_unref(OBJECT(vs->ioc));
406+ vs->ioc = QIO_CHANNEL(tls);
407+ trace_vnc_client_io_wrap(vs, vs->ioc, "tls");
408+ vs->tls = qio_channel_tls_get_session(tls);
95259824
WB
409
410- qio_channel_tls_handshake(tls,
411- vnc_tls_handshake_done,
412- vs,
413- NULL);
95259824
WB
414+ qio_channel_tls_handshake(tls,
415+ vnc_tls_handshake_done,
416+ vs,
417+ NULL);
418+ }
419 }
420 return 0;
421 }
6838f038 422@@ -144,8 +263,9 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
95259824
WB
423 vnc_client_error(vs);
424 } else {
95259824
WB
425 vnc_write_u8(vs, 0); /* Accept version */
426- vnc_write_u8(vs, 1); /* Number of sub-auths */
427+ vnc_write_u8(vs, 2); /* Number of sub-auths */
428 vnc_write_u32(vs, vs->subauth); /* The supported auth */
429+ vnc_write_u32(vs, VNC_AUTH_VENCRYPT_PLAIN); /* Alternative supported auth */
430 vnc_flush(vs);
431 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
432 }
433diff --git a/ui/vnc.c b/ui/vnc.c
6838f038 434index 4494cb1dd4..1589cbe1b3 100644
95259824
WB
435--- a/ui/vnc.c
436+++ b/ui/vnc.c
6838f038 437@@ -55,6 +55,125 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
95259824
WB
438 #include "vnc_keysym.h"
439 #include "crypto/cipher.h"
440
441+static int pve_vmid = 0;
442+
443+void pve_auth_setup(int vmid) {
444+ pve_vmid = vmid;
445+}
446+
447+static char *
448+urlencode(char *buf, const char *value)
449+{
450+ static const char *hexchar = "0123456789abcdef";
451+ char *p = buf;
452+ int i;
453+ int l = strlen(value);
454+ for (i = 0; i < l; i++) {
455+ char c = value[i];
456+ if (('a' <= c && c <= 'z') ||
457+ ('A' <= c && c <= 'Z') ||
458+ ('0' <= c && c <= '9')) {
459+ *p++ = c;
460+ } else if (c == 32) {
461+ *p++ = '+';
462+ } else {
463+ *p++ = '%';
464+ *p++ = hexchar[c >> 4];
465+ *p++ = hexchar[c & 15];
466+ }
467+ }
468+ *p = 0;
469+
470+ return p;
471+}
472+
473+int
474+pve_auth_verify(const char *clientip, const char *username, const char *passwd)
475+{
476+ struct sockaddr_in server;
477+
478+ int sfd = socket(AF_INET, SOCK_STREAM, 0);
479+ if (sfd == -1) {
480+ perror("pve_auth_verify: socket failed");
481+ return -1;
482+ }
483+
484+ struct hostent *he;
485+ if ((he = gethostbyname("localhost")) == NULL) {
486+ fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
487+ goto err;
488+ }
489+
490+ memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
491+ server.sin_family = AF_INET;
492+ server.sin_port = htons(85);
493+
494+ if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
495+ perror("pve_auth_verify: error connecting to server");
496+ goto err;
497+ }
498+
499+ char buf[8192];
500+ char form[8192];
501+
502+ char *p = form;
503+ p = urlencode(p, "username");
504+ *p++ = '=';
505+ p = urlencode(p, username);
506+
507+ *p++ = '&';
508+ p = urlencode(p, "password");
509+ *p++ = '=';
510+ p = urlencode(p, passwd);
511+
512+ *p++ = '&';
513+ p = urlencode(p, "path");
514+ *p++ = '=';
515+ char authpath[256];
516+ sprintf(authpath, "/vms/%d", pve_vmid);
517+ p = urlencode(p, authpath);
518+
519+ *p++ = '&';
520+ p = urlencode(p, "privs");
521+ *p++ = '=';
522+ p = urlencode(p, "VM.Console");
523+
524+ sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
525+ "Host: localhost:85\n"
526+ "Connection: close\n"
527+ "PVEClientIP: %s\n"
528+ "Content-Type: application/x-www-form-urlencoded\n"
529+ "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form);
530+ ssize_t len = strlen(buf);
531+ ssize_t sb = send(sfd, buf, len, 0);
532+ if (sb < 0) {
533+ perror("pve_auth_verify: send failed");
534+ goto err;
535+ }
536+ if (sb != len) {
537+ fprintf(stderr, "pve_auth_verify: partial send error\n");
538+ goto err;
539+ }
540+
541+ len = recv(sfd, buf, sizeof(buf) - 1, 0);
542+ if (len < 0) {
543+ perror("pve_auth_verify: recv failed");
544+ goto err;
545+ }
546+
547+ buf[len] = 0;
548+
549+ //printf("DATA:%s\n", buf);
550+
551+ shutdown(sfd, SHUT_RDWR);
552+
553+ return strncmp(buf, "HTTP/1.1 200 OK", 15);
554+
555+err:
556+ shutdown(sfd, SHUT_RDWR);
557+ return -1;
558+}
559+
560 static QTAILQ_HEAD(, VncDisplay) vnc_displays =
561 QTAILQ_HEAD_INITIALIZER(vnc_displays);
562
6838f038 563@@ -3507,10 +3626,16 @@ vnc_display_setup_auth(int *auth,
a544966d
WB
564 if (password) {
565 if (is_x509) {
95259824 566 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
a544966d
WB
567- *subauth = VNC_AUTH_VENCRYPT_X509VNC;
568+ if (tlscreds->pve)
569+ *subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
95259824 570+ else
a544966d
WB
571+ *subauth = VNC_AUTH_VENCRYPT_X509VNC;
572 } else {
95259824 573 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
a544966d
WB
574- *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
575+ if (tlscreds->pve)
576+ *subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
95259824 577+ else
a544966d
WB
578+ *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
579 }
580
581 } else if (sasl) {
6838f038 582@@ -3544,6 +3669,7 @@ vnc_display_create_creds(bool x509,
95259824
WB
583 bool x509verify,
584 const char *dir,
585 const char *id,
586+ bool pve,
587 Error **errp)
588 {
589 gchar *credsid = g_strdup_printf("tlsvnc%s", id);
6838f038 590@@ -3559,6 +3685,7 @@ vnc_display_create_creds(bool x509,
95259824
WB
591 "endpoint", "server",
592 "dir", dir,
593 "verify-peer", x509verify ? "yes" : "no",
594+ "pve", pve ? "yes" : "no",
595 NULL);
596 } else {
597 creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON,
6838f038 598@@ -3566,6 +3693,7 @@ vnc_display_create_creds(bool x509,
95259824
WB
599 credsid,
600 &err,
601 "endpoint", "server",
602+ "pve", pve ? "yes" : "no",
603 NULL);
604 }
605
6838f038 606@@ -4032,12 +4160,17 @@ void vnc_display_open(const char *id, Error **errp)
95259824
WB
607 }
608 } else {
609 const char *path;
610- bool tls = false, x509 = false, x509verify = false;
611+ bool tls = false, x509 = false, x509verify = false, pve = false;
612 tls = qemu_opt_get_bool(opts, "tls", false);
613 path = qemu_opt_get(opts, "x509");
614 if (tls || path) {
615 if (path) {
616 x509 = true;
617+ if (!strcmp(path, "on")) {
618+ /* magic to default to /etc/pve */
619+ path = "/etc/pve";
620+ pve = true;
621+ }
622 } else {
623 path = qemu_opt_get(opts, "x509verify");
624 if (path) {
6838f038 625@@ -4049,6 +4182,7 @@ void vnc_display_open(const char *id, Error **errp)
95259824
WB
626 x509verify,
627 path,
a544966d 628 vd->id,
95259824
WB
629+ pve,
630 errp);
a544966d 631 if (!vd->tlscreds) {
95259824
WB
632 goto fail;
633diff --git a/ui/vnc.h b/ui/vnc.h
6838f038 634index bbda0540a7..8cc6367ed3 100644
95259824
WB
635--- a/ui/vnc.h
636+++ b/ui/vnc.h
6838f038 637@@ -290,6 +290,8 @@ struct VncState
95259824
WB
638 int auth;
639 int subauth; /* Used by VeNCrypt */
640 char challenge[VNC_AUTH_CHALLENGE_SIZE];
641+ int username_len;
642+ int password_len;
643 QCryptoTLSSession *tls; /* Borrowed pointer from channel, don't free */
644 #ifdef CONFIG_VNC_SASL
645 VncStateSASL sasl;
6838f038 646@@ -595,4 +597,6 @@ int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
95259824
WB
647 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
648 void vnc_zrle_clear(VncState *vs);
649
650+int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
651+
652 #endif /* QEMU_VNC_H */
653diff --git a/vl.c b/vl.c
6838f038 654index 75fde82180..255d989009 100644
95259824
WB
655--- a/vl.c
656+++ b/vl.c
6838f038 657@@ -3096,6 +3096,7 @@ static void register_global_properties(MachineState *ms)
95259824
WB
658 int main(int argc, char **argv, char **envp)
659 {
660 int i;
661+ long int vm_id_long = 0;
662 int snapshot, linux_boot;
663 const char *initrd_filename;
664 const char *kernel_filename, *kernel_cmdline;
6838f038 665@@ -3922,6 +3923,14 @@ int main(int argc, char **argv, char **envp)
95259824
WB
666 exit(1);
667 }
668 break;
669+ case QEMU_OPTION_id:
670+ vm_id_long = strtol(optarg, (char **) &optarg, 10);
671+ if (*optarg != 0 || vm_id_long < 100 || vm_id_long > INT_MAX) {
672+ fprintf(stderr, "Invalid ID\n");
673+ exit(1);
674+ }
675+ pve_auth_setup(vm_id_long);
676+ break;
677 case QEMU_OPTION_vnc:
678 vnc_parse(optarg, &error_fatal);
679 break;
680--
45169293 6812.11.0
95259824 682