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