svn commit: r320567 - stable/11/usr.sbin/bhyve

Marcelo Araujo araujo at FreeBSD.org
Sun Jul 2 04:14:36 UTC 2017


Author: araujo
Date: Sun Jul  2 04:14:34 2017
New Revision: 320567
URL: https://svnweb.freebsd.org/changeset/base/320567

Log:
  MFC r319487-r319488, r319682, r319968, r319995
  
  r319487:
  Add VNC Authentication support based on RFC6143 section 7.2.2.
  
  Submitted by:	Fabian Freyer <fabian.freyer at physik.tu-berlin.de>
  Reworked by:	myself
  Reviewed by:	grehan, rgrimes and jilles
  Relnotes:	Yes.
  Sponsored by:	iXsystems, Inc.
  Differential Revision:	https://reviews.freebsd.org/D10818
  
  r319488:
  Bump manpage date.
  
  r319682:
  Make the VNC authentication build with LibreSSL on HardenedBSD and TrueOS.
  
  PR:		219790
  Submitted by:	Shirkdog <mshirk at daemon-security.com>
  Reviewed by:	grehan and rgrimes
  Sponsored by:	iXsystems, Inc.
  Differential Revision:	https://reviews.freebsd.org/D11071
  
  r319968:
  Initialize variables and use byteorder(9) instead of aliasing char array
  buf via uint32_t pointer.
  
  CID:		1375949
  Reported by:	Coverity, cem
  Reviewed by:	cem
  Sponsored by:	iXsystems, Inc.
  Differential Revision:	https://reviews.freebsd.org/D11153
  
  r319995:
  Check if pthread_create(3) successfully created the thread prior to call
  pthread_join(3). The variable tid is not yet initialized in case
  the authentication fails at early stage, that would lead pthread_join be
  called with an uninitialized variable.
  
  CID:		1375950
  Reported by:	Coverity, cem
  Reviewed by:	cem
  Sponsored by:	iXsystems, Inc.
  Differential Revision:	https://reviews.freebsd.org/D11150

Modified:
  stable/11/usr.sbin/bhyve/Makefile
  stable/11/usr.sbin/bhyve/bhyve.8
  stable/11/usr.sbin/bhyve/pci_fbuf.c
  stable/11/usr.sbin/bhyve/rfb.c
  stable/11/usr.sbin/bhyve/rfb.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/bhyve/Makefile
==============================================================================
--- stable/11/usr.sbin/bhyve/Makefile	Sun Jul  2 04:09:05 2017	(r320566)
+++ stable/11/usr.sbin/bhyve/Makefile	Sun Jul  2 04:14:34 2017	(r320567)
@@ -2,6 +2,8 @@
 # $FreeBSD$
 #
 
+.include <src.opts.mk>
+
 PROG=	bhyve
 PACKAGE=	bhyve
 
@@ -61,6 +63,12 @@ SRCS=	\
 SRCS+=	vmm_instruction_emul.c
 
 LIBADD=	vmmapi md pthread z
+
+.if ${MK_OPENSSL} == "no"
+CFLAGS+=-DNO_OPENSSL
+.else
+LIBADD+=	crypto
+.endif
 
 CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/e1000
 CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/mii

Modified: stable/11/usr.sbin/bhyve/bhyve.8
==============================================================================
--- stable/11/usr.sbin/bhyve/bhyve.8	Sun Jul  2 04:09:05 2017	(r320566)
+++ stable/11/usr.sbin/bhyve/bhyve.8	Sun Jul  2 04:14:34 2017	(r320567)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 3, 2017
+.Dd June 2, 2017
 .Dt BHYVE 8
 .Os
 .Sh NAME
@@ -309,7 +309,7 @@ Emergency write is advertised, but no-op at present.
 .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,11 @@ Instruct
 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
+This type of authentication is known to be cryptographically weak and is not
+intended for use on untrusted networks.
+Many implementations will want to use stronger security, such as running
+the session over an encrypted channel provided by IPsec or SSH.
 .El
 .El
 .Pp

Modified: stable/11/usr.sbin/bhyve/pci_fbuf.c
==============================================================================
--- stable/11/usr.sbin/bhyve/pci_fbuf.c	Sun Jul  2 04:09:05 2017	(r320566)
+++ stable/11/usr.sbin/bhyve/pci_fbuf.c	Sun Jul  2 04:14:34 2017	(r320567)
@@ -93,6 +93,7 @@ struct pci_fbuf_softc {
 
 	/* rfb server */
 	char      *rfb_host;
+	char      *rfb_password;
 	int       rfb_port;
 	int       rfb_wait;
 	int       vga_enabled;
@@ -285,7 +286,8 @@ pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *o
 				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 @@ pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *p
 
 	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);

Modified: stable/11/usr.sbin/bhyve/rfb.c
==============================================================================
--- stable/11/usr.sbin/bhyve/rfb.c	Sun Jul  2 04:09:05 2017	(r320566)
+++ stable/11/usr.sbin/bhyve/rfb.c	Sun Jul  2 04:14:34 2017	(r320567)
@@ -29,6 +29,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/endian.h>
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <sys/time.h>
@@ -54,10 +55,23 @@ __FBSDID("$FreeBSD$");
 #include "rfb.h"
 #include "sockstream.h"
 
+#ifndef NO_OPENSSL
+#include <openssl/des.h>
+#endif
+
 static int rfb_debug = 0;
 #define	DPRINTF(params) if (rfb_debug) printf params
 #define	WPRINTF(params) printf params
 
