diff options
Diffstat (limited to 'usr/src/lib/libsmbfs/smb/ntlmssp.c')
-rw-r--r-- | usr/src/lib/libsmbfs/smb/ntlmssp.c | 113 |
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); |