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