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