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 773 rc->cfd = cfd; 774 775 /* 1a. Send server version */ 776 stream_write(cfd, vbuf, strlen(vbuf)); 777 778 /* 1b. Read client version */ 779 len = read(cfd, buf, sizeof(buf)); 780 781 /* 2a. Send security type */ 782 buf[0] = 1; 783 #ifndef NO_OPENSSL 784 if (rc->password) 785 buf[1] = SECURITY_TYPE_VNC_AUTH; 786 else 787 buf[1] = SECURITY_TYPE_NONE; 788 #else 789 buf[1] = SECURITY_TYPE_NONE; 790 #endif 791 792 stream_write(cfd, buf, 2); 793 794 /* 2b. Read agreed security type */ 795 len = stream_read(cfd, buf, 1); 796 797 /* 2c. Do VNC authentication */ 798 switch (buf[0]) { 799 case SECURITY_TYPE_NONE: 800 sres = 0; 801 break; 802 case SECURITY_TYPE_VNC_AUTH: 803 /* 804 * The client encrypts the challenge with DES, using a password 805 * supplied by the user as the key. 806 * To form the key, the password is truncated to 807 * eight characters, or padded with null bytes on the right. 808 * The client then sends the resulting 16-bytes response. 809 */ 810 #ifndef NO_OPENSSL 811 strncpy(keystr, rc->password, PASSWD_LENGTH); 812 813 /* VNC clients encrypts the challenge with all the bit fields 814 * in each byte of the password mirrored. 815 * Here we flip each byte of the keystr. 816 */ 817 for (i = 0; i < PASSWD_LENGTH; i++) { 818 keystr[i] = (keystr[i] & 0xF0) >> 4 819 | (keystr[i] & 0x0F) << 4; 820 keystr[i] = (keystr[i] & 0xCC) >> 2 821 | (keystr[i] & 0x33) << 2; 822 keystr[i] = (keystr[i] & 0xAA) >> 1 823 | (keystr[i] & 0x55) << 1; 824 } 825 826 /* Initialize a 16-byte random challenge */ 827 arc4random_buf(challenge, sizeof(challenge)); 828 stream_write(cfd, challenge, AUTH_LENGTH); 829 830 /* Receive the 16-byte challenge response */ 831 stream_read(cfd, buf, AUTH_LENGTH); 832 833 memcpy(crypt_expected, challenge, AUTH_LENGTH); 834 835 /* Encrypt the Challenge with DES */ 836 DES_set_key((const_DES_cblock *)keystr, &ks); 837 DES_ecb_encrypt((const_DES_cblock *)challenge, 838 (const_DES_cblock *)crypt_expected, 839 &ks, DES_ENCRYPT); 840 DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH), 841 (const_DES_cblock *)(crypt_expected + 842 PASSWD_LENGTH), 843 &ks, DES_ENCRYPT); 844 845 if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) { 846 message = "Auth Failed: Invalid Password."; 847 sres = htonl(1); 848 } else 849 sres = 0; 850 #else 851 sres = 0; 852 WPRINTF(("Auth not supported, no OpenSSL in your system")); 853 #endif 854 855 break; 856 } 857 858 /* 2d. Write back a status */ 859 stream_write(cfd, &sres, 4); 860 861 if (sres) { 862 be32enc(buf, strlen(message)); 863 stream_write(cfd, buf, 4); 864 stream_write(cfd, message, strlen(message)); 865 goto done; 866 } 867 868 /* 3a. Read client shared-flag byte */ 869 len = stream_read(cfd, buf, 1); 870 871 /* 4a. Write server-init info */ 872 rfb_send_server_init_msg(cfd); 873 874 if (!rc->zbuf) { 875 rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16); 876 assert(rc->zbuf != NULL); 877 } 878 879 rfb_send_screen(rc, cfd, 1); 880 881 pthread_create(&tid, NULL, rfb_wr_thr, rc); 882 pthread_set_name_np(tid, "rfbout"); 883 884 /* Now read in client requests. 1st byte identifies type */ 885 for (;;) { 886 len = read(cfd, buf, 1); 887 if (len <= 0) { 888 DPRINTF(("rfb client exiting\r\n")); 889 break; 890 } 891 892 switch (buf[0]) { 893 case 0: 894 rfb_recv_set_pixfmt_msg(rc, cfd); 895 break; 896 case 2: 897 rfb_recv_set_encodings_msg(rc, cfd); 898 break; 899 case 3: 900 rfb_recv_update_msg(rc, cfd, 1); 901 break; 902 case 4: 903 rfb_recv_key_msg(rc, cfd); 904 break; 905 case 5: 906 rfb_recv_ptr_msg(rc, cfd); 907 break; 908 case 6: 909 rfb_recv_cuttext_msg(rc, cfd); 910 break; 911 default: 912 WPRINTF(("rfb unknown cli-code %d!\n", buf[0] & 0xff)); 913 goto done; 914 } 915 } 916 done: 917 rc->cfd = -1; 918 pthread_join(tid, NULL); 919 if (rc->enc_zlib_ok) 920 deflateEnd(&rc->zstream); 921 } 922 923 static void * 924 rfb_thr(void *arg) 925 { 926 struct rfb_softc *rc; 927 sigset_t set; 928 929 int cfd; 930 931 rc = arg; 932 933 sigemptyset(&set); 934 sigaddset(&set, SIGPIPE); 935 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { 936 perror("pthread_sigmask"); 937 return (NULL); 938 } 939 940 for (;;) { 941 rc->enc_raw_ok = false; 942 rc->enc_zlib_ok = false; 943 rc->enc_resize_ok = false; 944 945 cfd = accept(rc->sfd, NULL, NULL); 946 if (rc->conn_wait) { 947 pthread_mutex_lock(&rc->mtx); 948 pthread_cond_signal(&rc->cond); 949 pthread_mutex_unlock(&rc->mtx); 950 rc->conn_wait = 0; 951 } 952 rfb_handle(rc, cfd); 953 close(cfd); 954 } 955 956 /* NOTREACHED */ 957 return (NULL); 958 } 959 960 static int 961 sse42_supported(void) 962 { 963 u_int cpu_registers[4], ecx; 964 965 do_cpuid(1, cpu_registers); 966 967 ecx = cpu_registers[2]; 968 969 return ((ecx & CPUID2_SSE42) != 0); 970 } 971 972 int 973 rfb_init(char *hostname, int port, int wait, char *password) 974 { 975 struct rfb_softc *rc; 976 struct sockaddr_in sin; 977 int on = 1; 978 #ifndef WITHOUT_CAPSICUM 979 cap_rights_t rights; 980 #endif 981 982 rc = calloc(1, sizeof(struct rfb_softc)); 983 984 rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 985 sizeof(uint32_t)); 986 rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32), 987 sizeof(uint32_t)); 988 rc->crc_width = RFB_MAX_WIDTH; 989 rc->crc_height = RFB_MAX_HEIGHT; 990 991 rc->password = password; 992 993 rc->sfd = socket(AF_INET, SOCK_STREAM, 0); 994 if (rc->sfd < 0) { 995 perror("socket"); 996 return (-1); 997 } 998 999 setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 1000 1001 sin.sin_len = sizeof(sin); 1002 sin.sin_family = AF_INET; 1003 sin.sin_port = port ? htons(port) : htons(5900); 1004 if (hostname && strlen(hostname) > 0) 1005 inet_pton(AF_INET, hostname, &(sin.sin_addr)); 1006 else 1007 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1008 1009 if (bind(rc->sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 1010 perror("bind"); 1011 return (-1); 1012 } 1013 1014 if (listen(rc->sfd, 1) < 0) { 1015 perror("listen"); 1016 return (-1); 1017 } 1018 1019 #ifndef WITHOUT_CAPSICUM 1020 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); 1021 if (cap_rights_limit(rc->sfd, &rights) == -1 && errno != ENOSYS) 1022 errx(EX_OSERR, "Unable to apply rights for sandbox"); 1023 #endif 1024 1025 rc->hw_crc = sse42_supported(); 1026 1027 rc->conn_wait = wait; 1028 if (wait) { 1029 pthread_mutex_init(&rc->mtx, NULL); 1030 pthread_cond_init(&rc->cond, NULL); 1031 } 1032 1033 pthread_create(&rc->tid, NULL, rfb_thr, rc); 1034 pthread_set_name_np(rc->tid, "rfb"); 1035 1036 if (wait) { 1037 DPRINTF(("Waiting for rfb client...\n")); 1038 pthread_mutex_lock(&rc->mtx); 1039 pthread_cond_wait(&rc->cond, &rc->mtx); 1040 pthread_mutex_unlock(&rc->mtx); 1041 } 1042 1043 return (0); 1044 } 1045