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