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