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