]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/rfb.c
MFV r362254: file 5.39.
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / rfb.c
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
75 static 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
89 struct 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
118 struct 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
132 struct rfb_srvr_info {
133         uint16_t                width;
134         uint16_t                height;
135         struct rfb_pixfmt       pixfmt;
136         uint32_t                namelen;
137 };
138
139 struct 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
156 struct rfb_enc_msg {
157         uint8_t         type;
158         uint8_t         pad;
159         uint16_t        numencs;
160 };
161
162 struct 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
171 struct rfb_key_msg {
172         uint8_t         type;
173         uint8_t         down;
174         uint16_t        pad;
175         uint32_t        code;
176 };
177
178 struct rfb_ptr_msg {
179         uint8_t         type;
180         uint8_t         button;
181         uint16_t        x;
182         uint16_t        y;
183 };
184
185 struct rfb_srvr_updt_msg {
186         uint8_t         type;
187         uint8_t         pad;
188         uint16_t        numrects;
189 };
190
191 struct 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
199 struct rfb_cuttext_msg {
200         uint8_t         type;
201         uint8_t         padding[3];
202         uint32_t        length;
203 };
204
205
206 static void
207 rfb_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
231 static void
232 rfb_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
252 static void
253 rfb_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
261 static void
262 rfb_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  */
293 static __inline uint32_t
294 fast_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
312 static int
313 rfb_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
382 doraw:
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
404 static int
405 rfb_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
464 doraw:
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
481 static int
482 rfb_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
618 done:
619         pthread_mutex_lock(&rc->mtx);
620         rc->sending = 0;
621         pthread_mutex_unlock(&rc->mtx);
622         
623         return (retval);
624 }
625
626
627 static void
628 rfb_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
657 static void
658 rfb_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
667 static void
668 rfb_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
677 static void
678 rfb_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
693 static int64_t
694 timeval_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
702 static void *
703 rfb_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
746 void
747 rfb_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         }
911 done:
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
919 static void *
920 rfb_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
956 static int
957 sse42_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
968 int
969 rfb_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 = NULL;
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         rc->sfd = -1;
990
991         rc->password = password;
992
993         snprintf(servname, sizeof(servname), "%d", port ? port : 5900);
994
995         if (!hostname || strlen(hostname) == 0)
996 #if defined(INET)
997                 hostname = "127.0.0.1";
998 #elif defined(INET6)
999                 hostname = "[::1]";
1000 #endif
1001
1002         memset(&hints, 0, sizeof(hints));
1003         hints.ai_family = AF_UNSPEC;
1004         hints.ai_socktype = SOCK_STREAM;
1005         hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
1006
1007         if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) {
1008                 EPRINTLN("getaddrinfo: %s", gai_strerror(e));
1009                 goto error;
1010         }
1011
1012         rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0);
1013         if (rc->sfd < 0) {
1014                 perror("socket");
1015                 goto error;
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                 goto error;
1023         }
1024
1025         if (listen(rc->sfd, 1) < 0) {
1026                 perror("listen");
1027                 goto error;
1028         }
1029
1030 #ifndef WITHOUT_CAPSICUM
1031         cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
1032         if (caph_rights_limit(rc->sfd, &rights) == -1)
1033                 errx(EX_OSERR, "Unable to apply rights for sandbox");
1034 #endif
1035
1036         rc->hw_crc = sse42_supported();
1037
1038         rc->conn_wait = wait;
1039         if (wait) {
1040                 pthread_mutex_init(&rc->mtx, NULL);
1041                 pthread_cond_init(&rc->cond, NULL);
1042         }
1043
1044         pthread_create(&rc->tid, NULL, rfb_thr, rc);
1045         pthread_set_name_np(rc->tid, "rfb");
1046
1047         if (wait) {
1048                 DPRINTF(("Waiting for rfb client..."));
1049                 pthread_mutex_lock(&rc->mtx);
1050                 pthread_cond_wait(&rc->cond, &rc->mtx);
1051                 pthread_mutex_unlock(&rc->mtx);
1052                 DPRINTF(("rfb client connected"));
1053         }
1054
1055         freeaddrinfo(ai);
1056         return (0);
1057
1058  error:
1059         if (ai != NULL)
1060                 freeaddrinfo(ai);
1061         if (rc->sfd != -1)
1062                 close(rc->sfd);
1063         free(rc->crc);
1064         free(rc->crc_tmp);
1065         free(rc);
1066         return (-1);
1067 }