+#define AUTH_LENGTH	16
+#define PASSWD_LENGTH	8
+
+#define SECURITY_TYPE_NONE 1
+#define SECURITY_TYPE_VNC_AUTH 2
+
+#define AUTH_FAILED_UNAUTH 1
+#define AUTH_FAILED_ERROR 2
+
 struct rfb_softc {
 	int		sfd;
 	pthread_t	tid;
@@ -66,10 +80,12 @@ struct rfb_softc {
 
 	int		width, height;
 
-	bool		enc_raw_ok;
-	bool		enc_zlib_ok;
-	bool		enc_resize_ok;
+	char		*password;
 
+	bool	enc_raw_ok;
+	bool	enc_zlib_ok;
+	bool	enc_resize_ok;
+
 	z_stream	zstream;
 	uint8_t		*zbuf;
 	int		zbuflen;
@@ -202,7 +218,7 @@ static void
 rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd)
 {
 	struct rfb_srvr_updt_msg supdt_msg;
-        struct rfb_srvr_rect_hdr srect_hdr;
+	struct rfb_srvr_rect_hdr srect_hdr;
 
 	/* Number of rectangles: 1 */
 	supdt_msg.type = 0;
@@ -733,9 +749,21 @@ rfb_handle(struct rfb_softc *rc, int cfd)
 {
 	const char *vbuf = "RFB 003.008\n";
 	unsigned char buf[80];
+	unsigned char *message = NULL;
+
+#ifndef NO_OPENSSL
+	unsigned char challenge[AUTH_LENGTH];
+	unsigned char keystr[PASSWD_LENGTH];
+	unsigned char crypt_expected[AUTH_LENGTH];
+
+	DES_key_schedule ks;
+	int i;
+#endif
+
 	pthread_t tid;
-        uint32_t sres;
+	uint32_t sres = 0;
 	int len;
+	int perror = 1;
 
 	rc->cfd = cfd;
 
@@ -745,19 +773,93 @@ rfb_handle(struct rfb_softc *rc, int cfd)
 	/* 1b. Read client version */
 	len = read(cfd, buf, sizeof(buf));
 
-	/* 2a. Send security type 'none' */
+	/* 2a. Send security type */
 	buf[0] = 1;
-	buf[1] = 1; /* none */
+#ifndef NO_OPENSSL
+	if (rc->password) 
+		buf[1] = SECURITY_TYPE_VNC_AUTH;
+	else
+		buf[1] = SECURITY_TYPE_NONE;
+#else
+	buf[1] = SECURITY_TYPE_NONE;
+#endif
+
 	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.
+		 */
+#ifndef NO_OPENSSL
+		strncpy(keystr, rc->password, PASSWD_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 < PASSWD_LENGTH; 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 */
+		arc4random_buf(challenge, sizeof(challenge));
+		stream_write(cfd, challenge, AUTH_LENGTH);
+
+		/* Receive the 16-byte challenge response */
+		stream_read(cfd, buf, AUTH_LENGTH);
+
+		memcpy(crypt_expected, challenge, AUTH_LENGTH);
+
+		/* Encrypt the Challenge with DES */
+		DES_set_key((const_DES_cblock *)keystr, &ks);
+		DES_ecb_encrypt((const_DES_cblock *)challenge,
+				(const_DES_cblock *)crypt_expected,
+				&ks, DES_ENCRYPT);
+		DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH),
+				(const_DES_cblock *)(crypt_expected +
+				PASSWD_LENGTH),
+				&ks, DES_ENCRYPT);
+
+		if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) {
+			message = "Auth Failed: Invalid Password.";
+			sres = htonl(1);
+		} else
+			sres = 0;
+#else
+		sres = 0;
+		WPRINTF(("Auth not supported, no OpenSSL in your system"));
+#endif
+
+		break;
+	}
+
+	/* 2d. Write back a status */
 	stream_write(cfd, &sres, 4);
 
+	if (sres) {
+		be32enc(buf, strlen(message));
+		stream_write(cfd, buf, 4);
+		stream_write(cfd, message, strlen(message));
+		goto done;
+	}
+
 	/* 3a. Read client shared-flag byte */
 	len = stream_read(cfd, buf, 1);
 
@@ -771,8 +873,9 @@ rfb_handle(struct rfb_softc *rc, int cfd)
 
 	rfb_send_screen(rc, cfd, 1);
 
-	pthread_create(&tid, NULL, rfb_wr_thr, rc);
-	pthread_set_name_np(tid, "rfbout");
+	perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
+	if (perror == 0)
+		pthread_set_name_np(tid, "rfbout");
 
         /* Now read in client requests. 1st byte identifies type */
 	for (;;) {
@@ -808,7 +911,8 @@ rfb_handle(struct rfb_softc *rc, int cfd)
 	}
 done:
 	rc->cfd = -1;
-	pthread_join(tid, NULL);
+	if (perror == 0)
+		pthread_join(tid, NULL);
 	if (rc->enc_zlib_ok)
 		deflateEnd(&rc->zstream);
 }
@@ -863,7 +967,7 @@ sse42_supported(void)
 }
 
 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;
@@ -877,6 +981,8 @@ rfb_init(char *hostname, int port, int wait)
 	                     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) {

Modified: stable/11/usr.sbin/bhyve/rfb.h
==============================================================================
--- stable/11/usr.sbin/bhyve/rfb.h	Sun Jul  2 04:09:05 2017	(r320566)
+++ stable/11/usr.sbin/bhyve/rfb.h	Sun Jul  2 04:14:34 2017	(r320567)
@@ -31,6 +31,6 @@
 
 #define	RFB_PORT	5900
 
-int	rfb_init(char *hostname, int port, int wait);
+int	rfb_init(char *hostname, int port, int wait, char *password);
 
 #endif /* _RFB_H_ */


More information about the svn-src-all mailing list