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