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