]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/pve/0030-PVE-VNC-authentication.patch
bump version to 2.9.0-1~rc2+5
[pve-qemu-kvm.git] / debian / patches / pve / 0030-PVE-VNC-authentication.patch
CommitLineData
87ba737b 1From d55b3d4bca482ded41c0c1489626e426007e786c Mon Sep 17 00:00:00 2001
ca0fe5f5
WB
2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3Date: Mon, 11 Jan 2016 10:40:31 +0100
adeb0c7a 4Subject: [PATCH 30/48] PVE VNC authentication
ca0fe5f5
WB
5
6---
b07d35a5 7 crypto/tlscreds.c | 47 +++++++++++
ca0fe5f5 8 crypto/tlscredspriv.h | 2 +
1a91ab45 9 crypto/tlscredsx509.c | 13 +--
ca0fe5f5
WB
10 crypto/tlssession.c | 1 +
11 include/crypto/tlscreds.h | 1 +
12 include/ui/console.h | 1 +
13 qemu-options.hx | 3 +
1a91ab45 14 ui/vnc-auth-vencrypt.c | 196 ++++++++++++++++++++++++++++++++++++++--------
b07d35a5
TL
15 ui/vnc.c | 140 ++++++++++++++++++++++++++++++++-
16 ui/vnc.h | 4 +
ca0fe5f5 17 vl.c | 9 +++
1a91ab45 18 11 files changed, 376 insertions(+), 41 deletions(-)
ca0fe5f5
WB
19
20diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
68a30562 21index a896553..e9ae13c 100644
ca0fe5f5
WB
22--- a/crypto/tlscreds.c
23+++ b/crypto/tlscreds.c
6fb04df7 24@@ -158,6 +158,33 @@ qcrypto_tls_creds_prop_get_verify(Object *obj,
ca0fe5f5
WB
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)
68a30562 58@@ -250,6 +277,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 85diff --git a/crypto/tlscredspriv.h b/crypto/tlscredspriv.h
68a30562 86index 13e9b6c..0356acc 100644
ca0fe5f5
WB
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
68a30562 97 #endif /* QCRYPTO_TLSCREDSPRIV_H */
ca0fe5f5 98diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
1a91ab45 99index 50eb54f..09f7364 100644
ca0fe5f5
WB
100--- a/crypto/tlscredsx509.c
101+++ b/crypto/tlscredsx509.c
68a30562 102@@ -555,22 +555,23 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
ca0fe5f5
WB
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,
68a30562 129@@ -579,13 +580,13 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
ca0fe5f5
WB
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
1a91ab45 147index 96a02de..c453e29 100644
ca0fe5f5
WB
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
68a30562 159index ad47d88..f86d379 100644
ca0fe5f5
WB
160--- a/include/crypto/tlscreds.h
161+++ b/include/crypto/tlscreds.h
68a30562 162@@ -55,6 +55,7 @@ struct QCryptoTLSCreds {
ca0fe5f5
WB
163 #endif
164 bool verifyPeer;
68a30562 165 char *priority;
ca0fe5f5
WB
166+ bool pve;
167 };
168
169
170diff --git a/include/ui/console.h b/include/ui/console.h
1a91ab45 171index d759338..69f010e 100644
ca0fe5f5
WB
172--- a/include/ui/console.h
173+++ b/include/ui/console.h
1a91ab45 174@@ -462,6 +462,7 @@ static inline void cocoa_display_init(DisplayState *ds, int full_screen)
68a30562 175 #endif
ca0fe5f5
WB
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
1a91ab45 183index 10f0e81..fbd1a1c 100644
ca0fe5f5
WB
184--- a/qemu-options.hx
185+++ b/qemu-options.hx
1a91ab45 186@@ -513,6 +513,9 @@ STEXI
ca0fe5f5
WB
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
1a91ab45 197index ffaab57..de1c194 100644
ca0fe5f5
WB
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 {
6fb04df7 308@@ -39,6 +140,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
ca0fe5f5
WB
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");
1a91ab45 326@@ -88,45 +200,64 @@ 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
1a91ab45 374- qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
b07d35a5
TL
375- VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
376- object_unref(OBJECT(vs->ioc));
377- vs->ioc = QIO_CHANNEL(tls);
378- vs->tls = qio_channel_tls_get_session(tls);
379+ tls = qio_channel_tls_new_server(
380+ vs->ioc,
381+ vs->vd->tlscreds,
382+ vs->vd->tlsaclname,
383+ &err);
384+ if (!tls) {
385+ VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
ca0fe5f5
WB
386+ error_free(err);
387+ vnc_client_error(vs);
388+ return 0;
b07d35a5
TL
389+ vs->tls = qcrypto_tls_session_new(vs->vd->tlscreds,
390+ NULL,
391+ vs->vd->tlsaclname,
392+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
393+ &err);
394+ if (!vs->tls) {
395+ VNC_DEBUG("Failed to setup TLS %s\n",
396+ error_get_pretty(err));
397+ error_free(err);
398+ vnc_client_error(vs);
399+ return 0;
400+ }
ca0fe5f5 401+ }
1a91ab45 402+ qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
ca0fe5f5 403
b07d35a5
TL
404- qio_channel_tls_handshake(tls,
405- vnc_tls_handshake_done,
406- vs,
407- NULL);
ca0fe5f5 408+ VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
b07d35a5
TL
409+ object_unref(OBJECT(vs->ioc));
410+ vs->ioc = QIO_CHANNEL(tls);
411+ vs->tls = qio_channel_tls_get_session(tls);
412+
413+ qio_channel_tls_handshake(tls,
414+ vnc_tls_handshake_done,
415+ vs,
416+ NULL);
417+ }
ca0fe5f5
WB
418 }
419 return 0;
b07d35a5 420 }
1a91ab45 421@@ -140,10 +271,11 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
ca0fe5f5
WB
422 vnc_flush(vs);
423 vnc_client_error(vs);
424 } else {
425- VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
426+ VNC_DEBUG("Sending allowed auths %d %d\n", vs->subauth, VNC_AUTH_VENCRYPT_PLAIN);
427 vnc_write_u8(vs, 0); /* Accept version */
428- vnc_write_u8(vs, 1); /* Number of sub-auths */
429+ vnc_write_u8(vs, 2); /* Number of sub-auths */
430 vnc_write_u32(vs, vs->subauth); /* The supported auth */
431+ vnc_write_u32(vs, VNC_AUTH_VENCRYPT_PLAIN); /* Alternative supported auth */
432 vnc_flush(vs);
433 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
434 }
435diff --git a/ui/vnc.c b/ui/vnc.c
1a91ab45 436index 039b3ed..a34ba08 100644
ca0fe5f5
WB
437--- a/ui/vnc.c
438+++ b/ui/vnc.c
1a91ab45 439@@ -56,6 +56,125 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
ca0fe5f5
WB
440 #include "vnc_keysym.h"
441 #include "crypto/cipher.h"
442
443+static int pve_vmid = 0;
444+
445+void pve_auth_setup(int vmid) {
446+ pve_vmid = vmid;
447+}
448+
449+static char *
450+urlencode(char *buf, const char *value)
451+{
452+ static const char *hexchar = "0123456789abcdef";
453+ char *p = buf;
454+ int i;
455+ int l = strlen(value);
456+ for (i = 0; i < l; i++) {
457+ char c = value[i];
458+ if (('a' <= c && c <= 'z') ||
459+ ('A' <= c && c <= 'Z') ||
460+ ('0' <= c && c <= '9')) {
461+ *p++ = c;
462+ } else if (c == 32) {
463+ *p++ = '+';
464+ } else {
465+ *p++ = '%';
466+ *p++ = hexchar[c >> 4];
467+ *p++ = hexchar[c & 15];
468+ }
469+ }
470+ *p = 0;
471+
472+ return p;
473+}
474+
475+int
476+pve_auth_verify(const char *clientip, const char *username, const char *passwd)
477+{
478+ struct sockaddr_in server;
479+
480+ int sfd = socket(AF_INET, SOCK_STREAM, 0);
481+ if (sfd == -1) {
482+ perror("pve_auth_verify: socket failed");
483+ return -1;
484+ }
485+
486+ struct hostent *he;
487+ if ((he = gethostbyname("localhost")) == NULL) {
488+ fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
489+ goto err;
490+ }
491+
492+ memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
493+ server.sin_family = AF_INET;
494+ server.sin_port = htons(85);
495+
496+ if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
497+ perror("pve_auth_verify: error connecting to server");
498+ goto err;
499+ }
500+
501+ char buf[8192];
502+ char form[8192];
503+
504+ char *p = form;
505+ p = urlencode(p, "username");
506+ *p++ = '=';
507+ p = urlencode(p, username);
508+
509+ *p++ = '&';
510+ p = urlencode(p, "password");
511+ *p++ = '=';
512+ p = urlencode(p, passwd);
513+
514+ *p++ = '&';
515+ p = urlencode(p, "path");
516+ *p++ = '=';
517+ char authpath[256];
518+ sprintf(authpath, "/vms/%d", pve_vmid);
519+ p = urlencode(p, authpath);
520+
521+ *p++ = '&';
522+ p = urlencode(p, "privs");
523+ *p++ = '=';
524+ p = urlencode(p, "VM.Console");
525+
526+ sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
527+ "Host: localhost:85\n"
528+ "Connection: close\n"
529+ "PVEClientIP: %s\n"
530+ "Content-Type: application/x-www-form-urlencoded\n"
531+ "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form);
532+ ssize_t len = strlen(buf);
533+ ssize_t sb = send(sfd, buf, len, 0);
534+ if (sb < 0) {
535+ perror("pve_auth_verify: send failed");
536+ goto err;
537+ }
538+ if (sb != len) {
539+ fprintf(stderr, "pve_auth_verify: partial send error\n");
540+ goto err;
541+ }
542+
543+ len = recv(sfd, buf, sizeof(buf) - 1, 0);
544+ if (len < 0) {
545+ perror("pve_auth_verify: recv failed");
546+ goto err;
547+ }
548+
549+ buf[len] = 0;
550+
551+ //printf("DATA:%s\n", buf);
552+
553+ shutdown(sfd, SHUT_RDWR);
554+
555+ return strncmp(buf, "HTTP/1.1 200 OK", 15);
556+
557+err:
558+ shutdown(sfd, SHUT_RDWR);
559+ return -1;
560+}
561+
562 static QTAILQ_HEAD(, VncDisplay) vnc_displays =
563 QTAILQ_HEAD_INITIALIZER(vnc_displays);
564
1a91ab45
WB
565@@ -3350,10 +3469,16 @@ vnc_display_setup_auth(int *auth,
566 if (password) {
567 if (is_x509) {
ca0fe5f5 568 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
1a91ab45
WB
569- *subauth = VNC_AUTH_VENCRYPT_X509VNC;
570+ if (tlscreds->pve)
571+ *subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
ca0fe5f5 572+ else
1a91ab45
WB
573+ *subauth = VNC_AUTH_VENCRYPT_X509VNC;
574 } else {
ca0fe5f5 575 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
1a91ab45
WB
576- *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
577+ if (tlscreds->pve)
578+ *subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
ca0fe5f5 579+ else
1a91ab45
WB
580+ *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
581 }
582
583 } else if (sasl) {
584@@ -3387,6 +3512,7 @@ vnc_display_create_creds(bool x509,
ca0fe5f5
WB
585 bool x509verify,
586 const char *dir,
587 const char *id,
588+ bool pve,
589 Error **errp)
590 {
591 gchar *credsid = g_strdup_printf("tlsvnc%s", id);
1a91ab45 592@@ -3402,6 +3528,7 @@ vnc_display_create_creds(bool x509,
ca0fe5f5
WB
593 "endpoint", "server",
594 "dir", dir,
595 "verify-peer", x509verify ? "yes" : "no",
596+ "pve", pve ? "yes" : "no",
597 NULL);
598 } else {
599 creds = object_new_with_props(TYPE_QCRYPTO_TLS_CREDS_ANON,
1a91ab45 600@@ -3409,6 +3536,7 @@ vnc_display_create_creds(bool x509,
ca0fe5f5
WB
601 credsid,
602 &err,
603 "endpoint", "server",
604+ "pve", pve ? "yes" : "no",
605 NULL);
606 }
607
1a91ab45 608@@ -3876,12 +4004,17 @@ void vnc_display_open(const char *id, Error **errp)
ca0fe5f5
WB
609 }
610 } else {
611 const char *path;
612- bool tls = false, x509 = false, x509verify = false;
613+ bool tls = false, x509 = false, x509verify = false, pve = false;
614 tls = qemu_opt_get_bool(opts, "tls", false);
615 path = qemu_opt_get(opts, "x509");
616 if (tls || path) {
617 if (path) {
618 x509 = true;
619+ if (!strcmp(path, "on")) {
620+ /* magic to default to /etc/pve */
621+ path = "/etc/pve";
622+ pve = true;
623+ }
624 } else {
625 path = qemu_opt_get(opts, "x509verify");
626 if (path) {
1a91ab45 627@@ -3893,6 +4026,7 @@ void vnc_display_open(const char *id, Error **errp)
ca0fe5f5
WB
628 x509verify,
629 path,
1a91ab45 630 vd->id,
ca0fe5f5
WB
631+ pve,
632 errp);
1a91ab45 633 if (!vd->tlscreds) {
ca0fe5f5
WB
634 goto fail;
635diff --git a/ui/vnc.h b/ui/vnc.h
1a91ab45 636index 694cf32..78d622a 100644
ca0fe5f5
WB
637--- a/ui/vnc.h
638+++ b/ui/vnc.h
1a91ab45 639@@ -284,6 +284,8 @@ struct VncState
ca0fe5f5
WB
640 int auth;
641 int subauth; /* Used by VeNCrypt */
642 char challenge[VNC_AUTH_CHALLENGE_SIZE];
643+ int username_len;
644+ int password_len;
b07d35a5 645 QCryptoTLSSession *tls; /* Borrowed pointer from channel, don't free */
ca0fe5f5
WB
646 #ifdef CONFIG_VNC_SASL
647 VncStateSASL sasl;
68a30562 648@@ -577,4 +579,6 @@ int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
ca0fe5f5
WB
649 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
650 void vnc_zrle_clear(VncState *vs);
651
652+int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
653+
68a30562 654 #endif /* QEMU_VNC_H */
ca0fe5f5 655diff --git a/vl.c b/vl.c
1a91ab45 656index d0780a4..2496b06 100644
ca0fe5f5
WB
657--- a/vl.c
658+++ b/vl.c
1a91ab45 659@@ -2947,6 +2947,7 @@ static int qemu_read_default_config_file(void)
ca0fe5f5
WB
660 int main(int argc, char **argv, char **envp)
661 {
662 int i;
663+ long int vm_id_long = 0;
664 int snapshot, linux_boot;
665 const char *initrd_filename;
666 const char *kernel_filename, *kernel_cmdline;
1a91ab45 667@@ -3774,6 +3775,14 @@ int main(int argc, char **argv, char **envp)
ca0fe5f5
WB
668 exit(1);
669 }
670 break;
671+ case QEMU_OPTION_id:
672+ vm_id_long = strtol(optarg, (char **) &optarg, 10);
673+ if (*optarg != 0 || vm_id_long < 100 || vm_id_long > INT_MAX) {
674+ fprintf(stderr, "Invalid ID\n");
675+ exit(1);
676+ }
677+ pve_auth_setup(vm_id_long);
678+ break;
679 case QEMU_OPTION_vnc:
68a30562
WB
680 vnc_parse(optarg, &error_fatal);
681 break;
ca0fe5f5
WB
682--
6832.1.4
684