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: stable/11/usr.sbin/bhyve/rfb.c 360965 2020-05-12 16:05:21Z jhb $");
32
33#include <sys/param.h>
34#include <sys/endian.h>
35#ifndef WITHOUT_CAPSICUM
36#include <sys/capsicum.h>
37#endif
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
71static int rfb_debug = 0;
72#define	DPRINTF(params) if (rfb_debug) printf params
73#define	WPRINTF(params) printf params
74
75#define VERSION_LENGTH	12
76#define AUTH_LENGTH	16
77#define PASSWD_LENGTH	8
78
79#define SECURITY_TYPE_NONE	1
80#define SECURITY_TYPE_VNC_AUTH	2
81
82#define AUTH_FAILED_UNAUTH	1
83#define AUTH_FAILED_ERROR	2
84
85struct rfb_softc {
86	int		sfd;
87	pthread_t	tid;
88
89	int		cfd;
90
91	int		width, height;
92
93	char		*password;
94
95	bool	enc_raw_ok;
96	bool	enc_zlib_ok;
97	bool	enc_resize_ok;
98
99	z_stream	zstream;
100	uint8_t		*zbuf;
101	int		zbuflen;
102
103	int		conn_wait;
104	int		sending;
105	pthread_mutex_t mtx;
106	pthread_cond_t  cond;
107
108	int		hw_crc;
109	uint32_t	*crc;		/* WxH crc cells */
110	uint32_t	*crc_tmp;	/* buffer to store single crc row */
111	int		crc_width, crc_height;
112};
113
114struct rfb_pixfmt {
115	uint8_t		bpp;
116	uint8_t		depth;
117	uint8_t		bigendian;
118	uint8_t		truecolor;
119	uint16_t	red_max;
120	uint16_t	green_max;
121	uint16_t	blue_max;
122	uint8_t		red_shift;
123	uint8_t		green_shift;
124	uint8_t		blue_shift;
125	uint8_t		pad[3];
126};
127
128struct rfb_srvr_info {
129	uint16_t		width;
130	uint16_t		height;
131	struct rfb_pixfmt	pixfmt;
132	uint32_t		namelen;
133};
134
135struct rfb_pixfmt_msg {
136	uint8_t			type;
137	uint8_t			pad[3];
138	struct rfb_pixfmt	pixfmt;
139};
140
141#define	RFB_ENCODING_RAW		0
142#define	RFB_ENCODING_ZLIB		6
143#define	RFB_ENCODING_RESIZE		-223
144
145#define	RFB_MAX_WIDTH			2000
146#define	RFB_MAX_HEIGHT			1200
147#define	RFB_ZLIB_BUFSZ			RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
148
149/* percentage changes to screen before sending the entire screen */
150#define	RFB_SEND_ALL_THRESH		25
151
152struct rfb_enc_msg {
153	uint8_t		type;
154	uint8_t		pad;
155	uint16_t	numencs;
156};
157
158struct rfb_updt_msg {
159	uint8_t		type;
160	uint8_t		incremental;
161	uint16_t	x;
162	uint16_t	y;
163	uint16_t	width;
164	uint16_t	height;
165};
166
167struct rfb_key_msg {
168	uint8_t		type;
169	uint8_t		down;
170	uint16_t	pad;
171	uint32_t	code;
172};
173
174struct rfb_ptr_msg {
175	uint8_t		type;
176	uint8_t		button;
177	uint16_t	x;
178	uint16_t	y;
179};
180
181struct rfb_srvr_updt_msg {
182	uint8_t		type;
183	uint8_t		pad;
184	uint16_t	numrects;
185};
186
187struct rfb_srvr_rect_hdr {
188	uint16_t	x;
189	uint16_t	y;
190	uint16_t	width;
191	uint16_t	height;
192	uint32_t	encoding;
193};
194
195struct rfb_cuttext_msg {
196	uint8_t		type;
197	uint8_t		padding[3];
198	uint32_t	length;
199};
200
201
202static void
203rfb_send_server_init_msg(int cfd)
204{
205	struct bhyvegc_image *gc_image;
206	struct rfb_srvr_info sinfo;
207
208	gc_image = console_get_image();
209
210	sinfo.width = htons(gc_image->width);
211	sinfo.height = htons(gc_image->height);
212	sinfo.pixfmt.bpp = 32;
213	sinfo.pixfmt.depth = 32;
214	sinfo.pixfmt.bigendian = 0;
215	sinfo.pixfmt.truecolor = 1;
216	sinfo.pixfmt.red_max = htons(255);
217	sinfo.pixfmt.green_max = htons(255);
218	sinfo.pixfmt.blue_max = htons(255);
219	sinfo.pixfmt.red_shift = 16;
220	sinfo.pixfmt.green_shift = 8;
221	sinfo.pixfmt.blue_shift = 0;
222	sinfo.namelen = htonl(strlen("bhyve"));
223	(void)stream_write(cfd, &sinfo, sizeof(sinfo));
224	(void)stream_write(cfd, "bhyve", strlen("bhyve"));
225}
226
227static void
228rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd)
229{
230	struct rfb_srvr_updt_msg supdt_msg;
231	struct rfb_srvr_rect_hdr srect_hdr;
232
233	/* Number of rectangles: 1 */
234	supdt_msg.type = 0;
235	supdt_msg.pad = 0;
236	supdt_msg.numrects = htons(1);
237	stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg));
238
239	/* Rectangle header */
240	srect_hdr.x = htons(0);
241	srect_hdr.y = htons(0);
242	srect_hdr.width = htons(rc->width);
243	srect_hdr.height = htons(rc->height);
244	srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE);
245	stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr));
246}
247
248static void
249rfb_recv_set_pixfmt_msg(struct rfb_softc *rc, int cfd)
250{
251	struct rfb_pixfmt_msg pixfmt_msg;
252
253	(void)stream_read(cfd, ((void *)&pixfmt_msg)+1, sizeof(pixfmt_msg)-1);
254}
255
256
257static void
258rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd)
259{
260	struct rfb_enc_msg enc_msg;
261	int i;
262	uint32_t encoding;
263
264	assert((sizeof(enc_msg) - 1) == 3);
265	(void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
266
267	for (i = 0; i < htons(enc_msg.numencs); i++) {
268		(void)stream_read(cfd, &encoding, sizeof(encoding));
269		switch (htonl(encoding)) {
270		case RFB_ENCODING_RAW:
271			rc->enc_raw_ok = true;
272			break;
273		case RFB_ENCODING_ZLIB:
274			if (!rc->enc_zlib_ok) {
275				deflateInit(&rc->zstream, Z_BEST_SPEED);
276				rc->enc_zlib_ok = true;
277			}
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 */
289static __inline uint32_t
290fast_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
308static int
309rfb_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
378doraw:
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
400static int
401rfb_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
460doraw:
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
477static int
478rfb_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
614done:
615	pthread_mutex_lock(&rc->mtx);
616	rc->sending = 0;
617	pthread_mutex_unlock(&rc->mtx);
618
619	return (retval);
620}
621
622
623static void
624rfb_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
653static void
654rfb_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
663static void
664rfb_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
673static void
674rfb_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
689static int64_t
690timeval_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
698static void *
699rfb_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
742void
743rfb_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 = stream_read(cfd, buf, VERSION_LENGTH);
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	}
907done:
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
915static void *
916rfb_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
952static int
953sse42_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
964int
965rfb_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 (cap_rights_limit(rc->sfd, &rights) == -1 && errno != ENOSYS)
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