]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/pve-auth.patch
refresh all quilt patches
[pve-qemu-kvm.git] / debian / patches / pve-auth.patch
1 Index: new/ui/vnc.c
2 ===================================================================
3 --- new.orig/ui/vnc.c 2014-06-17 06:14:54.000000000 +0200
4 +++ new/ui/vnc.c 2014-06-17 06:14:54.000000000 +0200
5 @@ -45,6 +45,125 @@
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
130 static int vnc_cursor_define(VncState *vs);
131 @@ -3146,6 +3265,7 @@
132 tls = 1; /* Require TLS */
133 } else if (strncmp(options, "x509", 4) == 0) {
134 char *start, *end;
135 + tls = 1; /* Require TLS */
136 x509 = 1; /* Require x509 certificates */
137 if (strncmp(options, "x509verify", 10) == 0)
138 vs->tls.x509verify = 1; /* ...and verify client certs */
139 @@ -3166,8 +3286,10 @@
140 }
141 g_free(path);
142 } else {
143 - error_setg(errp, "No certificate path provided");
144 - goto fail;
145 + if (pve_tls_set_x509_creds_dir(vs) < 0) {
146 + error_setg(errp, "No certificate path provided");
147 + goto fail;
148 + }
149 }
150 #endif
151 #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
152 @@ -3240,10 +3362,10 @@
153 vs->auth = VNC_AUTH_VENCRYPT;
154 if (x509) {
155 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
156 - vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
157 + vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
158 } else {
159 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
160 - vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
161 + vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
162 }
163 } else {
164 #endif /* CONFIG_VNC_TLS */
165 Index: new/ui/vnc-auth-vencrypt.c
166 ===================================================================
167 --- new.orig/ui/vnc-auth-vencrypt.c 2014-06-17 06:14:28.000000000 +0200
168 +++ new/ui/vnc-auth-vencrypt.c 2014-06-17 06:14:54.000000000 +0200
169 @@ -26,6 +26,107 @@
170
171 #include "vnc.h"
172 #include "qemu/main-loop.h"
173 +#include "qemu/sockets.h"
174 +
175 +static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
176 +{
177 + const char *err = NULL;
178 + char username[256];
179 + char passwd[512];
180 +
181 + char clientip[256];
182 + clientip[0] = 0;
183 + struct sockaddr_in client;
184 + socklen_t addrlen = sizeof(client);
185 + if (getpeername(vs->csock, &client, &addrlen) == 0) {
186 + inet_ntop(client.sin_family, &client.sin_addr,
187 + clientip, sizeof(clientip));
188 + }
189 +
190 + if ((len != (vs->username_len + vs->password_len)) ||
191 + (vs->username_len >= (sizeof(username)-1)) ||
192 + (vs->password_len >= (sizeof(passwd)-1)) ) {
193 + err = "Got unexpected data length";
194 + goto err;
195 + }
196 +
197 + strncpy(username, (char *)data, vs->username_len);
198 + username[vs->username_len] = 0;
199 + strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
200 + passwd[vs->password_len] = 0;
201 +
202 + VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
203 +
204 + if (pve_auth_verify(clientip, username, passwd) == 0) {
205 + vnc_write_u32(vs, 0); /* Accept auth completion */
206 + start_client_init(vs);
207 + return 0;
208 + }
209 +
210 + err = "Authentication failed";
211 +err:
212 + if (err) {
213 + VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
214 + vnc_write_u32(vs, 1); /* Reject auth */
215 + if (vs->minor >= 8) {
216 + int elen = strlen(err);
217 + vnc_write_u32(vs, elen);
218 + vnc_write(vs, err, elen);
219 + }
220 + }
221 + vnc_flush(vs);
222 + vnc_client_error(vs);
223 +
224 + return 0;
225 +
226 +}
227 +
228 +static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
229 +{
230 + uint32_t ulen = read_u32(data, 0);
231 + uint32_t pwlen = read_u32(data, 4);
232 + const char *err = NULL;
233 +
234 + VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
235 +
236 + if (!ulen) {
237 + err = "No User name.";
238 + goto err;
239 + }
240 + if (ulen >= 255) {
241 + err = "User name too long.";
242 + goto err;
243 + }
244 + if (!pwlen) {
245 + err = "Password too short";
246 + goto err;
247 + }
248 + if (pwlen >= 511) {
249 + err = "Password too long.";
250 + goto err;
251 + }
252 +
253 + vs->username_len = ulen;
254 + vs->password_len = pwlen;
255 +
256 + vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
257 +
258 + return 0;
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 static void start_auth_vencrypt_subauth(VncState *vs)
276 {
277 @@ -37,6 +138,12 @@
278 start_client_init(vs);
279 break;
280
281 + case VNC_AUTH_VENCRYPT_TLSPLAIN:
282 + case VNC_AUTH_VENCRYPT_X509PLAIN:
283 + VNC_DEBUG("Start TLS auth PLAIN\n");
284 + vnc_read_when(vs, protocol_client_auth_plain_start, 8);
285 + break;
286 +
287 case VNC_AUTH_VENCRYPT_TLSVNC:
288 case VNC_AUTH_VENCRYPT_X509VNC:
289 VNC_DEBUG("Start TLS auth VNC\n");
290 Index: new/ui/vnc.h
291 ===================================================================
292 --- new.orig/ui/vnc.h 2014-06-17 06:14:28.000000000 +0200
293 +++ new/ui/vnc.h 2014-06-17 06:14:54.000000000 +0200
294 @@ -279,6 +279,8 @@
295 char challenge[VNC_AUTH_CHALLENGE_SIZE];
296 #ifdef CONFIG_VNC_TLS
297 int subauth; /* Used by VeNCrypt */
298 + int username_len;
299 + int password_len;
300 VncStateTLS tls;
301 #endif
302 #ifdef CONFIG_VNC_SASL
303 @@ -594,4 +596,6 @@
304 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
305 void vnc_zrle_clear(VncState *vs);
306
307 +int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
308 +
309 #endif /* __QEMU_VNC_H */
310 Index: new/ui/vnc-tls.c
311 ===================================================================
312 --- new.orig/ui/vnc-tls.c 2014-06-17 06:14:28.000000000 +0200
313 +++ new/ui/vnc-tls.c 2014-06-17 06:14:54.000000000 +0200
314 @@ -302,6 +302,14 @@
315
316 static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
317 {
318 + /* optimize for speed */
319 + static const int ciphers[] = {
320 + GNUTLS_CIPHER_ARCFOUR_128,
321 + GNUTLS_CIPHER_AES_128_CBC,
322 + GNUTLS_CIPHER_3DES_CBC,
323 + 0
324 + };
325 +
326 static const int cert_types[] = { GNUTLS_CRT_X509, 0 };
327 static const int protocols[] = {
328 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
329 @@ -313,6 +321,11 @@
330 };
331 int rc;
332
333 + rc = gnutls_cipher_set_priority(s, ciphers);
334 + if (rc != GNUTLS_E_SUCCESS) {
335 + return -1;
336 + }
337 +
338 rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
339 if (rc != GNUTLS_E_SUCCESS) {
340 return -1;
341 @@ -466,6 +479,24 @@
342 return 0;
343 }
344
345 +int pve_tls_set_x509_creds_dir(VncDisplay *vd)
346 +{
347 + if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
348 + goto cleanup;
349 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
350 + goto cleanup;
351 + if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
352 + goto cleanup;
353 +
354 + return 0;
355 +
356 + cleanup:
357 + g_free(vd->tls.x509cacert);
358 + g_free(vd->tls.x509cert);
359 + g_free(vd->tls.x509key);
360 + vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
361 + return -1;
362 +}
363
364 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
365 const char *certdir)
366 Index: new/ui/vnc-tls.h
367 ===================================================================
368 --- new.orig/ui/vnc-tls.h 2014-06-17 06:14:28.000000000 +0200
369 +++ new/ui/vnc-tls.h 2014-06-17 06:14:54.000000000 +0200
370 @@ -68,6 +68,8 @@
371
372 int vnc_tls_validate_certificate(VncState *vs);
373
374 +int pve_tls_set_x509_creds_dir(VncDisplay *vd);
375 +
376 int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
377 const char *path);
378
379 Index: new/vl.c
380 ===================================================================
381 --- new.orig/vl.c 2014-06-17 06:14:52.000000000 +0200
382 +++ new/vl.c 2014-06-17 06:14:54.000000000 +0200
383 @@ -3744,6 +3744,7 @@
384 fprintf(stderr, "Invalid ID\n");
385 exit(1);
386 }
387 + pve_auth_setup(fairsched_id);
388 break;
389 case QEMU_OPTION_cpuunits:
390 cpuunits = atoi(optarg);
391 Index: new/include/ui/console.h
392 ===================================================================
393 --- new.orig/include/ui/console.h 2014-06-17 06:14:28.000000000 +0200
394 +++ new/include/ui/console.h 2014-06-17 06:14:54.000000000 +0200
395 @@ -322,6 +322,7 @@
396 void cocoa_display_init(DisplayState *ds, int full_screen);
397
398 /* vnc.c */
399 +void pve_auth_setup(int vmid);
400 void vnc_display_init(DisplayState *ds);
401 void vnc_display_open(DisplayState *ds, const char *display, Error **errp);
402 void vnc_display_add_client(DisplayState *ds, int csock, bool skipauth);