1 Index: new/qemu-options.hx
2 ===================================================================
3 --- new.orig/qemu-options.hx 2014-11-20 06:45:06.000000000 +0100
4 +++ new/qemu-options.hx 2014-11-20 06:50:44.000000000 +0100
9 +DEF("id", HAS_ARG, QEMU_OPTION_id,
10 + "-id n set the VMID\n", QEMU_ARCH_ALL)
12 DEF("fda", HAS_ARG, QEMU_OPTION_fda,
13 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
14 DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
16 ===================================================================
17 --- new.orig/vl.c 2014-11-20 06:45:06.000000000 +0100
18 +++ new/vl.c 2014-11-20 06:50:44.000000000 +0100
20 int main(int argc, char **argv, char **envp)
23 + long int vm_id_long = 0;
24 int snapshot, linux_boot;
25 const char *initrd_filename;
26 const char *kernel_filename, *kernel_cmdline;
27 @@ -3477,6 +3478,14 @@
31 + case QEMU_OPTION_id:
32 + vm_id_long = strtol(optarg, (char **) &optarg, 10);
33 + if (*optarg != 0 || vm_id_long < 100 || vm_id_long > INT_MAX) {
34 + fprintf(stderr, "Invalid ID\n");
37 + pve_auth_setup(vm_id_long);
42 Index: new/include/ui/console.h
43 ===================================================================
44 --- new.orig/include/ui/console.h 2014-11-20 06:45:06.000000000 +0100
45 +++ new/include/ui/console.h 2014-11-20 06:50:55.000000000 +0100
47 void cocoa_display_init(DisplayState *ds, int full_screen);
50 +void pve_auth_setup(int vmid);
51 void vnc_display_init(const char *id);
52 void vnc_display_open(const char *id, Error **errp);
53 void vnc_display_add_client(const char *id, int csock, bool skipauth);
55 ===================================================================
56 --- new.orig/ui/vnc.c 2014-11-20 06:50:51.000000000 +0100
57 +++ new/ui/vnc.c 2014-11-20 06:50:55.000000000 +0100
59 #include "vnc_keysym.h"
60 #include "crypto/cipher.h"
62 +static int pve_vmid = 0;
64 +void pve_auth_setup(int vmid) {
69 +urlencode(char *buf, const char *value)
71 + static const char *hexchar = "0123456789abcdef";
74 + int l = strlen(value);
75 + for (i = 0; i < l; i++) {
77 + if (('a' <= c && c <= 'z') ||
78 + ('A' <= c && c <= 'Z') ||
79 + ('0' <= c && c <= '9')) {
81 + } else if (c == 32) {
85 + *p++ = hexchar[c >> 4];
86 + *p++ = hexchar[c & 15];
95 +pve_auth_verify(const char *clientip, const char *username, const char *passwd)
97 + struct sockaddr_in server;
99 + int sfd = socket(AF_INET, SOCK_STREAM, 0);
101 + perror("pve_auth_verify: socket failed");
105 + struct hostent *he;
106 + if ((he = gethostbyname("localhost")) == NULL) {
107 + fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
111 + memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
112 + server.sin_family = AF_INET;
113 + server.sin_port = htons(85);
115 + if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
116 + perror("pve_auth_verify: error connecting to server");
124 + p = urlencode(p, "username");
126 + p = urlencode(p, username);
129 + p = urlencode(p, "password");
131 + p = urlencode(p, passwd);
134 + p = urlencode(p, "path");
136 + char authpath[256];
137 + sprintf(authpath, "/vms/%d", pve_vmid);
138 + p = urlencode(p, authpath);
141 + p = urlencode(p, "privs");
143 + p = urlencode(p, "VM.Console");
145 + sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
146 + "Host: localhost:85\n"
147 + "Connection: close\n"
148 + "PVEClientIP: %s\n"
149 + "Content-Type: application/x-www-form-urlencoded\n"
150 + "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form);
151 + ssize_t len = strlen(buf);
152 + ssize_t sb = send(sfd, buf, len, 0);
154 + perror("pve_auth_verify: send failed");
158 + fprintf(stderr, "pve_auth_verify: partial send error\n");
162 + len = recv(sfd, buf, sizeof(buf) - 1, 0);
164 + perror("pve_auth_verify: recv failed");
170 + //printf("DATA:%s\n", buf);
172 + shutdown(sfd, SHUT_RDWR);
174 + return strncmp(buf, "HTTP/1.1 200 OK", 15);
177 + shutdown(sfd, SHUT_RDWR);
181 static QTAILQ_HEAD(, VncDisplay) vnc_displays =
182 QTAILQ_HEAD_INITIALIZER(vnc_displays);
184 @@ -3393,10 +3512,10 @@
187 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
188 - vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
189 + vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
191 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
192 - vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
193 + vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
196 VNC_DEBUG("Initializing VNC server with password auth\n");
197 @@ -3557,7 +3676,14 @@
198 vs->tls.x509verify = true;
202 + if (path && strcmp(path, "on") == 0) {
205 + if (pve_tls_set_x509_creds_dir(vs) < 0) {
206 + error_setg(errp, "No certificate path provided");
211 if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
212 error_setg(errp, "Failed to find x509 certificates/keys in %s",
213 Index: new/ui/vnc-auth-vencrypt.c
214 ===================================================================
215 --- new.orig/ui/vnc-auth-vencrypt.c 2014-11-20 06:45:06.000000000 +0100
216 +++ new/ui/vnc-auth-vencrypt.c 2014-11-20 06:50:55.000000000 +0100
220 #include "qemu/main-loop.h"
221 +#include "qemu/sockets.h"
223 +static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
225 + const char *err = NULL;
226 + char username[256];
229 + char clientip[256];
231 + struct sockaddr_in client;
232 + socklen_t addrlen = sizeof(client);
233 + if (getpeername(vs->csock, &client, &addrlen) == 0) {
234 + inet_ntop(client.sin_family, &client.sin_addr,
235 + clientip, sizeof(clientip));
238 + if ((len != (vs->username_len + vs->password_len)) ||
239 + (vs->username_len >= (sizeof(username)-1)) ||
240 + (vs->password_len >= (sizeof(passwd)-1)) ) {
241 + err = "Got unexpected data length";
245 + strncpy(username, (char *)data, vs->username_len);
246 + username[vs->username_len] = 0;
247 + strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
248 + passwd[vs->password_len] = 0;
250 + VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
252 + if (pve_auth_verify(clientip, username, passwd) == 0) {
253 + vnc_write_u32(vs, 0); /* Accept auth completion */
254 + start_client_init(vs);
258 + err = "Authentication failed";
261 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
262 + vnc_write_u32(vs, 1); /* Reject auth */
263 + if (vs->minor >= 8) {
264 + int elen = strlen(err);
265 + vnc_write_u32(vs, elen);
266 + vnc_write(vs, err, elen);
270 + vnc_client_error(vs);
276 +static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
278 + uint32_t ulen = read_u32(data, 0);
279 + uint32_t pwlen = read_u32(data, 4);
280 + const char *err = NULL;
282 + VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
285 + err = "No User name.";
289 + err = "User name too long.";
293 + err = "Password too short";
296 + if (pwlen >= 511) {
297 + err = "Password too long.";
301 + vs->username_len = ulen;
302 + vs->password_len = pwlen;
304 + vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
309 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
310 + vnc_write_u32(vs, 1); /* Reject auth */
311 + if (vs->minor >= 8) {
312 + int elen = strlen(err);
313 + vnc_write_u32(vs, elen);
314 + vnc_write(vs, err, elen);
318 + vnc_client_error(vs);
323 static void start_auth_vencrypt_subauth(VncState *vs)
326 start_client_init(vs);
329 + case VNC_AUTH_VENCRYPT_TLSPLAIN:
330 + case VNC_AUTH_VENCRYPT_X509PLAIN:
331 + VNC_DEBUG("Start TLS auth PLAIN\n");
332 + vnc_read_when(vs, protocol_client_auth_plain_start, 8);
335 case VNC_AUTH_VENCRYPT_TLSVNC:
336 case VNC_AUTH_VENCRYPT_X509VNC:
337 VNC_DEBUG("Start TLS auth VNC\n");
339 ===================================================================
340 --- new.orig/ui/vnc.h 2014-11-20 06:45:06.000000000 +0100
341 +++ new/ui/vnc.h 2014-11-20 06:50:55.000000000 +0100
344 int subauth; /* Used by VeNCrypt */
345 char challenge[VNC_AUTH_CHALLENGE_SIZE];
348 #ifdef CONFIG_VNC_TLS
352 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
353 void vnc_zrle_clear(VncState *vs);
355 +int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
357 #endif /* __QEMU_VNC_H */
358 Index: new/ui/vnc-tls.c
359 ===================================================================
360 --- new.orig/ui/vnc-tls.c 2014-11-20 06:45:06.000000000 +0100
361 +++ new/ui/vnc-tls.c 2014-11-20 06:50:55.000000000 +0100
364 static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
366 + /* optimize for speed */
367 + static const int ciphers[] = {
368 + GNUTLS_CIPHER_ARCFOUR_128,
369 + GNUTLS_CIPHER_AES_128_CBC,
370 + GNUTLS_CIPHER_3DES_CBC,
374 static const int cert_types[] = { GNUTLS_CRT_X509, 0 };
375 static const int protocols[] = {
376 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
381 + rc = gnutls_cipher_set_priority(s, ciphers);
382 + if (rc != GNUTLS_E_SUCCESS) {
386 rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
387 if (rc != GNUTLS_E_SUCCESS) {
393 +int pve_tls_set_x509_creds_dir(VncDisplay *vd)
395 + if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
397 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
399 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
405 + g_free(vd->tls.x509cacert);
406 + g_free(vd->tls.x509cert);
407 + g_free(vd->tls.x509key);
408 + vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
412 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
414 Index: new/ui/vnc-tls.h
415 ===================================================================
416 --- new.orig/ui/vnc-tls.h 2014-11-20 06:45:06.000000000 +0100
417 +++ new/ui/vnc-tls.h 2014-11-20 06:50:55.000000000 +0100
420 int vnc_tls_validate_certificate(VncState *vs);
422 +int pve_tls_set_x509_creds_dir(VncDisplay *vd);
424 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,