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