summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs/smb/ntlmssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsmbfs/smb/ntlmssp.c')
-rw-r--r--usr/src/lib/libsmbfs/smb/ntlmssp.c113
1 files changed, 58 insertions, 55 deletions
diff --git a/usr/src/lib/libsmbfs/smb/ntlmssp.c b/usr/src/lib/libsmbfs/smb/ntlmssp.c
index f39fa594ec..5ae583114d 100644
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.c
+++ b/usr/src/lib/libsmbfs/smb/ntlmssp.c
@@ -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,13 +67,14 @@
#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 {
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 @@ struct sec_buf {
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_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb)
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 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
/*
* 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 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
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 @@ out:
*/
static int
ntlm_rand_ssn_key(
- struct smb_ctx *ctx,
ntlmssp_state_t *ssp_st,
struct mbdata *ek_mbp)
{
@@ -603,12 +607,12 @@ ntlm_rand_ssn_key(
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 @@ ntlm_rand_ssn_key(
* 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 @@ int
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);