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