xref: /freebsd/usr.sbin/bhyve/rfb.c (revision d93a896ef95946b0bf1219866fcb324b78543444)
1 /*-
2  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3  * Copyright (c) 2015 Leon Dang
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #ifndef WITHOUT_CAPSICUM
33 #include <sys/capsicum.h>
34 #endif
35 #include <sys/endian.h>
36 #include <sys/socket.h>
37 #include <sys/select.h>
38 #include <sys/time.h>
39 #include <arpa/inet.h>
40 #include <machine/cpufunc.h>
41 #include <machine/specialreg.h>
42 #include <netinet/in.h>
43 
44 #include <assert.h>
45 #include <err.h>
46 #include <errno.h>
47 #include <pthread.h>
48 #include <pthread_np.h>
49 #include <signal.h>
50 #include <stdbool.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <sysexits.h>
55 #include <unistd.h>
56 
57 #include <zlib.h>
58 
59 #include "bhyvegc.h"
60 #include "console.h"
61 #include "rfb.h"
62 #include "sockstream.h"
63 
64 #ifndef NO_OPENSSL
65 #include <openssl/des.h>
66 #endif
67 
68 static int rfb_debug = 0;
69 #define	DPRINTF(params) if (rfb_debug) printf params
70 #define	WPRINTF(params) printf params
71 
72 #define AUTH_LENGTH	16
73 #define PASSWD_LENGTH	8
74 
75 #define SECURITY_TYPE_NONE 1
76 #define SECURITY_TYPE_VNC_AUTH 2
77 
78 #define AUTH_FAILED_UNAUTH 1
79 #define AUTH_FAILED_ERROR 2
80 
81 struct rfb_softc {
82 	int		sfd;
83 	pthread_t	tid;
84 
85 	int		cfd;
86 
87 	int		width, height;
88 
89 	char		*password;
90 
91 	bool	enc_raw_ok;
92 	bool	enc_zlib_ok;
93 	bool	enc_resize_ok;
94 
95 	z_stream	zstream;
96 	uint8_t		*zbuf;
97 	int		zbuflen;
98 
99 	int		conn_wait;
100 	int		sending;
101 	pthread_mutex_t mtx;
102 	pthread_cond_t  cond;
103 
104 	int		hw_crc;
105 	uint32_t	*crc;		/* WxH crc cells */
106 	uint32_t	*crc_tmp;	/* buffer to store single crc row */
107 	int		crc_width, crc_height;
108 };
109 
110 struct rfb_pixfmt {
111 	uint8_t		bpp;
112 	uint8_t		depth;
113 	uint8_t		bigendian;
114 	uint8_t		truecolor;
115 	uint16_t	red_max;
116 	uint16_t	green_max;
117 	uint16_t	blue_max;
118 	uint8_t		red_shift;
119 	uint8_t		green_shift;
120 	uint8_t		blue_shift;
121 	uint8_t		pad[3];
122 };
123 
124 struct rfb_srvr_info {
125 	uint16_t		width;
126 	uint16_t		height;
127 	struct rfb_pixfmt	pixfmt;
128 	uint32_t		namelen;
129 };
130 
131 struct rfb_pixfmt_msg {
132 	uint8_t			type;
133 	uint8_t			pad[3];
134 	struct rfb_pixfmt	pixfmt;
135 };
136 
137 #define	RFB_ENCODING_RAW		0
138 #define	RFB_ENCODING_ZLIB		6
139 #define	RFB_ENCODING_RESIZE		-223
140 
141 #define RFB_MAX_WIDTH			2000
142 #define RFB_MAX_HEIGHT			1200
143 #define	RFB_ZLIB_BUFSZ			RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
144 
145 /* percentage changes to screen before sending the entire screen */
146 #define RFB_SEND_ALL_THRESH             25
147 
148 struct rfb_enc_msg {
149 	uint8_t		type;
150 	uint8_t		pad;
151 	uint16_t	numencs;
152 };
153 
154 struct rfb_updt_msg {
155 	uint8_t		type;
156 	uint8_t		incremental;
157 	uint16_t	x;
158 	uint16_t	y;
159 	uint16_t	width;
160 	uint16_t	height;
161 };
162 
163 struct rfb_key_msg {
164 	uint8_t		type;
165 	uint8_t		down;
166 	uint16_t	pad;
167 	uint32_t	code;
168 };
169 
170 struct rfb_ptr_msg {
171 	uint8_t		type;
172 	uint8_t		button;
173 	uint16_t	x;
174 	uint16_t	y;
175 };
176 
177 struct rfb_srvr_updt_msg {
178 	uint8_t		type;
179 	uint8_t		pad;
180 	uint16_t	numrects;
181 };
182 
183 struct rfb_srvr_rect_hdr {
184 	uint16_t	x;
185 	uint16_t	y;
186 	uint16_t	width;
187 	uint16_t	height;
188 	uint32_t	encoding;
189 };
190 
191 struct rfb_cuttext_msg {
192 	uint8_t		type;
193 	uint8_t		padding[3];
194 	uint32_t	length;
195 };
196 
197 
198 static void
199 rfb_send_server_init_msg(int cfd)
200 {
201 	struct bhyvegc_image *gc_image;
202 	struct rfb_srvr_info sinfo;
203 
204 	gc_image = console_get_image();
205 
206 	sinfo.width = htons(gc_image->width);
207 	sinfo.height = htons(gc_image->height);
208 	sinfo.pixfmt.bpp = 32;
209 	sinfo.pixfmt.depth = 32;
210 	sinfo.pixfmt.bigendian = 0;
211 	sinfo.pixfmt.truecolor = 1;
212 	sinfo.pixfmt.red_max = htons(255);
213 	sinfo.pixfmt.green_max = htons(255);
214 	sinfo.pixfmt.blue_max = htons(255);
215 	sinfo.pixfmt.red_shift = 16;
216 	sinfo.pixfmt.green_shift = 8;
217 	sinfo.pixfmt.blue_shift = 0;
218 	sinfo.namelen = htonl(strlen("bhyve"));
219 	(void)stream_write(cfd, &sinfo, sizeof(sinfo));
220 	(void)stream_write(cfd, "bhyve", strlen("bhyve"));
221 }
222 
223 static void
224 rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd)
225 {
226 	struct rfb_srvr_updt_msg supdt_msg;
227 	struct rfb_srvr_rect_hdr srect_hdr;
228 
229 	/* Number of rectangles: 1 */
230 	supdt_msg.type = 0;
231 	supdt_msg.pad = 0;
232 	supdt_msg.numrects = htons(1);
233 	stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
234 
235 	/* Rectangle header */
236 	srect_hdr.x = htons(0);
237 	srect_hdr.y = htons(0);
238 	srect_hdr.width = htons(rc->width);
239 	srect_hdr.height = htons(rc->height);
240 	srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE);
241 	stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
242 }
243 
244 static void
245 rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
246 {
247 	struct rfb_pixfmt_msg pixfmt_msg;
248 
249 	(void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1);
250 }
251 
252 
253 static void
254 rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd)
255 {
256 	struct rfb_enc_msg enc_msg;
257 	int i;
258 	uint32_t encoding;
259 
260 	assert((sizeof(enc_msg) - 1) == 3);
261 	(void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
262 
263 	for (i = 0; i < htons(enc_msg.numencs); i++) {
264 		(void)stream_read(cfd, &encoding, sizeof(encoding));
265 		switch (htonl(encoding)) {
266 		case RFB_ENCODING_RAW:
267 			rc->enc_raw_ok = true;
268 			break;
269 		case RFB_ENCODING_ZLIB:
270 			rc->enc_zlib_ok = true;
271 			deflateInit(&rc->zstream, Z_BEST_SPEED);
272 			break;
273 		case RFB_ENCODING_RESIZE:
274 			rc->enc_resize_ok = true;
275 			break;
276 		}
277 	}
278 }
279 
280 /*
281  * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only
282  */
283 static __inline uint32_t
284 fast_crc32(void *buf, int len, uint32_t crcval)
285 {
286 	uint32_t q = len / sizeof(uint32_t);
287 	uint32_t *p = (uint32_t *)buf;
288 
289 	while (q--) {
290 		asm volatile (
291 			".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
292 			:"=S" (crcval)
293 			:"0" (crcval), "c" (*p)
294 		);
295 		p++;
296 	}
297 
298 	return (crcval);
299 }
300 
301 
302 static int
303 rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
304               int x, int y, int w, int h)
305 {
306 	struct rfb_srvr_updt_msg supdt_msg;
307         struct rfb_srvr_rect_hdr srect_hdr;
308 	unsigned long zlen;
309 	ssize_t nwrite, total;
310 	int err;
311 	uint32_t *p;
312 	uint8_t *zbufp;
313 
314 	/*
315 	 * Send a single rectangle of the given x, y, w h dimensions.
316 	 */
317 
318 	/* Number of rectangles: 1 */
319 	supdt_msg.type = 0;
320 	supdt_msg.pad = 0;
321 	supdt_msg.numrects = htons(1);
322 	nwrite = stream_write(cfd, &supdt_msg,
323 	                      sizeof(struct rfb_srvr_updt_msg));
324 	if (nwrite <= 0)
325 		return (nwrite);
326 
327 
328 	/* Rectangle header */
329 	srect_hdr.x = htons(x);
330 	srect_hdr.y = htons(y);
331 	srect_hdr.width = htons(w);
332 	srect_hdr.height = htons(h);
333 
334 	h = y + h;
335 	w *= sizeof(uint32_t);
336 	if (rc->enc_zlib_ok) {
337 		zbufp = rc->zbuf;
338 		rc->zstream.total_in = 0;
339 		rc->zstream.total_out = 0;
340 		for (p = &gc->data[y * gc->width + x]; y < h; y++) {
341 			rc->zstream.next_in = (Bytef *)p;
342 			rc->zstream.avail_in = w;
343 			rc->zstream.next_out = (Bytef *)zbufp;
344 			rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
345 			                        rc->zstream.total_out;
346 			rc->zstream.data_type = Z_BINARY;
347 
348 			/* Compress with zlib */
349 			err = deflate(&rc->zstream, Z_SYNC_FLUSH);
350 			if (err != Z_OK) {
351 				WPRINTF(("zlib[rect] deflate err: %d\n", err));
352 				rc->enc_zlib_ok = false;
353 				deflateEnd(&rc->zstream);
354 				goto doraw;
355 			}
356 			zbufp = rc->zbuf + rc->zstream.total_out;
357 			p += gc->width;
358 		}
359 		srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
360 		nwrite = stream_write(cfd, &srect_hdr,
361 		                      sizeof(struct rfb_srvr_rect_hdr));
362 		if (nwrite <= 0)
363 			return (nwrite);
364 
365 		zlen = htonl(rc->zstream.total_out);
366 		nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
367 		if (nwrite <= 0)
368 			return (nwrite);
369 		return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
370 	}
371 
372 doraw:
373 
374 	total = 0;
375 	zbufp = rc->zbuf;
376 	for (p = &gc->data[y * gc->width + x]; y < h; y++) {
377 		memcpy(zbufp, p, w);
378 		zbufp += w;
379 		total += w;
380 		p += gc->width;
381 	}
382 
383 	srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
384 	nwrite = stream_write(cfd, &srect_hdr,
385 	                      sizeof(struct rfb_srvr_rect_hdr));
386 	if (nwrite <= 0)
387 		return (nwrite);
388 
389 	total = stream_write(cfd, rc->zbuf, total);
390 
391 	return (total);
392 }
393 
394 static int
395 rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc)
396 {
397 	struct rfb_srvr_updt_msg supdt_msg;
398         struct rfb_srvr_rect_hdr srect_hdr;
399 	ssize_t nwrite;
400 	unsigned long zlen;
401 	int err;
402 
403 	/*
404 	 * Send the whole thing
405 	 */
406 
407 	/* Number of rectangles: 1 */
408 	supdt_msg.type = 0;
409 	supdt_msg.pad = 0;
410 	supdt_msg.numrects = htons(1);
411 	nwrite = stream_write(cfd, &supdt_msg,
412 	                      sizeof(struct rfb_srvr_updt_msg));
413 	if (nwrite <= 0)
414 		return (nwrite);
415 
416 	/* Rectangle header */
417 	srect_hdr.x = 0;
418 	srect_hdr.y = 0;
419 	srect_hdr.width = htons(gc->width);
420 	srect_hdr.height = htons(gc->height);
421 	if (rc->enc_zlib_ok) {
422 		rc->zstream.next_in = (Bytef *)gc->data;
423 		rc->zstream.avail_in = gc->width * gc->height *
424 		                   sizeof(uint32_t);
425 		rc->zstream.next_out = (Bytef *)rc->zbuf;
426 		rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16;
427 		rc->zstream.data_type = Z_BINARY;
428 
429 		rc->zstream.total_in = 0;
430 		rc->zstream.total_out = 0;
431 
432 		/* Compress with zlib */
433 		err = deflate(&rc->zstream, Z_SYNC_FLUSH);
434 		if (err != Z_OK) {
435 			WPRINTF(("zlib deflate err: %d\n", err));
436 			rc->enc_zlib_ok = false;
437 			deflateEnd(&rc->zstream);
438 			goto doraw;
439 		}
440 
441 		srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB);
442 		nwrite = stream_write(cfd, &srect_hdr,
443 		                      sizeof(struct rfb_srvr_rect_hdr));
444 		if (nwrite <= 0)
445 			return (nwrite);
446 
447 		zlen = htonl(rc->zstream.total_out);
448 		nwrite = stream_write(cfd, &zlen, sizeof(uint32_t));
449 		if (nwrite <= 0)
450 			return (nwrite);
451 		return (stream_write(cfd, rc->zbuf, rc->zstream.total_out));
452 	}
453 
454 doraw:
455 	srect_hdr.encoding = htonl(RFB_ENCODING_RAW);
456 	nwrite = stream_write(cfd, &srect_hdr,
457 	                      sizeof(struct rfb_srvr_rect_hdr));
458 	if (nwrite <= 0)
459 		return (nwrite);
460 
461 	nwrite = stream_write(cfd, gc->data,
462 	               gc->width * gc->height * sizeof(uint32_t));
463 
464 	return (nwrite);
465 }
466 
467 #define PIX_PER_CELL	32
468 #define	PIXCELL_SHIFT	5
469 #define PIXCELL_MASK	0x1F
470 
471 static int
472 rfb_send_screen(struct rfb_softc *rc, int cfd, int all)
473 {
474 	struct bhyvegc_image *gc_image;
475 	ssize_t nwrite;
476 	int x, y;
477 	int celly, cellwidth;
478 	int xcells, ycells;
479 	int w, h;
480 	uint32_t *p;
481 	int rem_x, rem_y;   /* remainder for resolutions not x32 pixels ratio */
482 	int retval;
483 	uint32_t *crc_p, *orig_crc;
484 	int changes;
485 
486 	console_refresh();
487 	gc_image = console_get_image();
488 
489 	pthread_mutex_lock(&rc->mtx);
490 	if (rc->sending) {
491 		pthread_mutex_unlock(&rc->mtx);
492 		return (1);
493 	}
494 	rc->sending = 1;
495 	pthread_mutex_unlock(&rc->mtx);
496 
497 	retval = 0;
498 
499 	if (all) {
500 		retval = rfb_send_all(rc, cfd, gc_image);
501 		goto done;
502 	}
503 
504 	/*
505 	 * Calculate the checksum for each 32x32 cell. Send each that
506 	 * has changed since the last scan.
507 	 */
508 
509 	/* Resolution changed */
510 
511 	rc->crc_width = gc_image->width;
512 	rc->crc_height = gc_image->height;
513 
514 	w = rc->crc_width;
515 	h = rc->crc_height;
516 	xcells = howmany(rc->crc_width, PIX_PER_CELL);
517 	ycells = howmany(rc->crc_height, PIX_PER_CELL);
518 
519 	rem_x = w & PIXCELL_MASK;
520 
521 	rem_y = h & PIXCELL_MASK;
522 	if (!rem_y)
523 		rem_y = PIX_PER_CELL;
524 
525 	p = gc_image->data;
526 
527 	/*
528 	 * Go through all cells and calculate crc. If significant number
529 	 * of changes, then send entire screen.
530 	 * crc_tmp is dual purpose: to store the new crc and to flag as
531 	 * a cell that has changed.
532 	 */
533 	crc_p = rc->crc_tmp - xcells;
534 	orig_crc = rc->crc - xcells;
535 	changes = 0;
536 	memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells);
537 	for (y = 0; y < h; y++) {
538 		if ((y & PIXCELL_MASK) == 0) {
539 			crc_p += xcells;
540 			orig_crc += xcells;
541 		}
542 
543 		for (x = 0; x < xcells; x++) {
544 			if (rc->hw_crc)
545 				crc_p[x] = fast_crc32(p,
546 				             PIX_PER_CELL * sizeof(uint32_t),
547 				             crc_p[x]);
548 			else
549 				crc_p[x] = (uint32_t)crc32(crc_p[x],
550 				             (Bytef *)p,
551 				             PIX_PER_CELL * sizeof(uint32_t));
552 
553 			p += PIX_PER_CELL;
554 
555 			/* check for crc delta if last row in cell */
556 			if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) {
557 				if (orig_crc[x] != crc_p[x]) {
558 					orig_crc[x] = crc_p[x];
559 					crc_p[x] = 1;
560 					changes++;
561 				} else {
562 					crc_p[x] = 0;
563 				}
564 			}
565 		}
566 
567 		if (rem_x) {
568 			if (rc->hw_crc)
569 				crc_p[x] = fast_crc32(p,
570 				                    rem_x * sizeof(uint32_t),
571 				                    crc_p[x]);
572 			else
573 				crc_p[x] = (uint32_t)crc32(crc_p[x],
574 				                    (Bytef *)p,
575 				                    rem_x * sizeof(uint32_t));
576 			p += rem_x;
577 
578 			if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) {
579 				if (orig_crc[x] != crc_p[x]) {
580 					orig_crc[x] = crc_p[x];
581 					crc_p[x] = 1;
582 					changes++;
583 				} else {
584 					crc_p[x] = 0;
585 				}
586 			}
587 		}
588 	}
589 
590 	/* If number of changes is > THRESH percent, send the whole screen */
591 	if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) {
592 		retval = rfb_send_all(rc, cfd, gc_image);
593 		goto done;
594 	}
595 
596 	/* Go through all cells, and send only changed ones */
597 	crc_p = rc->crc_tmp;
598 	for (y = 0; y < h; y += PIX_PER_CELL) {
599 		/* previous cell's row */
600 		celly = (y >> PIXCELL_SHIFT);
601 
602 		/* Delta check crc to previous set */
603 		for (x = 0; x < xcells; x++) {
604 			if (*crc_p++ == 0)
605 				continue;
606 
607 			if (x == (xcells - 1) && rem_x > 0)
608 				cellwidth = rem_x;
609 			else
610 				cellwidth = PIX_PER_CELL;
611 			nwrite = rfb_send_rect(rc, cfd,
612 				gc_image,
613 				x * PIX_PER_CELL,
614 				celly * PIX_PER_CELL,
615 			        cellwidth,
616 				y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL);
617 			if (nwrite <= 0) {
618 				retval = nwrite;
619 				goto done;
620 			}
621 		}
622 	}
623 	retval = 1;
624 
625 done:
626 	pthread_mutex_lock(&rc->mtx);
627 	rc->sending = 0;
628 	pthread_mutex_unlock(&rc->mtx);
629 
630 	return (retval);
631 }
632 
633 
634 static void
635 rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int discardonly)
636 {
637 	struct rfb_updt_msg updt_msg;
638 	struct bhyvegc_image *gc_image;
639 
640 	(void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
641 
642 	console_refresh();
643 	gc_image = console_get_image();
644 
645 	updt_msg.x = htons(updt_msg.x);
646 	updt_msg.y = htons(updt_msg.y);
647 	updt_msg.width = htons(updt_msg.width);
648 	updt_msg.height = htons(updt_msg.height);
649 
650 	if (updt_msg.width != gc_image->width ||
651 	    updt_msg.height != gc_image->height) {
652 		rc->width = gc_image->width;
653 		rc->height = gc_image->height;
654 		if (rc->enc_resize_ok)
655 			rfb_send_resize_update_msg(rc, cfd);
656 	}
657 
658 	if (discardonly)
659 		return;
660 
661 	rfb_send_screen(rc, cfd, 1);
662 }
663 
664 static void
665 rfb_recv_key_msg(struct rfb_softc *rc, int cfd)
666 {
667 	struct rfb_key_msg key_msg;
668 
669 	(void)stream_read(cfd, ((void *)&key_msg) + 1, sizeof(key_msg) - 1);
670 
671 	console_key_event(key_msg.down, htonl(key_msg.code));
672 }
673 
674 static void
675 rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd)
676 {
677 	struct rfb_ptr_msg ptr_msg;
678 
679 	(void)stream_read(cfd, ((void *)&ptr_msg) + 1, sizeof(ptr_msg) - 1);
680 
681 	console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y));
682 }
683 
684 static void
685 rfb_recv_cuttext_msg(struct rfb_softc *rc, int cfd)
686 {
687 	struct rfb_cuttext_msg ct_msg;
688 	unsigned char buf[32];
689 	int len;
690 
691 	len = stream_read(cfd, ((void *)&ct_msg) + 1, sizeof(ct_msg) - 1);
692 	ct_msg.length = htonl(ct_msg.length);
693 	while (ct_msg.length > 0) {
694 		len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ?
695 			sizeof(buf) : ct_msg.length);
696 		ct_msg.length -= len;
697 	}
698 }
699 
700 static int64_t
701 timeval_delta(struct timeval *prev, struct timeval *now)
702 {
703 	int64_t n1, n2;
704 	n1 = now->tv_sec * 1000000 + now->tv_usec;
705 	n2 = prev->tv_sec * 1000000 + prev->tv_usec;
706 	return (n1 - n2);
707 }
708 
709 static void *
710 rfb_wr_thr(void *arg)
711 {
712 	struct rfb_softc *rc;
713 	fd_set rfds;
714 	struct timeval tv;
715 	struct timeval prev_tv;
716 	int64_t tdiff;
717 	int cfd;
718 	int err;
719 
720 	rc = arg;
721 	cfd = rc->cfd;
722 
723 	prev_tv.tv_sec = 0;
724 	prev_tv.tv_usec = 0;
725 	while (rc->cfd >= 0) {
726 		FD_ZERO(&rfds);
727 		FD_SET(cfd, &rfds);
728 		tv.tv_sec = 0;
729 		tv.tv_usec = 10000;
730 
731 		err = select(cfd+1, &rfds, NULL, NULL, &tv);
732                 if (err < 0)
733 			return (NULL);
734 
735 		/* Determine if its time to push screen; ~24hz */
736 		gettimeofday(&tv, NULL);
737 		tdiff = timeval_delta(&prev_tv, &tv);
738 		if (tdiff > 40000) {
739 			prev_tv.tv_sec = tv.tv_sec;
740 			prev_tv.tv_usec = tv.tv_usec;
741 			if (rfb_send_screen(rc, cfd, 0) <= 0) {
742 				return (NULL);
743 			}
744 		} else {
745 			/* sleep */
746 			usleep(40000 - tdiff);
747 		}
748 	}
749 
750 	return (NULL);
751 }
752 
753 void
754 rfb_handle(struct rfb_softc *rc, int cfd)
755 {
756 	const char *vbuf = "RFB 003.008\n";
757 	unsigned char buf[80];
758 	unsigned char *message = NULL;
759 
760 #ifndef NO_OPENSSL
761 	unsigned char challenge[AUTH_LENGTH];
762 	unsigned char keystr[PASSWD_LENGTH];
763 	unsigned char crypt_expected[AUTH_LENGTH];
764 
765 	DES_key_schedule ks;
766 	int i;
767 #endif
768 
769 	pthread_t tid;
770 	uint32_t sres = 0;
771 	int len;
772 	int perror = 1;
773 
774 	rc->cfd = cfd;
775 
776 	/* 1a. Send server version */
777 	stream_write(cfd, vbuf, strlen(vbuf));
778 
779 	/* 1b. Read client version */
780 	len = read(cfd, buf, sizeof(buf));
781 
782 	/* 2a. Send security type */
783 	buf[0] = 1;
784 #ifndef NO_OPENSSL
785 	if (rc->password)
786 		buf[1] = SECURITY_TYPE_VNC_AUTH;
787 	else
788 		buf[1] = SECURITY_TYPE_NONE;
789 #else
790 	buf[1] = SECURITY_TYPE_NONE;
791 #endif
792 
793 	stream_write(cfd, buf, 2);
794 
795 	/* 2b. Read agreed security type */
796 	len = stream_read(cfd, buf, 1);
797 
798 	/* 2c. Do VNC authentication */
799 	switch (buf[0]) {
800 	case SECURITY_TYPE_NONE:
801 		sres = 0;
802 		break;
803 	case SECURITY_TYPE_VNC_AUTH:
804 		/*
805 		 * The client encrypts the challenge with DES, using a password
806 		 * supplied by the user as the key.
807 		 * To form the key, the password is truncated to
808 		 * eight characters, or padded with null bytes on the right.
809 		 * The client then sends the resulting 16-bytes response.
810 		 */
811 #ifndef NO_OPENSSL
812 		strncpy(keystr, rc->password, PASSWD_LENGTH);
813 
814 		/* VNC clients encrypts the challenge with all the bit fields
815 		 * in each byte of the password mirrored.
816 		 * Here we flip each byte of the keystr.
817 		 */
818 		for (i = 0; i < PASSWD_LENGTH; i++) {
819 			keystr[i] = (keystr[i] & 0xF0) >> 4
820 				  | (keystr[i] & 0x0F) << 4;
821 			keystr[i] = (keystr[i] & 0xCC) >> 2
822 				  | (keystr[i] & 0x33) << 2;
823 			keystr[i] = (keystr[i] & 0xAA) >> 1
824 				  | (keystr[i] & 0x55) << 1;
825 		}
826 
827 		/* Initialize a 16-byte random challenge */
828 		arc4random_buf(challenge, sizeof(challenge));
829 		stream_write(cfd, challenge, AUTH_LENGTH);
830 
831 		/* Receive the 16-byte challenge response */
832 		stream_read(cfd, buf, AUTH_LENGTH);
833 
834 		memcpy(crypt_expected, challenge, AUTH_LENGTH);
835 
836 		/* Encrypt the Challenge with DES */
837 		DES_set_key((const_DES_cblock *)keystr, &ks);
838 		DES_ecb_encrypt((const_DES_cblock *)challenge,
839 				(const_DES_cblock *)crypt_expected,
840 				&ks, DES_ENCRYPT);
841 		DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH),
842 				(const_DES_cblock *)(crypt_expected +
843 				PASSWD_LENGTH),
844 				&ks, DES_ENCRYPT);
845 
846 		if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) {
847 			message = "Auth Failed: Invalid Password.";
848 			sres = htonl(1);
849 		} else
850 			sres = 0;
851 #else
852 		sres = 0;
853 		WPRINTF(("Auth not supported, no OpenSSL in your system"));
854 #endif
855 
856 		break;
857 	}
858 
859 	/* 2d. Write back a status */
860 	stream_write(cfd, &sres, 4);
861 
862 	if (sres) {
863 		be32enc(buf, strlen(message));
864 		stream_write(cfd, buf, 4);
865 		stream_write(cfd, message, strlen(message));
866 		goto done;
867 	}
868 
869 	/* 3a. Read client shared-flag byte */
870 	len = stream_read(cfd, buf, 1);
871 
872 	/* 4a. Write server-init info */
873 	rfb_send_server_init_msg(cfd);
874 
875 	if (!rc->zbuf) {
876 		rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16);
877 		assert(rc->zbuf != NULL);
878 	}
879 
880 	rfb_send_screen(rc, cfd, 1);
881 
882 	perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
883 	if (perror == 0)
884 		pthread_set_name_np(tid, "rfbout");
885 
886         /* Now read in client requests. 1st byte identifies type */
887 	for (;;) {
888 		len = read(cfd, buf, 1);
889 		if (len <= 0) {
890 			DPRINTF(("rfb client exiting\r\n"));
891 			break;
892 		}
893 
894 		switch (buf[0]) {
895 		case 0:
896 			rfb_recv_set_pixfmt_msg(rc, cfd);
897 			break;
898 		case 2:
899 			rfb_recv_set_encodings_msg(rc, cfd);
900 			break;
901 		case 3:
902 			rfb_recv_update_msg(rc, cfd, 1);
903 			break;
904 		case 4:
905 			rfb_recv_key_msg(rc, cfd);
906 			break;
907 		case 5:
908 			rfb_recv_ptr_msg(rc, cfd);
909 			break;
910 		case 6:
911 			rfb_recv_cuttext_msg(rc, cfd);
912 			break;
913 		default:
914 			WPRINTF(("rfb unknown cli-code %d!\n", buf[0] & 0xff));
915 			goto done;
916 		}
917 	}
918 done:
919 	rc->cfd = -1;
920 	if (perror == 0)
921 		pthread_join(tid, NULL);
922 	if (rc->enc_zlib_ok)
923 		deflateEnd(&rc->zstream);
924 }
925 
926 static void *
927 rfb_thr(void *arg)
928 {
929 	struct rfb_softc *rc;
930 	sigset_t set;
931 
932 	int cfd;
933 
934 	rc = arg;
935 
936 	sigemptyset(&set);
937 	sigaddset(&set, SIGPIPE);
938 	if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
939 		perror("pthread_sigmask");
940 		return (NULL);
941 	}
942 
943 	for (;;) {
944 		rc->enc_raw_ok = false;
945 		rc->enc_zlib_ok = false;
946 		rc->enc_resize_ok = false;
947 
948 		cfd = accept(rc->sfd, NULL, NULL);
949 		if (rc->conn_wait) {
950 			pthread_mutex_lock(&rc->mtx);
951 			pthread_cond_signal(&rc->cond);
952 			pthread_mutex_unlock(&rc->mtx);
953 			rc->conn_wait = 0;
954 		}
955 		rfb_handle(rc, cfd);
956 		close(cfd);
957 	}
958 
959 	/* NOTREACHED */
960 	return (NULL);
961 }
962 
963 static int
964 sse42_supported(void)
965 {
966 	u_int cpu_registers[4], ecx;
967 
968 	do_cpuid(1, cpu_registers);
969 
970 	ecx = cpu_registers[2];
971 
972 	return ((ecx & CPUID2_SSE42) != 0);
973 }
974 
975 int
976 rfb_init(char *hostname, int port, int wait, char *password)
977 {
978 	struct rfb_softc *rc;
979 	struct sockaddr_in sin;
980 	int on = 1;
981 #ifndef WITHOUT_CAPSICUM
982 	cap_rights_t rights;
983 #endif
984 
985 	rc = calloc(1, sizeof(struct rfb_softc));
986 
987 	rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
988 	                 sizeof(uint32_t));
989 	rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
990 	                     sizeof(uint32_t));
991 	rc->crc_width = RFB_MAX_WIDTH;
992 	rc->crc_height = RFB_MAX_HEIGHT;
993 
994 	rc->password = password;
995 
996 	rc->sfd = socket(AF_INET, SOCK_STREAM, 0);
997 	if (rc->sfd < 0) {
998 		perror("socket");
999 		return (-1);
1000 	}
1001 
1002 	setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1003 
1004 	sin.sin_len = sizeof(sin);
1005 	sin.sin_family = AF_INET;
1006 	sin.sin_port = port ? htons(port) : htons(5900);
1007 	if (hostname && strlen(hostname) > 0)
1008 		inet_pton(AF_INET, hostname, &(sin.sin_addr));
1009 	else
1010 		sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1011 
1012 	if (bind(rc->sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
1013 		perror("bind");
1014 		return (-1);
1015 	}
1016 
1017 	if (listen(rc->sfd, 1) < 0) {
1018 		perror("listen");
1019 		return (-1);
1020 	}
1021 
1022 #ifndef WITHOUT_CAPSICUM
1023 	cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
1024 	if (cap_rights_limit(rc->sfd, &rights) == -1 && errno != ENOSYS)
1025 		errx(EX_OSERR, "Unable to apply rights for sandbox");
1026 #endif
1027 
1028 	rc->hw_crc = sse42_supported();
1029 
1030 	rc->conn_wait = wait;
1031 	if (wait) {
1032 		pthread_mutex_init(&rc->mtx, NULL);
1033 		pthread_cond_init(&rc->cond, NULL);
1034 	}
1035 
1036 	pthread_create(&rc->tid, NULL, rfb_thr, rc);
1037 	pthread_set_name_np(rc->tid, "rfb");
1038 
1039 	if (wait) {
1040 		DPRINTF(("Waiting for rfb client...\n"));
1041 		pthread_mutex_lock(&rc->mtx);
1042 		pthread_cond_wait(&rc->cond, &rc->mtx);
1043 		pthread_mutex_unlock(&rc->mtx);
1044 	}
1045 
1046 	return (0);
1047 }
1048