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