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