2 ===================================================================
3 --- new.orig/ui/vnc.c 2013-02-12 12:06:38.000000000 +0100
4 +++ new/ui/vnc.c 2013-02-12 12:06:40.000000000 +0100
6 #include "vnc_keysym.h"
9 +static int pve_vmid = 0;
11 +void pve_auth_setup(int vmid) {
16 +urlencode(char *buf, const char *value)
18 + static const char *hexchar = "0123456789abcdef";
21 + int l = strlen(value);
22 + for (i = 0; i < l; i++) {
24 + if (('a' <= c && c <= 'z') ||
25 + ('A' <= c && c <= 'Z') ||
26 + ('0' <= c && c <= '9')) {
28 + } else if (c == 32) {
32 + *p++ = hexchar[c >> 4];
33 + *p++ = hexchar[c & 15];
42 +pve_auth_verify(const char *clientip, const char *username, const char *passwd)
44 + struct sockaddr_in server;
46 + int sfd = socket(AF_INET, SOCK_STREAM, 0);
48 + perror("pve_auth_verify: socket failed");
53 + if ((he = gethostbyname("localhost")) == NULL) {
54 + fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
58 + memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
59 + server.sin_family = AF_INET;
60 + server.sin_port = htons(85);
62 + if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
63 + perror("pve_auth_verify: error connecting to server");
71 + p = urlencode(p, "username");
73 + p = urlencode(p, username);
76 + p = urlencode(p, "password");
78 + p = urlencode(p, passwd);
81 + p = urlencode(p, "path");
84 + sprintf(authpath, "/vms/%d", pve_vmid);
85 + p = urlencode(p, authpath);
88 + p = urlencode(p, "privs");
90 + p = urlencode(p, "VM.Console");
92 + sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
93 + "Host: localhost:85\n"
94 + "Connection: close\n"
96 + "Content-Type: application/x-www-form-urlencoded\n"
97 + "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form);
98 + ssize_t len = strlen(buf);
99 + ssize_t sb = send(sfd, buf, len, 0);
101 + perror("pve_auth_verify: send failed");
105 + fprintf(stderr, "pve_auth_verify: partial send error\n");
109 + len = recv(sfd, buf, sizeof(buf) - 1, 0);
111 + perror("pve_auth_verify: recv failed");
117 + //printf("DATA:%s\n", buf);
119 + shutdown(sfd, SHUT_RDWR);
121 + return strncmp(buf, "HTTP/1.1 200 OK", 15);
124 + shutdown(sfd, SHUT_RDWR);
128 static VncDisplay *vnc_display; /* needed for info vnc */
129 static DisplayChangeListener *dcl;
131 @@ -2025,7 +2144,7 @@
132 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
134 vnc_write_u16(vs, 1); /* number of rects */
135 - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
136 + vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
137 ds_get_height(vs->ds), VNC_ENCODING_WMVi);
138 pixel_format_message(vs);
139 vnc_unlock_output(vs);
140 @@ -2989,7 +3108,7 @@
141 char *vnc_display_local_addr(DisplayState *ds)
143 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
146 return vnc_socket_local_addr("%s:%s", vs->lsock);
149 @@ -3077,6 +3196,7 @@
150 tls = 1; /* Require TLS */
151 } else if (strncmp(options, "x509", 4) == 0) {
153 + tls = 1; /* Require TLS */
154 x509 = 1; /* Require x509 certificates */
155 if (strncmp(options, "x509verify", 10) == 0)
156 vs->tls.x509verify = 1; /* ...and verify client certs */
157 @@ -3097,8 +3217,10 @@
161 - error_setg(errp, "No certificate path provided");
163 + if (pve_tls_set_x509_creds_dir(vs) < 0) {
164 + error_setg(errp, "No certificate path provided");
169 #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
170 @@ -3162,10 +3284,10 @@
171 vs->auth = VNC_AUTH_VENCRYPT;
173 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
174 - vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
175 + vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
177 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
178 - vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
179 + vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
182 #endif /* CONFIG_VNC_TLS */
183 Index: new/ui/vnc-auth-vencrypt.c
184 ===================================================================
185 --- new.orig/ui/vnc-auth-vencrypt.c 2013-02-12 12:05:14.000000000 +0100
186 +++ new/ui/vnc-auth-vencrypt.c 2013-02-12 12:06:40.000000000 +0100
191 +#include "qemu_socket.h"
193 +static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
195 + const char *err = NULL;
196 + char username[256];
199 + char clientip[256];
201 + struct sockaddr_in client;
202 + socklen_t addrlen = sizeof(client);
203 + if (getpeername(vs->csock, &client, &addrlen) == 0) {
204 + inet_ntop(client.sin_family, &client.sin_addr,
205 + clientip, sizeof(clientip));
208 + if ((len != (vs->username_len + vs->password_len)) ||
209 + (vs->username_len >= (sizeof(username)-1)) ||
210 + (vs->password_len >= (sizeof(passwd)-1)) ) {
211 + err = "Got unexpected data length";
215 + strncpy(username, (char *)data, vs->username_len);
216 + username[vs->username_len] = 0;
217 + strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
218 + passwd[vs->password_len] = 0;
220 + VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
222 + if (pve_auth_verify(clientip, username, passwd) == 0) {
223 + vnc_write_u32(vs, 0); /* Accept auth completion */
224 + start_client_init(vs);
228 + err = "Authentication failed";
231 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
232 + vnc_write_u32(vs, 1); /* Reject auth */
233 + if (vs->minor >= 8) {
234 + int elen = strlen(err);
235 + vnc_write_u32(vs, elen);
236 + vnc_write(vs, err, elen);
240 + vnc_client_error(vs);
246 +static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
248 + uint32_t ulen = read_u32(data, 0);
249 + uint32_t pwlen = read_u32(data, 4);
250 + const char *err = NULL;
252 + VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
255 + err = "No User name.";
259 + err = "User name too long.";
263 + err = "Password too short";
266 + if (pwlen >= 511) {
267 + err = "Password too long.";
271 + vs->username_len = ulen;
272 + vs->password_len = pwlen;
274 + vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
279 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
280 + vnc_write_u32(vs, 1); /* Reject auth */
281 + if (vs->minor >= 8) {
282 + int elen = strlen(err);
283 + vnc_write_u32(vs, elen);
284 + vnc_write(vs, err, elen);
288 + vnc_client_error(vs);
293 static void start_auth_vencrypt_subauth(VncState *vs)
296 start_client_init(vs);
299 + case VNC_AUTH_VENCRYPT_TLSPLAIN:
300 + case VNC_AUTH_VENCRYPT_X509PLAIN:
301 + VNC_DEBUG("Start TLS auth PLAIN\n");
302 + vnc_read_when(vs, protocol_client_auth_plain_start, 8);
305 case VNC_AUTH_VENCRYPT_TLSVNC:
306 case VNC_AUTH_VENCRYPT_X509VNC:
307 VNC_DEBUG("Start TLS auth VNC\n");
309 ===================================================================
310 --- new.orig/ui/vnc.h 2013-02-12 12:05:14.000000000 +0100
311 +++ new/ui/vnc.h 2013-02-12 12:06:40.000000000 +0100
313 char challenge[VNC_AUTH_CHALLENGE_SIZE];
314 #ifdef CONFIG_VNC_TLS
315 int subauth; /* Used by VeNCrypt */
320 #ifdef CONFIG_VNC_SASL
322 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
323 void vnc_zrle_clear(VncState *vs);
325 +int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
327 #endif /* __QEMU_VNC_H */
328 Index: new/ui/vnc-tls.c
329 ===================================================================
330 --- new.orig/ui/vnc-tls.c 2013-02-12 12:05:14.000000000 +0100
331 +++ new/ui/vnc-tls.c 2013-02-12 12:06:40.000000000 +0100
334 static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
336 + /* optimize for speed */
337 + static const int ciphers[] = {
338 + GNUTLS_CIPHER_ARCFOUR_128,
339 + GNUTLS_CIPHER_AES_128_CBC,
340 + GNUTLS_CIPHER_3DES_CBC,
344 static const int cert_types[] = { GNUTLS_CRT_X509, 0 };
345 static const int protocols[] = {
346 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
351 + rc = gnutls_cipher_set_priority(s, ciphers);
352 + if (rc != GNUTLS_E_SUCCESS) {
356 rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
357 if (rc != GNUTLS_E_SUCCESS) {
363 +int pve_tls_set_x509_creds_dir(VncDisplay *vd)
365 + if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
367 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
369 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
375 + g_free(vd->tls.x509cacert);
376 + g_free(vd->tls.x509cert);
377 + g_free(vd->tls.x509key);
378 + vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
382 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
384 Index: new/ui/vnc-tls.h
385 ===================================================================
386 --- new.orig/ui/vnc-tls.h 2013-02-12 12:05:14.000000000 +0100
387 +++ new/ui/vnc-tls.h 2013-02-12 12:06:40.000000000 +0100
390 int vnc_tls_validate_certificate(VncState *vs);
392 +int pve_tls_set_x509_creds_dir(VncDisplay *vd);
394 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
398 ===================================================================
399 --- new.orig/vl.c 2013-02-12 12:06:20.000000000 +0100
400 +++ new/vl.c 2013-02-12 12:06:40.000000000 +0100
401 @@ -3595,6 +3595,7 @@
402 fprintf(stderr, "Invalid ID\n");
405 + pve_auth_setup(fairsched_id);
407 case QEMU_OPTION_cpuunits:
408 cpuunits = atoi(optarg);
409 Index: new/include/ui/console.h
410 ===================================================================
411 --- new.orig/include/ui/console.h 2013-02-12 12:05:14.000000000 +0100
412 +++ new/include/ui/console.h 2013-02-12 12:06:40.000000000 +0100
414 void cocoa_display_init(DisplayState *ds, int full_screen);
417 +void pve_auth_setup(int vmid);
418 void vnc_display_init(DisplayState *ds);
419 void vnc_display_open(DisplayState *ds, const char *display, Error **errp);
420 void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);