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