Page MenuHomeFreeBSD

D10818.id28566.diff
No OneTemporary

D10818.id28566.diff

Index: usr.sbin/bhyve/Makefile
===================================================================
--- usr.sbin/bhyve/Makefile
+++ usr.sbin/bhyve/Makefile
@@ -61,7 +61,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/e1000
CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/mii
Index: usr.sbin/bhyve/bhyve.8
===================================================================
--- usr.sbin/bhyve/bhyve.8
+++ usr.sbin/bhyve/bhyve.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 3, 2017
+.Dd May 19, 2017
.Dt BHYVE 8
.Os
.Sh NAME
@@ -309,7 +309,7 @@
.Pp
Framebuffer devices:
.Bl -tag -width 10n
-.It Oo rfb= Ns Oo Ar IP: Oc Ns Ar port Oc Ns Oo ,w= Ns Ar width Oc Ns Oo ,h= Ns Ar height Oc Ns Oo ,vga= Ns Ar vgaconf Oc Ns Oo Ns ,wait Oc
+.It Oo rfb= Ns Oo Ar IP: Oc Ns Ar port Oc Ns Oo ,w= Ns Ar width Oc Ns Oo ,h= Ns Ar height Oc Ns Oo ,vga= Ns Ar vgaconf Oc Ns Oo Ns ,wait Oc Ns Oo ,password= Ns Ar password Oc
.Bl -tag -width 8n
.It Ar IP:port
An
@@ -368,6 +368,9 @@
to only boot upon the initiation of a VNC connection, simplifying the installation
of operating systems that require immediate keyboard input.
This can be removed for post-installation use.
+.It password
+The password implementation usage is only for interoperability with certain VNC
+clients and must not be used as a method to secure the VNC service.
.El
.El
.Pp
Index: usr.sbin/bhyve/pci_fbuf.c
===================================================================
--- usr.sbin/bhyve/pci_fbuf.c
+++ usr.sbin/bhyve/pci_fbuf.c
@@ -93,6 +93,7 @@
/* rfb server */
char *rfb_host;
+ char *rfb_password;
int rfb_port;
int rfb_wait;
int vga_enabled;
@@ -285,7 +286,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;
@@ -407,7 +409,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: usr.sbin/bhyve/rfb.h
===================================================================
--- usr.sbin/bhyve/rfb.h
+++ usr.sbin/bhyve/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: usr.sbin/bhyve/rfb.c
===================================================================
--- usr.sbin/bhyve/rfb.c
+++ usr.sbin/bhyve/rfb.c
@@ -60,10 +60,14 @@
#include "rfb.h"
#include "sockstream.h"
+#include <openssl/des.h>
+
static int rfb_debug = 0;
#define DPRINTF(params) if (rfb_debug) printf params
#define WPRINTF(params) printf params
+#define AUTH_LENGTH 16
+
struct rfb_softc {
int sfd;
pthread_t tid;
@@ -72,10 +76,15 @@
int width, height;
- bool enc_raw_ok;
- bool enc_zlib_ok;
- bool enc_resize_ok;
+ char *password;
+ unsigned char challenge[AUTH_LENGTH];
+ unsigned char keystr[AUTH_LENGTH];
+ unsigned char crypt_expected[AUTH_LENGTH];
+ bool enc_raw_ok;
+ bool enc_zlib_ok;
+ bool enc_resize_ok;
+
z_stream zstream;
uint8_t *zbuf;
int zbuflen;
@@ -739,9 +748,13 @@
{
const char *vbuf = "RFB 003.008\n";
unsigned char buf[80];
+ unsigned char *message;
+
+ DES_key_schedule ks;
pthread_t tid;
- uint32_t sres;
+ uint32_t sres;
int len;
+ int i;
rc->cfd = cfd;
@@ -753,17 +766,76 @@
/* 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 authentication */
+ switch (buf[0]) {
+ case SECURITY_TYPE_NONE:
+ sres = 0;
+ break;
+ case SECURITY_TYPE_VNC_AUTH:
+ /*
+ * The client encrypts the challenge with DES, using a password
+ * supplied by the user as the key. To form the key, the password
+ * is truncated to eight characters, or padded with null bytes on
+ * the right. The client then sends the resulting 16-bytes response.
+ */
+ strncpy(rc->keystr, rc->password, AUTH_LENGTH);
+
+ /* VNC clients encrypts the challenge with all the bit fields in each
+ * byte of the password mirrored. Here we flip each byte of the keystr.
+ */
+ for (i = 0; i < 16; i++) {
+ rc->keystr[i] = (rc->keystr[i] & 0xF0) >> 4
+ | (rc->keystr[i] & 0x0F) << 4;
+ rc->keystr[i] = (rc->keystr[i] & 0xCC) >> 2
+ | (rc->keystr[i] & 0x33) << 2;
+ rc->keystr[i] = (rc->keystr[i] & 0xAA) >> 1
+ | (rc->keystr[i] & 0x55) << 1;
+ }
+
+ /* Initialize a 16-byte random challenge */
+ arc4random_buf(rc->challenge, sizeof(rc->challenge));
+ stream_write(cfd, rc->challenge, AUTH_LENGTH);
+
+ /* Receive the 16-byte challenge response */
+ stream_read(cfd, buf, AUTH_LENGTH);
+
+ /* We encrypt the challenge sent with the flipped keystr. */
+ DES_set_key((C_Block *)rc->keystr, &ks);
+ DES_ecb_encrypt((C_Block *)rc->challenge,
+ (C_Block *)rc->crypt_expected, &ks, DES_ENCRYPT);
+ DES_ecb_encrypt((C_Block *)(rc->challenge + 8),
+ (C_Block *)(rc->crypt_expected + 8), &ks, DES_ENCRYPT);
+
+ if (memcmp(buf, rc->crypt_expected, AUTH_LENGTH)) {
+ message = "Auth Failed: Invalid Password.";
+ sres = htonl(1);
+ }
+ else
+ sres = 0;
+
+ 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));
+ goto done;
+ }
+
/* 3a. Read client shared-flag byte */
len = stream_read(cfd, buf, 1);
@@ -869,7 +941,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;
@@ -886,6 +958,8 @@
sizeof(uint32_t));
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) {

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 11, 6:33 PM (18 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23588003
Default Alt Text
D10818.id28566.diff (6 KB)

Event Timeline