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