]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/pve-auth.patch
Two more fixes
[pve-qemu-kvm.git] / debian / patches / pve-auth.patch
CommitLineData
58117ea6
WB
1Index: 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
5@@ -411,6 +411,9 @@
6 @table @option
7 ETEXI
8
9+DEF("id", HAS_ARG, QEMU_OPTION_id,
10+ "-id n set the VMID\n", QEMU_ARCH_ALL)
11+
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)
15Index: new/vl.c
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
19@@ -2730,6 +2730,7 @@
20 int main(int argc, char **argv, char **envp)
21 {
22 int i;
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 @@
28 exit(1);
29 }
30 break;
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");
35+ exit(1);
36+ }
37+ pve_auth_setup(vm_id_long);
38+ break;
39 case QEMU_OPTION_vnc:
432a6eb5 40 {
58117ea6 41 #ifdef CONFIG_VNC
58117ea6
WB
42Index: 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
46@@ -328,6 +328,7 @@
47 void cocoa_display_init(DisplayState *ds, int full_screen);
48
49 /* vnc.c */
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);
4676c0af
DM
54Index: new/ui/vnc.c
55===================================================================
24bb7da3
DM
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
58117ea6 58@@ -48,6 +48,125 @@
4676c0af 59 #include "vnc_keysym.h"
432a6eb5 60 #include "crypto/cipher.h"
4676c0af
DM
61
62+static int pve_vmid = 0;
63+
64+void pve_auth_setup(int vmid) {
65+ pve_vmid = vmid;
66+}
67+
68+static char *
69+urlencode(char *buf, const char *value)
70+{
71+ static const char *hexchar = "0123456789abcdef";
72+ char *p = buf;
73+ int i;
74+ int l = strlen(value);
75+ for (i = 0; i < l; i++) {
76+ char c = value[i];
77+ if (('a' <= c && c <= 'z') ||
78+ ('A' <= c && c <= 'Z') ||
79+ ('0' <= c && c <= '9')) {
80+ *p++ = c;
81+ } else if (c == 32) {
82+ *p++ = '+';
83+ } else {
84+ *p++ = '%';
85+ *p++ = hexchar[c >> 4];
86+ *p++ = hexchar[c & 15];
87+ }
88+ }
89+ *p = 0;
90+
91+ return p;
92+}
93+
94+int
95+pve_auth_verify(const char *clientip, const char *username, const char *passwd)
96+{
97+ struct sockaddr_in server;
98+
99+ int sfd = socket(AF_INET, SOCK_STREAM, 0);
100+ if (sfd == -1) {
101+ perror("pve_auth_verify: socket failed");
102+ return -1;
103+ }
104+
105+ struct hostent *he;
106+ if ((he = gethostbyname("localhost")) == NULL) {
107+ fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
108+ goto err;
109+ }
110+
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);
114+
115+ if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
116+ perror("pve_auth_verify: error connecting to server");
117+ goto err;
118+ }
119+
120+ char buf[8192];
121+ char form[8192];
122+
123+ char *p = form;
124+ p = urlencode(p, "username");
125+ *p++ = '=';
126+ p = urlencode(p, username);
127+
128+ *p++ = '&';
129+ p = urlencode(p, "password");
130+ *p++ = '=';
131+ p = urlencode(p, passwd);
132+
133+ *p++ = '&';
134+ p = urlencode(p, "path");
135+ *p++ = '=';
136+ char authpath[256];
137+ sprintf(authpath, "/vms/%d", pve_vmid);
138+ p = urlencode(p, authpath);
139+
140+ *p++ = '&';
141+ p = urlencode(p, "privs");
142+ *p++ = '=';
143+ p = urlencode(p, "VM.Console");
144+
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);
153+ if (sb < 0) {
154+ perror("pve_auth_verify: send failed");
155+ goto err;
156+ }
157+ if (sb != len) {
158+ fprintf(stderr, "pve_auth_verify: partial send error\n");
159+ goto err;
160+ }
161+
162+ len = recv(sfd, buf, sizeof(buf) - 1, 0);
163+ if (len < 0) {
164+ perror("pve_auth_verify: recv failed");
165+ goto err;
166+ }
167+
168+ buf[len] = 0;
169+
170+ //printf("DATA:%s\n", buf);
171+
172+ shutdown(sfd, SHUT_RDWR);
173+
174+ return strncmp(buf, "HTTP/1.1 200 OK", 15);
175+
176+err:
177+ shutdown(sfd, SHUT_RDWR);
178+ return -1;
179+}
180+
58117ea6
WB
181 static QTAILQ_HEAD(, VncDisplay) vnc_displays =
182 QTAILQ_HEAD_INITIALIZER(vnc_displays);
4676c0af 183
58117ea6 184@@ -3393,10 +3512,10 @@
4676c0af 185 }
4676c0af
DM
186 if (x509) {
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;
190 } else {
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;
194 }
195 } else {
58117ea6
WB
196 VNC_DEBUG("Initializing VNC server with password auth\n");
197@@ -3557,7 +3676,14 @@
198 vs->tls.x509verify = true;
199 }
200 }
201- if (path) {
202+ if (path && strcmp(path, "on") == 0) {
203+ x509 = true;
204+ tls = true;
205+ if (pve_tls_set_x509_creds_dir(vs) < 0) {
206+ error_setg(errp, "No certificate path provided");
207+ goto fail;
208+ }
209+ } else if (path) {
210 x509 = true;
211 if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
212 error_setg(errp, "Failed to find x509 certificates/keys in %s",
4676c0af
DM
213Index: new/ui/vnc-auth-vencrypt.c
214===================================================================
24bb7da3
DM
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
074210ad 217@@ -26,6 +26,107 @@
4676c0af
DM
218
219 #include "vnc.h"
074210ad
DM
220 #include "qemu/main-loop.h"
221+#include "qemu/sockets.h"
222+
4676c0af
DM
223+static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
224+{
225+ const char *err = NULL;
226+ char username[256];
227+ char passwd[512];
228+
229+ char clientip[256];
230+ clientip[0] = 0;
231+ struct sockaddr_in client;
232+ socklen_t addrlen = sizeof(client);
233+ if (getpeername(vs->csock, &client, &addrlen) == 0) {
07a7849d 234+ inet_ntop(client.sin_family, &client.sin_addr,
4676c0af
DM
235+ clientip, sizeof(clientip));
236+ }
237+
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";
242+ goto err;
243+ }
244+
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;
249+
250+ VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
251+
252+ if (pve_auth_verify(clientip, username, passwd) == 0) {
253+ vnc_write_u32(vs, 0); /* Accept auth completion */
254+ start_client_init(vs);
255+ return 0;
256+ }
257+
258+ err = "Authentication failed";
259+err:
260+ if (err) {
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);
267+ }
268+ }
269+ vnc_flush(vs);
270+ vnc_client_error(vs);
271+
272+ return 0;
273+
274+}
275+
276+static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
277+{
278+ uint32_t ulen = read_u32(data, 0);
279+ uint32_t pwlen = read_u32(data, 4);
280+ const char *err = NULL;
281+
282+ VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
283+
284+ if (!ulen) {
285+ err = "No User name.";
286+ goto err;
287+ }
288+ if (ulen >= 255) {
289+ err = "User name too long.";
290+ goto err;
291+ }
292+ if (!pwlen) {
293+ err = "Password too short";
294+ goto err;
295+ }
296+ if (pwlen >= 511) {
297+ err = "Password too long.";
298+ goto err;
299+ }
300+
301+ vs->username_len = ulen;
302+ vs->password_len = pwlen;
303+
304+ vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
305+
306+ return 0;
307+err:
308+ if (err) {
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);
315+ }
316+ }
317+ vnc_flush(vs);
318+ vnc_client_error(vs);
319+
320+ return 0;
321+}
322
323 static void start_auth_vencrypt_subauth(VncState *vs)
324 {
074210ad 325@@ -37,6 +138,12 @@
4676c0af
DM
326 start_client_init(vs);
327 break;
328
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);
333+ break;
334+
335 case VNC_AUTH_VENCRYPT_TLSVNC:
336 case VNC_AUTH_VENCRYPT_X509VNC:
337 VNC_DEBUG("Start TLS auth VNC\n");
338Index: new/ui/vnc.h
339===================================================================
24bb7da3
DM
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
58117ea6
WB
342@@ -288,6 +288,8 @@
343 int auth;
4676c0af 344 int subauth; /* Used by VeNCrypt */
58117ea6 345 char challenge[VNC_AUTH_CHALLENGE_SIZE];
4676c0af
DM
346+ int username_len;
347+ int password_len;
58117ea6 348 #ifdef CONFIG_VNC_TLS
4676c0af
DM
349 VncStateTLS tls;
350 #endif
58117ea6 351@@ -603,4 +605,6 @@
07a7849d
DM
352 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
353 void vnc_zrle_clear(VncState *vs);
354
355+int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
356+
357 #endif /* __QEMU_VNC_H */
4676c0af
DM
358Index: new/ui/vnc-tls.c
359===================================================================
24bb7da3
DM
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
07a7849d 362@@ -302,6 +302,14 @@
4676c0af 363
07a7849d
DM
364 static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
365 {
4676c0af
DM
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,
371+ 0
372+ };
373+
07a7849d
DM
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
377@@ -313,6 +321,11 @@
378 };
379 int rc;
4676c0af 380
07a7849d
DM
381+ rc = gnutls_cipher_set_priority(s, ciphers);
382+ if (rc != GNUTLS_E_SUCCESS) {
383+ return -1;
384+ }
385+
386 rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
387 if (rc != GNUTLS_E_SUCCESS) {
388 return -1;
58117ea6 389@@ -448,6 +460,24 @@
4676c0af
DM
390 return 0;
391 }
392
393+int pve_tls_set_x509_creds_dir(VncDisplay *vd)
394+{
395+ if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
396+ goto cleanup;
397+ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
398+ goto cleanup;
399+ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
400+ goto cleanup;
401+
402+ return 0;
403+
404+ cleanup:
07a7849d
DM
405+ g_free(vd->tls.x509cacert);
406+ g_free(vd->tls.x509cert);
407+ g_free(vd->tls.x509key);
4676c0af
DM
408+ vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
409+ return -1;
410+}
411
412 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
413 const char *certdir)
414Index: new/ui/vnc-tls.h
415===================================================================
24bb7da3
DM
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
58117ea6 418@@ -61,6 +61,8 @@
4676c0af
DM
419
420 int vnc_tls_validate_certificate(VncState *vs);
421
422+int pve_tls_set_x509_creds_dir(VncDisplay *vd);
423+
424 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
425 const char *path);
426