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