]> git.proxmox.com Git - pve-qemu.git/blob - 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
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Mon, 11 Jan 2016 10:40:31 +0100
4 Subject: [PATCH] vnc: PVE VNC authentication
5
6 ---
7 crypto/tlscreds.c | 47 ++++++++++++
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 qapi-schema.json | 1 +
14 qemu-options.hx | 3 +
15 ui/vnc-auth-vencrypt.c | 182 ++++++++++++++++++++++++++++++++++++++--------
16 ui/vnc.c | 140 ++++++++++++++++++++++++++++++++++-
17 ui/vnc.h | 4 +
18 vl.c | 9 +++
19 12 files changed, 364 insertions(+), 40 deletions(-)
20
21 diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
22 index 3cd41035bb..e982da3451 100644
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",
79 + &QCryptoTLSCredsEndpoint_lookup,
80 + qcrypto_tls_creds_prop_get_endpoint,
81 + qcrypto_tls_creds_prop_set_endpoint,
82 + NULL);
83 }
84
85
86 diff --git a/crypto/tlscredspriv.h b/crypto/tlscredspriv.h
87 index 13e9b6c0b2..0356acc2c9 100644
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 */
99 diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
100 index 50eb54f6bb..09f7364001 100644
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 }
147 diff --git a/crypto/tlssession.c b/crypto/tlssession.c
148 index 96a02deb69..c453e29cad 100644
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
159 diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
160 index ad47d88be7..f86d379f26 100644
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
171 diff --git a/include/ui/console.h b/include/ui/console.h
172 index 580dfc57ee..383e5c88bd 100644
173 --- a/include/ui/console.h
174 +++ b/include/ui/console.h
175 @@ -466,6 +466,7 @@ static inline void cocoa_display_init(DisplayState *ds, int full_screen)
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);
183 diff --git a/qapi-schema.json b/qapi-schema.json
184 index 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',
195 diff --git a/qemu-options.hx b/qemu-options.hx
196 index 7c054af8f9..07129d55bc 100644
197 --- a/qemu-options.hx
198 +++ b/qemu-options.hx
199 @@ -583,6 +583,9 @@ STEXI
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)
209 diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
210 index 7833631275..c42acd3714 100644
211 --- a/ui/vnc-auth-vencrypt.c
212 +++ b/ui/vnc-auth-vencrypt.c
213 @@ -29,6 +29,108 @@
214 #include "qapi/error.h"
215 #include "qemu/main-loop.h"
216 #include "trace.h"
217 +#include "io/channel-socket.h"
218 +
219 +static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
220 +{
221 + Error *err = NULL;
222 + char username[256];
223 + char passwd[512];
224 +
225 + SocketAddress *clientip = qio_channel_socket_get_remote_address(vs->sioc, &err);
226 + if (err) {
227 + goto err;
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)) ) {
233 + error_setg(&err, "Got unexpected data length");
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 +
244 + if (pve_auth_verify(clientip->u.inet.host, username, passwd) == 0) {
245 + vnc_write_u32(vs, 0); /* Accept auth completion */
246 + start_client_init(vs);
247 + qapi_free_SocketAddress(clientip);
248 + return 0;
249 + }
250 +
251 + error_setg(&err, "Authentication failed");
252 +err:
253 + if (err) {
254 + const char *err_msg = error_get_pretty(err);
255 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err_msg);
256 + vnc_write_u32(vs, 1); /* Reject auth */
257 + if (vs->minor >= 8) {
258 + int elen = strlen(err_msg);
259 + vnc_write_u32(vs, elen);
260 + vnc_write(vs, err_msg, elen);
261 + }
262 + error_free(err);
263 + }
264 + vnc_flush(vs);
265 + vnc_client_error(vs);
266 +
267 + qapi_free_SocketAddress(clientip);
268 +
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 {
322 @@ -39,6 +141,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
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:
339 start_auth_vnc(vs);
340 @@ -90,45 +203,51 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
341 int auth = read_u32(data, 0);
342
343 trace_vnc_auth_vencrypt_subauth(vs, auth);
344 - if (auth != vs->subauth) {
345 + if (auth != vs->subauth && auth != VNC_AUTH_VENCRYPT_PLAIN) {
346 trace_vnc_auth_fail(vs, vs->auth, "Unsupported sub-auth version", "");
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;
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;
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) {
376 - trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
377 - error_get_pretty(err));
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 + }
386 + tls = qio_channel_tls_new_server(
387 + vs->ioc,
388 + vs->vd->tlscreds,
389 + vs->vd->tlsaclname,
390 + &err);
391 + if (!tls) {
392 + trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
393 + error_get_pretty(err));
394 + error_free(err);
395 + vnc_client_error(vs);
396 + return 0;
397 + }
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);
404 + qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
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);
409
410 - qio_channel_tls_handshake(tls,
411 - vnc_tls_handshake_done,
412 - vs,
413 - NULL);
414 + qio_channel_tls_handshake(tls,
415 + vnc_tls_handshake_done,
416 + vs,
417 + NULL);
418 + }
419 }
420 return 0;
421 }
422 @@ -144,8 +263,9 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
423 vnc_client_error(vs);
424 } else {
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 }
433 diff --git a/ui/vnc.c b/ui/vnc.c
434 index 4494cb1dd4..1589cbe1b3 100644
435 --- a/ui/vnc.c
436 +++ b/ui/vnc.c
437 @@ -55,6 +55,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 @@ -3507,10 +3626,16 @@ vnc_display_setup_auth(int *auth,
564 if (password) {
565 if (is_x509) {
566 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
567 - *subauth = VNC_AUTH_VENCRYPT_X509VNC;
568 + if (tlscreds->pve)
569 + *subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
570 + else
571 + *subauth = VNC_AUTH_VENCRYPT_X509VNC;
572 } else {
573 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
574 - *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
575 + if (tlscreds->pve)
576 + *subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
577 + else
578 + *subauth = VNC_AUTH_VENCRYPT_TLSVNC;
579 }
580
581 } else if (sasl) {
582 @@ -3544,6 +3669,7 @@ vnc_display_create_creds(bool x509,
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);
590 @@ -3559,6 +3685,7 @@ vnc_display_create_creds(bool x509,
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,
598 @@ -3566,6 +3693,7 @@ vnc_display_create_creds(bool x509,
599 credsid,
600 &err,
601 "endpoint", "server",
602 + "pve", pve ? "yes" : "no",
603 NULL);
604 }
605
606 @@ -4032,12 +4160,17 @@ void vnc_display_open(const char *id, Error **errp)
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) {
625 @@ -4049,6 +4182,7 @@ void vnc_display_open(const char *id, Error **errp)
626 x509verify,
627 path,
628 vd->id,
629 + pve,
630 errp);
631 if (!vd->tlscreds) {
632 goto fail;
633 diff --git a/ui/vnc.h b/ui/vnc.h
634 index bbda0540a7..8cc6367ed3 100644
635 --- a/ui/vnc.h
636 +++ b/ui/vnc.h
637 @@ -290,6 +290,8 @@ struct VncState
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;
646 @@ -595,4 +597,6 @@ int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
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 */
653 diff --git a/vl.c b/vl.c
654 index 75fde82180..255d989009 100644
655 --- a/vl.c
656 +++ b/vl.c
657 @@ -3096,6 +3096,7 @@ static void register_global_properties(MachineState *ms)
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;
665 @@ -3922,6 +3923,14 @@ int main(int argc, char **argv, char **envp)
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 --
681 2.11.0
682