]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/pve-auth.patch
update to qemu-kvm-1.1-rc2
[pve-qemu-kvm.git] / debian / patches / pve-auth.patch
CommitLineData
4676c0af
DM
1Index: new/ui/vnc.c
2===================================================================
24565bc0
DM
3--- new.orig/ui/vnc.c 2012-03-13 08:10:11.000000000 +0100
4+++ new/ui/vnc.c 2012-03-13 08:10:20.000000000 +0100
07a7849d 5@@ -42,6 +42,125 @@
4676c0af
DM
6 #include "vnc_keysym.h"
7 #include "d3des.h"
8
9+static int pve_vmid = 0;
10+
11+void pve_auth_setup(int vmid) {
12+ pve_vmid = vmid;
13+}
14+
15+static char *
16+urlencode(char *buf, const char *value)
17+{
18+ static const char *hexchar = "0123456789abcdef";
19+ char *p = buf;
20+ int i;
21+ int l = strlen(value);
22+ for (i = 0; i < l; i++) {
23+ char c = value[i];
24+ if (('a' <= c && c <= 'z') ||
25+ ('A' <= c && c <= 'Z') ||
26+ ('0' <= c && c <= '9')) {
27+ *p++ = c;
28+ } else if (c == 32) {
29+ *p++ = '+';
30+ } else {
31+ *p++ = '%';
32+ *p++ = hexchar[c >> 4];
33+ *p++ = hexchar[c & 15];
34+ }
35+ }
36+ *p = 0;
37+
38+ return p;
39+}
40+
41+int
42+pve_auth_verify(const char *clientip, const char *username, const char *passwd)
43+{
44+ struct sockaddr_in server;
45+
46+ int sfd = socket(AF_INET, SOCK_STREAM, 0);
47+ if (sfd == -1) {
48+ perror("pve_auth_verify: socket failed");
49+ return -1;
50+ }
51+
52+ struct hostent *he;
53+ if ((he = gethostbyname("localhost")) == NULL) {
54+ fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
55+ goto err;
56+ }
57+
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);
61+
62+ if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
63+ perror("pve_auth_verify: error connecting to server");
64+ goto err;
65+ }
66+
67+ char buf[8192];
68+ char form[8192];
69+
70+ char *p = form;
71+ p = urlencode(p, "username");
72+ *p++ = '=';
73+ p = urlencode(p, username);
74+
75+ *p++ = '&';
76+ p = urlencode(p, "password");
77+ *p++ = '=';
78+ p = urlencode(p, passwd);
79+
80+ *p++ = '&';
81+ p = urlencode(p, "path");
82+ *p++ = '=';
83+ char authpath[256];
84+ sprintf(authpath, "/vms/%d", pve_vmid);
85+ p = urlencode(p, authpath);
86+
87+ *p++ = '&';
88+ p = urlencode(p, "privs");
89+ *p++ = '=';
90+ p = urlencode(p, "VM.Console");
91+
92+ sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
93+ "Host: localhost:85\n"
94+ "Connection: close\n"
95+ "PVEClientIP: %s\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);
100+ if (sb < 0) {
101+ perror("pve_auth_verify: send failed");
102+ goto err;
103+ }
104+ if (sb != len) {
105+ fprintf(stderr, "pve_auth_verify: partial send error\n");
106+ goto err;
107+ }
108+
109+ len = recv(sfd, buf, sizeof(buf) - 1, 0);
110+ if (len < 0) {
111+ perror("pve_auth_verify: recv failed");
112+ goto err;
113+ }
114+
115+ buf[len] = 0;
116+
117+ //printf("DATA:%s\n", buf);
118+
119+ shutdown(sfd, SHUT_RDWR);
120+
121+ return strncmp(buf, "HTTP/1.1 200 OK", 15);
122+
123+err:
124+ shutdown(sfd, SHUT_RDWR);
125+ return -1;
126+}
127+
128 static VncDisplay *vnc_display; /* needed for info vnc */
129 static DisplayChangeListener *dcl;
130
b4818867 131@@ -1896,7 +2015,7 @@
4676c0af
DM
132 static void set_pixel_conversion(VncState *vs)
133 {
134 if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
135- (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
136+ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
137 !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
138 vs->write_pixels = vnc_write_pixels_copy;
139 vnc_hextile_set_pixel_conversion(vs, 0);
b4818867 140@@ -1982,7 +2101,7 @@
4676c0af
DM
141 vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
142 vnc_write_u8(vs, 0);
143 vnc_write_u16(vs, 1); /* number of rects */
144- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
145+ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
146 ds_get_height(vs->ds), VNC_ENCODING_WMVi);
147 pixel_format_message(vs);
148 vnc_unlock_output(vs);
b4818867 149@@ -2873,7 +2992,7 @@
4676c0af
DM
150 char *vnc_display_local_addr(DisplayState *ds)
151 {
152 VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
153-
154+
155 return vnc_socket_local_addr("%s:%s", vs->lsock);
156 }
157
b4818867 158@@ -2923,6 +3042,7 @@
4676c0af
DM
159 tls = 1; /* Require TLS */
160 } else if (strncmp(options, "x509", 4) == 0) {
161 char *start, *end;
162+ tls = 1; /* Require TLS */
163 x509 = 1; /* Require x509 certificates */
164 if (strncmp(options, "x509verify", 10) == 0)
165 vs->tls.x509verify = 1; /* ...and verify client certs */
b4818867 166@@ -2945,10 +3065,12 @@
4676c0af 167 }
07a7849d 168 g_free(path);
4676c0af
DM
169 } else {
170- fprintf(stderr, "No certificate path provided\n");
07a7849d 171- g_free(vs->display);
4676c0af
DM
172- vs->display = NULL;
173- return -1;
07a7849d 174+ if (pve_tls_set_x509_creds_dir(vs) < 0) {
4676c0af 175+ fprintf(stderr, "No certificate path provided\n");
07a7849d 176+ g_free(vs->display);
4676c0af
DM
177+ vs->display = NULL;
178+ return -1;
179+ }
180 }
181 #endif
182 #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
b4818867 183@@ -3014,10 +3136,10 @@
4676c0af
DM
184 vs->auth = VNC_AUTH_VENCRYPT;
185 if (x509) {
186 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
187- vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
188+ vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
189 } else {
190 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
191- vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
192+ vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
193 }
194 } else {
195 #endif /* CONFIG_VNC_TLS */
196Index: new/ui/vnc-auth-vencrypt.c
197===================================================================
24565bc0
DM
198--- new.orig/ui/vnc-auth-vencrypt.c 2012-03-13 07:26:50.000000000 +0100
199+++ new/ui/vnc-auth-vencrypt.c 2012-03-13 08:10:20.000000000 +0100
4676c0af
DM
200@@ -25,7 +25,107 @@
201 */
202
203 #include "vnc.h"
204+#include "qemu_socket.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) {
07a7849d 217+ inet_ntop(client.sin_family, &client.sin_addr,
4676c0af
DM
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 +137,12 @@
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_TLSVNC:
319 case VNC_AUTH_VENCRYPT_X509VNC:
320 VNC_DEBUG("Start TLS auth VNC\n");
321Index: new/ui/vnc.h
322===================================================================
24565bc0
DM
323--- new.orig/ui/vnc.h 2012-03-13 07:26:50.000000000 +0100
324+++ new/ui/vnc.h 2012-03-13 08:10:20.000000000 +0100
b4818867 325@@ -276,6 +276,8 @@
4676c0af
DM
326 char challenge[VNC_AUTH_CHALLENGE_SIZE];
327 #ifdef CONFIG_VNC_TLS
328 int subauth; /* Used by VeNCrypt */
329+ int username_len;
330+ int password_len;
331 VncStateTLS tls;
332 #endif
333 #ifdef CONFIG_VNC_SASL
b4818867 334@@ -569,4 +571,6 @@
07a7849d
DM
335 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
336 void vnc_zrle_clear(VncState *vs);
337
338+int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
339+
340 #endif /* __QEMU_VNC_H */
4676c0af
DM
341Index: new/ui/vnc-tls.c
342===================================================================
24565bc0
DM
343--- new.orig/ui/vnc-tls.c 2012-03-13 07:26:50.000000000 +0100
344+++ new/ui/vnc-tls.c 2012-03-13 08:10:20.000000000 +0100
07a7849d 345@@ -302,6 +302,14 @@
4676c0af 346
07a7849d
DM
347 static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
348 {
4676c0af
DM
349+ /* optimize for speed */
350+ static const int ciphers[] = {
351+ GNUTLS_CIPHER_ARCFOUR_128,
352+ GNUTLS_CIPHER_AES_128_CBC,
353+ GNUTLS_CIPHER_3DES_CBC,
354+ 0
355+ };
356+
07a7849d
DM
357 static const int cert_types[] = { GNUTLS_CRT_X509, 0 };
358 static const int protocols[] = {
359 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
360@@ -313,6 +321,11 @@
361 };
362 int rc;
4676c0af 363
07a7849d
DM
364+ rc = gnutls_cipher_set_priority(s, ciphers);
365+ if (rc != GNUTLS_E_SUCCESS) {
366+ return -1;
367+ }
368+
369 rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
370 if (rc != GNUTLS_E_SUCCESS) {
371 return -1;
372@@ -449,6 +462,24 @@
4676c0af
DM
373 return 0;
374 }
375
376+int pve_tls_set_x509_creds_dir(VncDisplay *vd)
377+{
378+ if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
379+ goto cleanup;
380+ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
381+ goto cleanup;
382+ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
383+ goto cleanup;
384+
385+ return 0;
386+
387+ cleanup:
07a7849d
DM
388+ g_free(vd->tls.x509cacert);
389+ g_free(vd->tls.x509cert);
390+ g_free(vd->tls.x509key);
4676c0af
DM
391+ vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
392+ return -1;
393+}
394
395 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
396 const char *certdir)
397Index: new/ui/vnc-tls.h
398===================================================================
24565bc0
DM
399--- new.orig/ui/vnc-tls.h 2012-03-13 07:26:50.000000000 +0100
400+++ new/ui/vnc-tls.h 2012-03-13 08:10:20.000000000 +0100
4676c0af
DM
401@@ -68,6 +68,8 @@
402
403 int vnc_tls_validate_certificate(VncState *vs);
404
405+int pve_tls_set_x509_creds_dir(VncDisplay *vd);
406+
407 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
408 const char *path);
409
410Index: new/vl.c
411===================================================================
24565bc0
DM
412--- new.orig/vl.c 2012-03-13 08:09:04.000000000 +0100
413+++ new/vl.c 2012-03-13 08:11:15.000000000 +0100
414@@ -3033,6 +3033,7 @@
4676c0af
DM
415 fprintf(stderr, "Invalid ID\n");
416 exit(1);
24565bc0
DM
417 }
418+ pve_auth_setup(fairsched_id);
419 break;
420 case QEMU_OPTION_cpuunits:
421 cpuunits = atoi(optarg);
a023e148
DM
422Index: new/console.h
423===================================================================
24565bc0
DM
424--- new.orig/console.h 2012-03-13 07:26:50.000000000 +0100
425+++ new/console.h 2012-03-13 08:10:20.000000000 +0100
a023e148
DM
426@@ -371,6 +371,7 @@
427 void cocoa_display_init(DisplayState *ds, int full_screen);
428
429 /* vnc.c */
430+void pve_auth_setup(int vmid);
431 void vnc_display_init(DisplayState *ds);
432 void vnc_display_close(DisplayState *ds);
433 int vnc_display_open(DisplayState *ds, const char *display);