Index: projects/bhyve_graphics/Makefile =================================================================== --- projects/bhyve_graphics/Makefile +++ projects/bhyve_graphics/Makefile @@ -59,7 +59,7 @@ .PATH: ${BHYVE_SYSDIR}/sys/amd64/vmm SRCS+= vmm_instruction_emul.c -LIBADD= vmmapi md pthread z +LIBADD= vmmapi md pthread z crypto CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/usb/controller Index: projects/bhyve_graphics/pci_fbuf.c =================================================================== --- projects/bhyve_graphics/pci_fbuf.c +++ projects/bhyve_graphics/pci_fbuf.c @@ -93,6 +93,7 @@ /* rfb server */ char *rfb_host; + char *rfb_password; int rfb_port; int rfb_wait; int use_vga; @@ -277,7 +278,8 @@ goto done; } else if (sc->memregs.height == 0) sc->memregs.height = 1080; - + } else if (!strcmp(xopts, "password")) { + sc->rfb_password = config; } else { pci_fbuf_usage(xopts); ret = -1; @@ -389,7 +391,7 @@ memset((void *)sc->fb_base, 0, FB_SIZE); - error = rfb_init(sc->rfb_host, sc->rfb_port, sc->rfb_wait); + error = rfb_init(sc->rfb_host, sc->rfb_port, sc->rfb_wait, sc->rfb_password); done: if (error) free(sc); Index: projects/bhyve_graphics/rfb.h =================================================================== --- projects/bhyve_graphics/rfb.h +++ projects/bhyve_graphics/rfb.h @@ -31,6 +31,12 @@ #define RFB_PORT 5900 -int rfb_init(char *hostname, int port, int wait); +int rfb_init(char *hostname, int port, int wait, char *password); +#define SECURITY_TYPE_NONE 1 +#define SECURITY_TYPE_VNC_AUTH 2 + +#define AUTH_FAILED_UNAUTH 1 +#define AUTH_FAILED_ERROR 2 + #endif /* _RFB_H_ */ Index: projects/bhyve_graphics/rfb.c =================================================================== --- projects/bhyve_graphics/rfb.c +++ projects/bhyve_graphics/rfb.c @@ -48,6 +48,9 @@ #include #include +#include +#include + #include "bhyvegc.h" #include "console.h" #include "rfb.h" @@ -65,6 +68,8 @@ int width, height; + char *password; + bool enc_raw_ok; bool enc_zlib_ok; bool enc_resize_ok; @@ -758,9 +763,11 @@ { const char *vbuf = "RFB 003.008\n"; unsigned char buf[80]; + unsigned char *chall, *keystr, *expected, *message; + DES_key_schedule ks; pthread_t tid; - uint32_t sres; - int len; + uint32_t sres; + int len, i; rc->cfd = cfd; @@ -772,17 +779,83 @@ /* 2a. Send security type 'none' */ buf[0] = 1; - buf[1] = 1; /* none */ + if (rc->password) + buf[1] = SECURITY_TYPE_VNC_AUTH; + else + buf[1] = SECURITY_TYPE_NONE; + stream_write(cfd, buf, 2); - /* 2b. Read agreed security type */ len = stream_read(cfd, buf, 1); - /* 2c. Write back a status of 0 */ - sres = 0; + /* 2c. Do VNC authentification */ + sres = 4; + switch (buf[0]) { + case SECURITY_TYPE_NONE: + sres = 0; + break; + case SECURITY_TYPE_VNC_AUTH: + keystr = calloc(17, sizeof(unsigned char)); + strncpy(keystr, rc->password,16); + + /* Flip each byte in the key */ + for (i = 0; i < 16; i++) { + keystr[i] = (keystr[i] & 0xF0) >> 4 + | (keystr[i] & 0x0F) << 4; + keystr[i] = (keystr[i] & 0xCC) >> 2 + | (keystr[i] & 0x33) << 2; + keystr[i] = (keystr[i] & 0xAA) >> 1 + | (keystr[i] & 0x55) << 1; + } + + /* Initialize a 16-byte random challenge */ + chall = calloc(17, sizeof(unsigned char)); + if (!RAND_bytes(chall, 16)) { + WPRINTF(("rfb RAND_bytes failed\r\n")); + message = "Auth Failed: Internal Error."; + sres = htonl(1); + free(keystr); + free(chall); + break; + } + stream_write(cfd, chall, 16); + + /* Receive the 16-byte challenge response */ + stream_read(cfd, buf, 16); + + /* Encrypt the Challenge with DES */ + expected=calloc(17, sizeof(unsigned char)); + DES_set_key((C_Block *)keystr, &ks); + DES_ecb_encrypt((C_Block *)chall, (C_Block *)expected, + &ks, DES_ENCRYPT); + DES_ecb_encrypt((C_Block *)(chall+8), (C_Block *)(expected+8), + &ks, DES_ENCRYPT); + + if (memcmp(buf, expected, 16)) { + message = "Auth Failed: Invalid Password."; + sres = htonl(1); + } + else + sres = 0; + + free(keystr); + free(chall); + free(expected); + break; + } + + /* 2d. Write back a status */ stream_write(cfd, &sres, 4); + if (sres) { + *((uint32_t *) buf) = htonl(strlen(message)); + strncpy(buf+4, message, strlen(message)+1); + stream_write(cfd, buf, 4+strlen(message)); + WPRINTF(("%d, %s\r\n", *(uint32_t*)buf, buf+4)); + goto done; + } + /* 3a. Read client shared-flag byte */ len = stream_read(cfd, buf, 1); @@ -886,7 +959,7 @@ } int -rfb_init(char *hostname, int port, int wait) +rfb_init(char *hostname, int port, int wait, char *password) { struct rfb_softc *rc; struct sockaddr_in sin; @@ -901,6 +974,8 @@ rc->crc_width = RFB_MAX_WIDTH; rc->crc_height = RFB_MAX_HEIGHT; + rc->password = password; + rc->sfd = socket(AF_INET, SOCK_STREAM, 0); if (rc->sfd < 0) { perror("socket");