--- old/usr/src/lib/libsmbfs/smb/ntlmssp.c	Mon Aug  5 17:16:38 2019
+++ new/usr/src/lib/libsmbfs/smb/ntlmssp.c	Mon Aug  5 17:16:38 2019
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -67,7 +67,7 @@
 #include "ntlmssp.h"
 
 /* A shorter alias for a crazy long name from [MS-NLMP] */
-#define	NTLMSSP_NEGOTIATE_NTLM2 \
+#define	NTLMSSP_NEGOTIATE_ESS \
 	NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
 
 typedef struct ntlmssp_state {
@@ -74,6 +74,7 @@
 	uint32_t ss_flags;
 	char *ss_target_name;	/* Primary domain or server name */
 	struct mbuf *ss_target_info;
+	uchar_t	ss_ssnkey[NTLM_HASH_SZ];
 	uchar_t	ss_kxkey[NTLM_HASH_SZ];
 } ntlmssp_state_t;
 
@@ -90,8 +91,7 @@
 static const char ntlmssp_id[ID_SZ] = "NTLMSSP";
 
 static int
-ntlm_rand_ssn_key(struct smb_ctx *ctx,
-	ntlmssp_state_t *ssp_st, struct mbdata *ek_mbp);
+ntlm_rand_ssn_key(ntlmssp_state_t *ssp_st, struct mbdata *ek_mbp);
 
 /*
  * Get a "security buffer" (header part)
@@ -249,16 +249,14 @@
 	    NTLMSSP_NEGOTIATE_SEAL |
 	    /* NTLMSSP_NEGOTIATE_LM_KEY (never) */
 	    NTLMSSP_NEGOTIATE_NTLM |
-	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN (set below) */
-	    NTLMSSP_NEGOTIATE_NTLM2 |
+	    NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
+	    NTLMSSP_NEGOTIATE_ESS |
 	    NTLMSSP_NEGOTIATE_128 |
 	    NTLMSSP_NEGOTIATE_KEY_EXCH |
 	    NTLMSSP_NEGOTIATE_56;
 
-	if (ctx->ct_vcflags & SMBV_WILL_SIGN) {
-		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
-		ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
-	}
+	if ((ctx->ct_vopt & SMBVOPT_SIGNING_ENABLED) == 0)
+		ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
 
 	bcopy(ntlmssp_id, &hdr.h_id, ID_SZ);
 	hdr.h_type = NTLMSSP_MSGTYPE_NEGOTIATE;
@@ -447,15 +445,20 @@
 		/*
 		 * We're setting up a NULL session, meaning
 		 * the lm_mbc, nt_mbc parts remain empty.
-		 * Let's add the "anon" flag (hint).
-		 * As there is no session key, disable the
-		 * fancy session key stuff.
+		 * Let's add the "anon" flag (hint), and
+		 * as we have no OWF hashes, we can't use
+		 * "extended session security" (_ESS).
+		 * The SessionBaseKey is all zeros, so
+		 * the KeyExchangeKey is too.  Otherwise
+		 * this is like NTLMv2/LMv2
 		 */
-		hdr.h_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION;
-		ssp_st->ss_flags &= ~(
-		    NTLMSSP_NEGOTIATE_NTLM2 |
-		    NTLMSSP_NEGOTIATE_KEY_EXCH);
+		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION;
+		ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_ESS;
+		hdr.h_flags = ssp_st->ss_flags;
 		err = 0;
+		/* KeyExchangeKey = SessionBaseKey = (zeros) */
+		memset(ssp_st->ss_ssnkey, 0, NTLM_HASH_SZ);
+		memset(ssp_st->ss_kxkey, 0, NTLM_HASH_SZ);
 	} else if (ctx->ct_authflags & SMB_AT_NTLM2) {
 		/*
 		 * Doing NTLMv2/LMv2
@@ -465,47 +468,49 @@
 		if (err)
 			goto out;
 		err = ntlm_put_v2_responses(ctx, &ti_mbc,
-		    &lm_mbc, &nt_mbc);
+		    &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey);
 		if (err)
 			goto out;
-		/* The "key exg. key" is the session base key */
-		memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ);
-
-	} else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+		/* KeyExchangeKey = SessionBaseKey (v2) */
+		memcpy(ssp_st->ss_kxkey, ssp_st->ss_ssnkey, NTLM_HASH_SZ);
+	} else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_ESS) {
 		/*
 		 * Doing NTLM ("v1x") which is NTLM with
 		 * "Extended Session Security"
 		 */
 		err = ntlm_put_v1x_responses(ctx,
-		    &lm_mbc, &nt_mbc);
+		    &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey);
 		if (err)
 			goto out;
-		/* Compute the "Key exchange key". */
-		ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_kxkey);
+		/*
+		 * "v1x computes the KeyExchangeKey from both the
+		 * server and client nonce and (v1) SessionBaseKey.
+		 */
+		ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_ssnkey,
+		    ssp_st->ss_kxkey);
 	} else {
 		/*
 		 * Doing plain old NTLM (and LM if enabled)
 		 */
 		err = ntlm_put_v1_responses(ctx,
-		    &lm_mbc, &nt_mbc);
+		    &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey);
 		if (err)
 			goto out;
