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