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