]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/pve/0041-PVE-VNC-authentication.patch
update to qemu 2.6.0
[pve-qemu-kvm.git] / debian / patches / pve / 0041-PVE-VNC-authentication.patch
CommitLineData
ca0fe5f5
WB
1From 19a3e72ea86fb723d7facba1f07d7ae99520e461 Mon Sep 17 00:00:00 2001
2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3Date: Mon, 11 Jan 2016 10:40:31 +0100
b07d35a5 4Subject: [PATCH 41/54] PVE VNC authentication
ca0fe5f5
WB
5
6---
b07d35a5 7 crypto/tlscreds.c | 47 +++++++++++
ca0fe5f5
WB
8 crypto/tlscredspriv.h | 2 +
9 crypto/tlscredsx509.c | 13 ++--
10 crypto/tlssession.c | 1 +
11 include/crypto/tlscreds.h | 1 +
12 include/ui/console.h | 1 +
13 qemu-options.hx | 3 +
b07d35a5
TL
14 ui/vnc-auth-vencrypt.c | 194 ++++++++++++++++++++++++++++++++++++++--------
15 ui/vnc.c | 140 ++++++++++++++++++++++++++++++++-
16 ui/vnc.h | 4 +
ca0fe5f5 17 vl.c | 9 +++
b07d35a5 18 11 files changed, 375 insertions(+), 40 deletions(-)
ca0fe5f5
WB
19
20diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
21index e7d9c1c..27e5c78 100644
22--- a/crypto/tlscreds.c
23+++ b/crypto/tlscreds.c
24@@ -156,6 +156,33 @@ qcrypto_tls_creds_prop_get_verify(Object *obj,
25
26
27 static void
28+qcrypto_tls_creds_prop_set_pve(Object *obj,
29+ bool value,
30+ Error **errp G_GNUC_UNUSED)
31+{
32+ QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
33+
34+ creds->pve = value;
35+}
36+
37+
38+static bool
39+qcrypto_tls_creds_prop_get_pve(Object *obj,
40+ Error **errp G_GNUC_UNUSED)
41+{
42+ QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
43+
44+ return creds->pve;
45+}
46+
47+bool qcrypto_tls_creds_is_pve(QCryptoTLSCreds *creds)
48+{
49+ Error *errp = NULL;
50+ return qcrypto_tls_creds_prop_get_pve((Object*)creds, &errp);
51+}
52+
53+
54+static void
55 qcrypto_tls_creds_prop_set_dir(Object *obj,
56 const char *value,
57 Error **errp G_GNUC_UNUSED)
b07d35a5 58@@ -225,6 +252,26 @@ qcrypto_tls_creds_init(Object *obj)
ca0fe5f5
WB
59 QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
60
61 creds->verifyPeer = true;
62+ creds->pve = false;
b07d35a5
TL
63+
64+ object_property_add_bool(obj, "verify-peer",
65+ qcrypto_tls_creds_prop_get_verify,
66+ qcrypto_tls_creds_prop_set_verify,
67+ NULL);
ca0fe5f5
WB
68+ object_property_add_bool(obj, "pve",
69+ qcrypto_tls_creds_prop_get_pve,
70+ qcrypto_tls_creds_prop_set_pve,
71+ NULL);
b07d35a5
TL
72+ object_property_add_str(obj, "dir",
73+ qcrypto_tls_creds_prop_get_dir,
74+ qcrypto_tls_creds_prop_set_dir,
75+ NULL);
76+ object_property_add_enum(obj, "endpoint",
77+ "QCryptoTLSCredsEndpoint",
78+ QCryptoTLSCredsEndpoint_lookup,
79+ qcrypto_tls_creds_prop_get_endpoint,
80+ qcrypto_tls_creds_prop_set_endpoint,
81+ NULL);
82 }
83
84
ca0fe5f5
WB
85diff --git a/crypto/tlscredspriv.h b/crypto/tlscredspriv.h
86index 9222be4..3a34279 100644
87--- a/crypto/tlscredspriv.h
88+++ b/crypto/tlscredspriv.h
89@@ -36,6 +36,8 @@ int qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
90 gnutls_dh_params_t *dh_params,
91 Error **errp);
92
93+bool qcrypto_tls_creds_is_pve(QCryptoTLSCreds *creds);
94+
95 #endif
96
97 #endif /* QCRYPTO_TLSCRED_PRIV_H__ */
98diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
99index 26f18cb..12e67c8 100644
100--- a/crypto/tlscredsx509.c
101+++ b/crypto/tlscredsx509.c
102@@ -547,22 +547,23 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
103 *key = NULL, *dhparams = NULL;
104 int ret;
105 int rv = -1;
106+ bool pve = qcrypto_tls_creds_is_pve(&creds->parent_obj);
107
108 trace_qcrypto_tls_creds_x509_load(creds,
109 creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
110
111 if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
112 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
113- QCRYPTO_TLS_CREDS_X509_CA_CERT,
114+ pve ? "pve-root-ca.pem" : QCRYPTO_TLS_CREDS_X509_CA_CERT,
115 true, &cacert, errp) < 0 ||
116 qcrypto_tls_creds_get_path(&creds->parent_obj,
117 QCRYPTO_TLS_CREDS_X509_CA_CRL,
118 false, &cacrl, errp) < 0 ||
119 qcrypto_tls_creds_get_path(&creds->parent_obj,
120- QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
121+ pve ? "local/pve-ssl.pem" : QCRYPTO_TLS_CREDS_X509_SERVER_CERT,
122 true, &cert, errp) < 0 ||
123 qcrypto_tls_creds_get_path(&creds->parent_obj,
124- QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
125+ pve ? "local/pve-ssl.key" : QCRYPTO_TLS_CREDS_X509_SERVER_KEY,
126 true, &key, errp) < 0 ||
127 qcrypto_tls_creds_get_path(&creds->parent_obj,
128 QCRYPTO_TLS_CREDS_DH_PARAMS,
129@@ -571,13 +572,13 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
130 }
131 } else {
132 if (qcrypto_tls_creds_get_path(&creds->parent_obj,
133- QCRYPTO_TLS_CREDS_X509_CA_CERT,
134+ pve ? "pve-root-ca.pem" : QCRYPTO_TLS_CREDS_X509_CA_CERT,
135 true, &cacert, errp) < 0 ||
136 qcrypto_tls_creds_get_path(&creds->parent_obj,
137- QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
138+ pve ? "local/pve-ssl.pem" : QCRYPTO_TLS_CREDS_X509_CLIENT_CERT,
139 false, &cert, errp) < 0 ||
140 qcrypto_tls_creds_get_path(&creds->parent_obj,
141- QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
142+ pve ? "local/pve-ssl.key" : QCRYPTO_TLS_CREDS_X509_CLIENT_KEY,
143 false, &key, errp) < 0) {
144 goto cleanup;
145 }
146diff --git a/crypto/tlssession.c b/crypto/tlssession.c
147index 3735529..a7ed50a 100644
148--- a/crypto/tlssession.c
149+++ b/crypto/tlssession.c
b07d35a5 150@@ -23,6 +23,7 @@
ca0fe5f5
WB
151 #include "crypto/tlscredsanon.h"
152 #include "crypto/tlscredsx509.h"
b07d35a5 153 #include "qapi/error.h"
ca0fe5f5
WB
154+#include "crypto/tlscredspriv.h"
155 #include "qemu/acl.h"
156 #include "trace.h"
157
158diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
159index 21761b7..2cc0ce0 100644
160--- a/include/crypto/tlscreds.h
161+++ b/include/crypto/tlscreds.h
162@@ -56,6 +56,7 @@ struct QCryptoTLSCreds {
163 gnutls_dh_params_t dh_params;
164 #endif
165 bool verifyPeer;
166+ bool pve;
167 };
168
169
170diff --git a/include/ui/console.h b/include/ui/console.h
171index c249db4..399b42d 100644
172--- a/include/ui/console.h
173+++ b/include/ui/console.h
174@@ -409,6 +409,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
175 void cocoa_display_init(DisplayState *ds, int full_screen);
176
177 /* vnc.c */
178+void pve_auth_setup(int vmid);
179 void vnc_display_init(const char *id);
180 void vnc_display_open(const char *id, Error **errp);
181 void vnc_display_add_client(const char *id, int csock, bool skipauth);
182diff --git a/qemu-options.hx b/qemu-options.hx
183index cd465d5..bf87c00 100644
184--- a/qemu-options.hx
185+++ b/qemu-options.hx
186@@ -419,6 +419,9 @@ STEXI
187 @table @option
188 ETEXI
189
190+DEF("id", HAS_ARG, QEMU_OPTION_id,
191+ "-id n set the VMID\n", QEMU_ARCH_ALL)
192+
193 DEF("fda", HAS_ARG, QEMU_OPTION_fda,
194 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
195 DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
196diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
197index 44ac2fa..480a1ee 100644
198--- a/ui/vnc-auth-vencrypt.c
199+++ b/ui/vnc-auth-vencrypt.c
b07d35a5 200@@ -28,6 +28,107 @@
ca0fe5f5 201 #include "vnc.h"
b07d35a5 202 #include "qapi/error.h"
ca0fe5f5
WB
203 #include "qemu/main-loop.h"
204+#include "qemu/sockets.h"
205+
206+static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
207+{
208+ const char *err = NULL;
209+ char username[256];
210+ char passwd[512];
211+
212+ char clientip[256];
213+ clientip[0] = 0;
214+ struct sockaddr_in client;
215+ socklen_t addrlen = sizeof(client);
216+ if (getpeername(vs->csock, &client, &addrlen) == 0) {
217+ inet_ntop(client.sin_family, &client.sin_addr,
218+ clientip, sizeof(clientip));
219+ }
220+
221+ if ((len != (vs->username_len + vs->password_len)) ||
222+ (vs->username_len >= (sizeof(username)-1)) ||
223+ (vs->password_len >= (sizeof(passwd)-1)) ) {
224+ err = "Got unexpected data length";
225+ goto err;
226+ }
227+
228+ strncpy(username, (char *)data, vs->username_len);
229+ username[vs->username_len] = 0;
230+ strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
231+ passwd[vs->password_len] = 0;
232+
233+ VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
234+
235+ if (pve_auth_verify(clientip, username, passwd) == 0) {
236+ vnc_write_u32(vs, 0); /* Accept auth completion */
237+ start_client_init(vs);
238+ return 0;
239+ }
240+
241+ err = "Authentication failed";
242+err:
243+ if (err) {
244+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
245+ vnc_write_u32(vs, 1); /* Reject auth */
246+ if (vs->minor >= 8) {
247+ int elen = strlen(err);
248+ vnc_write_u32(vs, elen);
249+ vnc_write(vs, err, elen);
250+ }
251+ }
252+ vnc_flush(vs);
253+ vnc_client_error(vs);
254+
255+ return 0;
256+
257+}
258+
259+static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
260+{
261+ uint32_t ulen = read_u32(data, 0);
262+ uint32_t pwlen = read_u32(data, 4);
263+ const char *err = NULL;
264+
265+ VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
266+
267+ if (!ulen) {
268+ err = "No User name.";
269+ goto err;
270+ }
271+ if (ulen >= 255) {
272+ err = "User name too long.";
273+ goto err;
274+ }
275+ if (!pwlen) {
276+ err = "Password too short";
277+ goto err;
278+ }
279+ if (pwlen >= 511) {
280+ err = "Password too long.";
281+ goto err;
282+ }
283+
284+ vs->username_len = ulen;
285+ vs->password_len = pwlen;
286+
287+ vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
288+
289+ return 0;
290+err:
291+ if (err) {
292+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
293+ vnc_write_u32(vs, 1); /* Reject auth */
294+ if (vs->minor >= 8) {
295+ int elen = strlen(err);
296+ vnc_write_u32(vs, elen);
297+ vnc_write(vs, err, elen);
298+ }
299+ }
300+ vnc_flush(vs);
301+ vnc_client_error(vs);
302+
303+ return 0;
304+}
305
306 static void start_auth_vencrypt_subauth(VncState *vs)
307 {
308@@ -37,6 +138,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
309 start_client_init(vs);
310 break;
311
312+ case VNC_AUTH_VENCRYPT_TLSPLAIN:
313+ case VNC_AUTH_VENCRYPT_X509PLAIN:
314+ VNC_DEBUG("Start TLS auth PLAIN\n");
315+ vnc_read_when(vs, protocol_client_auth_plain_start, 8);
316+ break;
317+
318+ case VNC_AUTH_VENCRYPT_PLAIN:
319+ VNC_DEBUG("Start auth PLAIN\n");
320+ vnc_read_when(vs, protocol_client_auth_plain_start, 8);
321+ break;
322+
323 case VNC_AUTH_VENCRYPT_TLSVNC:
324 case VNC_AUTH_VENCRYPT_X509VNC:
325 VNC_DEBUG("Start TLS auth VNC\n");
b07d35a5 326@@ -87,44 +199,63 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
ca0fe5f5
WB
327 {
328 int auth = read_u32(data, 0);
329
330- if (auth != vs->subauth) {
331+ if (auth != vs->subauth && auth != VNC_AUTH_VENCRYPT_PLAIN) {
332 VNC_DEBUG("Rejecting auth %d\n", auth);
333 vnc_write_u8(vs, 0); /* Reject auth */
334 vnc_flush(vs);
335 vnc_client_error(vs);
336 } else {
337- Error *err = NULL;
b07d35a5 338- QIOChannelTLS *tls;
ca0fe5f5
WB
339- VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth);
340- vnc_write_u8(vs, 1); /* Accept auth */
341- vnc_flush(vs);
b07d35a5
TL
342-
343- if (vs->ioc_tag) {
344- g_source_remove(vs->ioc_tag);
345- vs->ioc_tag = 0;
ca0fe5f5
WB
346+ if (auth == VNC_AUTH_VENCRYPT_PLAIN) {
347+ vs->subauth = auth;
348+ start_auth_vencrypt_subauth(vs);
349 }
350+ else
351+ {
352+ Error *err = NULL;
b07d35a5 353+ QIOChannelTLS *tls;
ca0fe5f5
WB
354+ VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth);
355+ vnc_write_u8(vs, 1); /* Accept auth */
356+ vnc_flush(vs);
b07d35a5
TL
357
358- tls = qio_channel_tls_new_server(
359- vs->ioc,
360- vs->vd->tlscreds,
361- vs->vd->tlsaclname,
362- &err);
363- if (!tls) {
364- VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
365- error_free(err);
366- vnc_client_error(vs);
367- return 0;
368- }
369+ if (vs->ioc_tag) {
370+ g_source_remove(vs->ioc_tag);
371+ vs->ioc_tag = 0;
372+ }
373
374- VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
375- object_unref(OBJECT(vs->ioc));
376- vs->ioc = QIO_CHANNEL(tls);
377- vs->tls = qio_channel_tls_get_session(tls);
378+ tls = qio_channel_tls_new_server(
379+ vs->ioc,
380+ vs->vd->tlscreds,
381+ vs->vd->tlsaclname,
382+ &err);
383+ if (!tls) {
384+ VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
ca0fe5f5
WB
385+ error_free(err);
386+ vnc_client_error(vs);
387+ return 0;
b07d35a5
TL
388+ vs->tls = qcrypto_tls_session_new(vs->vd->tlscreds,
389+ NULL,
390+ vs->vd->tlsaclname,
391+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
392+ &err);
393+ if (!vs->tls) {
394+ VNC_DEBUG("Failed to setup TLS %s\n",
395+ error_get_pretty(err));
396+ error_free(err);
397+ vnc_client_error(vs);
398+ return 0;
399+ }
ca0fe5f5
WB
400+ }
401
b07d35a5
TL
402- qio_channel_tls_handshake(tls,
403- vnc_tls_handshake_done,
404- vs,
405- NULL);
ca0fe5f5 406+ VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
b07d35a5
TL
407+ object_unref(OBJECT(vs->ioc));
408+ vs->ioc = QIO_CHANNEL(tls);
409+ vs->tls = qio_channel_tls_get_session(tls);
410+
411+ qio_channel_tls_handshake(tls,
412+ vnc_tls_handshake_done,
413+ vs,
414+ NULL);
415+ }
ca0fe5f5
WB
416 }
417 return 0;
b07d35a5
TL
418 }
419@@ -138,10 +269,11 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
ca0fe5f5
WB
420 vnc_flush(vs);
421 vnc_client_error(vs);
422 } else {
423- VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
424+ VNC_DEBUG("Sending allowed auths %d %d\n", vs->subauth, VNC_AUTH_VENCRYPT_PLAIN);
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
434index ba99636..612cab2 100644
435--- a/ui/vnc.c
436+++ b/ui/vnc.c
437@@ -54,6 +54,125 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
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
563@@ -3427,11 +3546,17 @@ vnc_display_setup_auth(VncDisplay *vs,
564 if (object_dynamic_cast(OBJECT(vs->tlscreds),
565 TYPE_QCRYPTO_TLS_CREDS_X509)) {
566 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
567- vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
568+ if (vs->tlscreds->pve)
569+ vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
570+ else
571+ vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
572 } else if (object_dynamic_cast(OBJECT(vs->tlscreds),
573 TYPE_QCRYPTO_TLS_CREDS_ANON)) {
574 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
575- vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
576+ if (vs->tlscreds->pve)
577+ vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
578+ else
579+ vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
580 } else {
581 error_setg(errp,
582 "Unsupported TLS cred type %s",
583@@ -3522,6 +3647,7 @@ vnc_display_create_creds(bool x509,
584 bool x509verify,
585 const char *dir,
586 const char *id,
587+ bool pve,
588 Error **errp)
589 {
590 gchar *credsid = g_strdup_printf("tlsvnc%s", id);
591@@ -3537,6 +3663,7 @@ vnc_display_create_creds(bool x509,
592 "endpoint", "server",
593 "dir", dir,
594 "verify-peer", x509verify ? "yes" : "no",
595+ "pve", pve ? "yes" : "no",
596 NULL);
597 } else {
598 creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON,
599@@ -3544,6 +3671,7 @@ vnc_display_create_creds(bool x509,
600 credsid,
601 &err,
602 "endpoint", "server",
603+ "pve", pve ? "yes" : "no",
604 NULL);
605 }
606
607@@ -3730,12 +3858,17 @@ void vnc_display_open(const char *id, Error **errp)
608 }
609 } else {
610 const char *path;
611- bool tls = false, x509 = false, x509verify = false;
612+ bool tls = false, x509 = false, x509verify = false, pve = false;
613 tls = qemu_opt_get_bool(opts, "tls", false);
614 path = qemu_opt_get(opts, "x509");
615 if (tls || path) {
616 if (path) {
617 x509 = true;
618+ if (!strcmp(path, "on")) {
619+ /* magic to default to /etc/pve */
620+ path = "/etc/pve";
621+ pve = true;
622+ }
623 } else {
624 path = qemu_opt_get(opts, "x509verify");
625 if (path) {
626@@ -3747,6 +3880,7 @@ void vnc_display_open(const char *id, Error **errp)
627 x509verify,
628 path,
629 vs->id,
630+ pve,
631 errp);
632 if (!vs->tlscreds) {
633 goto fail;
634diff --git a/ui/vnc.h b/ui/vnc.h
635index 2863f58..1c4fee2 100644
636--- a/ui/vnc.h
637+++ b/ui/vnc.h
638@@ -275,6 +275,8 @@ struct VncState
639 int auth;
640 int subauth; /* Used by VeNCrypt */
641 char challenge[VNC_AUTH_CHALLENGE_SIZE];
642+ int username_len;
643+ int password_len;
b07d35a5 644 QCryptoTLSSession *tls; /* Borrowed pointer from channel, don't free */
ca0fe5f5
WB
645 #ifdef CONFIG_VNC_SASL
646 VncStateSASL sasl;
647@@ -578,4 +580,6 @@ int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
648 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
649 void vnc_zrle_clear(VncState *vs);
650
651+int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
652+
653 #endif /* __QEMU_VNC_H */
654diff --git a/vl.c b/vl.c
655index 63c6798..e8034b0 100644
656--- a/vl.c
657+++ b/vl.c
658@@ -2973,6 +2973,7 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
659 int main(int argc, char **argv, char **envp)
660 {
661 int i;
662+ long int vm_id_long = 0;
663 int snapshot, linux_boot;
664 const char *initrd_filename;
665 const char *kernel_filename, *kernel_cmdline;
666@@ -3736,6 +3737,14 @@ int main(int argc, char **argv, char **envp)
667 exit(1);
668 }
669 break;
670+ case QEMU_OPTION_id:
671+ vm_id_long = strtol(optarg, (char **) &optarg, 10);
672+ if (*optarg != 0 || vm_id_long < 100 || vm_id_long > INT_MAX) {
673+ fprintf(stderr, "Invalid ID\n");
674+ exit(1);
675+ }
676+ pve_auth_setup(vm_id_long);
677+ break;
678 case QEMU_OPTION_vnc:
679 {
680 #ifdef CONFIG_VNC
681--
6822.1.4
683