-		/* The "key exg. key" is the session base key */
-		memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ);
+		/* KeyExchangeKey = SessionBaseKey (v1) */
+		memcpy(ssp_st->ss_kxkey, ssp_st->ss_ssnkey, NTLM_HASH_SZ);
 	}
 
 	/*
-	 * Compute the "Exported Session Key" and (possibly)
-	 * the "Encrypted Random Sesion Key".
-	 * [MS-NLMP 3.1.5.1.2]
+	 * Compute the "ExportedSessionKey" and (possibly) the
+	 * "EncryptedRandomSesionKey". [MS-NLMP 3.1.5.1.2]
 	 */
 	if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
-		err = ntlm_rand_ssn_key(ctx, ssp_st, &ek_mbc);
+		err = ntlm_rand_ssn_key(ssp_st, &ek_mbc);
 		if (err)
 			goto out;
 	} else {
 		/* ExportedSessionKey is the KeyExchangeKey */
-		memcpy(ctx->ct_ssn_key, ssp_st->ss_kxkey, NTLM_HASH_SZ);
+		memcpy(ssp_st->ss_ssnkey, ssp_st->ss_kxkey, NTLM_HASH_SZ);
 		/* EncryptedRandomSessionKey remains NULL */
 	}
 
@@ -590,7 +595,6 @@
  */
 static int
 ntlm_rand_ssn_key(
-	struct smb_ctx *ctx,
 	ntlmssp_state_t *ssp_st,
 	struct mbdata *ek_mbp)
 {
@@ -603,12 +607,12 @@
 	encr_ssn_key = mb_reserve(ek_mbp, NTLM_HASH_SZ);
 
 	/* Set "ExportedSessionKey to NONCE(16) */
-	(void) smb_get_urandom(ctx->ct_ssn_key, NTLM_HASH_SZ);
+	(void) smb_get_urandom(ssp_st->ss_ssnkey, NTLM_HASH_SZ);
 
 	/* Set "EncryptedRandomSessionKey" to RC4(...) */
 	err = smb_encrypt_RC4(encr_ssn_key, NTLM_HASH_SZ,
 	    ssp_st->ss_kxkey, NTLM_HASH_SZ,
-	    ctx->ct_ssn_key, NTLM_HASH_SZ);
+	    ssp_st->ss_ssnkey, NTLM_HASH_SZ);
 
 	return (err);
 }
@@ -617,34 +621,29 @@
  * ntlmssp_final
  *
  * Called after successful authentication.
- * Setup the MAC key for signing.
+ * Save the session key.
  */
 int
 ntlmssp_final(struct ssp_ctx *sp)
 {
 	struct smb_ctx *ctx = sp->smb_ctx;
+	ntlmssp_state_t *ssp_st = sp->sp_private;
 	int err = 0;
 
 	/*
-	 * MAC_key is just the session key, but
-	 * Only on the first successful auth.
+	 * Update/save the session key.
 	 */
-	if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) &&
-	    (ctx->ct_mackey == NULL)) {
-		ctx->ct_mackeylen = NTLM_HASH_SZ;
-		ctx->ct_mackey = malloc(ctx->ct_mackeylen);
-		if (ctx->ct_mackey == NULL) {
-			ctx->ct_mackeylen = 0;
-			err = ENOMEM;
-			goto out;
-		}
-		memcpy(ctx->ct_mackey, ctx->ct_ssn_key, NTLM_HASH_SZ);
-		/*
-		 * Apparently, the server used seq. no. zero
-		 * for our previous message, so next is two.
-		 */
-		ctx->ct_mac_seqno = 2;
+	if (ctx->ct_ssnkey_buf != NULL) {
+		free(ctx->ct_ssnkey_buf);
+		ctx->ct_ssnkey_buf = NULL;
 	}
+	ctx->ct_ssnkey_buf = malloc(NTLM_HASH_SZ);
+	if (ctx->ct_ssnkey_buf == NULL) {
+		err = ENOMEM;
+		goto out;
+	}
+	ctx->ct_ssnkey_len = NTLM_HASH_SZ;
+	memcpy(ctx->ct_ssnkey_buf, ssp_st->ss_ssnkey, NTLM_HASH_SZ);
 
 out:
 	return (err);
@@ -728,13 +727,17 @@
 ntlmssp_init_client(struct ssp_ctx *sp)
 {
 	ntlmssp_state_t *ssp_st;
+	smb_ctx_t *ctx = sp->smb_ctx;
 
-	if ((sp->smb_ctx->ct_authflags &
+	if ((ctx->ct_authflags &
 	    (SMB_AT_NTLM2 | SMB_AT_NTLM1 | SMB_AT_ANON)) == 0) {
 		DPRINT("No NTLM authflags");
 		return (EINVAL);
 	}
 
+	/* Get the client nonce. */
+	(void) smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ);
+
 	ssp_st = calloc(1, sizeof (*ssp_st));
 	if (ssp_st == NULL)
 		return (ENOMEM);
