From owner-svn-src-all@freebsd.org Sun Jul 2 04:14:36 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2C164D9C649; Sun, 2 Jul 2017 04:14:36 +0000 (UTC) (envelope-from araujo@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0290E7EECB; Sun, 2 Jul 2017 04:14:35 +0000 (UTC) (envelope-from araujo@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v624EZjW091315; Sun, 2 Jul 2017 04:14:35 GMT (envelope-from araujo@FreeBSD.org) Received: (from araujo@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v624EYvU091310; Sun, 2 Jul 2017 04:14:34 GMT (envelope-from araujo@FreeBSD.org) Message-Id: <201707020414.v624EYvU091310@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: araujo set sender to araujo@FreeBSD.org using -f From: Marcelo Araujo Date: Sun, 2 Jul 2017 04:14:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r320567 - stable/11/usr.sbin/bhyve X-SVN-Group: stable-11 X-SVN-Commit-Author: araujo X-SVN-Commit-Paths: stable/11/usr.sbin/bhyve X-SVN-Commit-Revision: 320567 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Jul 2017 04:14:36 -0000 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 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 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 + 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 +#include #include #include #include @@ -54,10 +55,23 @@ __FBSDID("$FreeBSD$"); #include "rfb.h" #include "sockstream.h" +#ifndef NO_OPENSSL +#include +#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_ */