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