mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
r7757: Add NTLMv2 support to the NT1 Session setup (ie, not SPNEGO/NTLMSSP)
Session Setup code. Add a mem_ctx argument to a few of the NTLMv2 support functions, and add smb.conf options to control client NTLMv2 behaviour. Andrew Bartlett
This commit is contained in:
parent
edeb908aca
commit
3f35cdb218
@ -203,7 +203,8 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
|
||||
/* TODO: if the remote server is standalone, then we should replace 'domain'
|
||||
with the server name as supplied above */
|
||||
|
||||
if (!SMBNTLMv2encrypt_hash(user,
|
||||
if (!SMBNTLMv2encrypt_hash(gensec_ntlmssp_state,
|
||||
user,
|
||||
domain,
|
||||
nt_hash->hash, &challenge_blob,
|
||||
&struct_blob,
|
||||
|
@ -324,7 +324,8 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO
|
||||
return response;
|
||||
}
|
||||
|
||||
static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
static DATA_BLOB NTLMv2_generate_response(TALLOC_CTX *out_mem_ctx,
|
||||
const uint8_t ntlm_v2_hash[16],
|
||||
const DATA_BLOB *server_chal,
|
||||
const DATA_BLOB *names_blob)
|
||||
{
|
||||
@ -332,7 +333,8 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
DATA_BLOB ntlmv2_client_data;
|
||||
DATA_BLOB final_response;
|
||||
|
||||
TALLOC_CTX *mem_ctx = talloc_init("NTLMv2_generate_response internal context");
|
||||
TALLOC_CTX *mem_ctx = talloc_named(out_mem_ctx, 0,
|
||||
"NTLMv2_generate_response internal context");
|
||||
|
||||
if (!mem_ctx) {
|
||||
return data_blob(NULL, 0);
|
||||
@ -346,7 +348,7 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
/* Given that data, and the challenge from the server, generate a response */
|
||||
SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response);
|
||||
|
||||
final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
|
||||
final_response = data_blob(out_mem_ctx, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
|
||||
|
||||
memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
|
||||
|
||||
@ -358,12 +360,13 @@ static DATA_BLOB NTLMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
return final_response;
|
||||
}
|
||||
|
||||
static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
static DATA_BLOB LMv2_generate_response(TALLOC_CTX *mem_ctx,
|
||||
const uint8_t ntlm_v2_hash[16],
|
||||
const DATA_BLOB *server_chal)
|
||||
{
|
||||
uint8_t lmv2_response[16];
|
||||
DATA_BLOB lmv2_client_data = data_blob(NULL, 8);
|
||||
DATA_BLOB final_response = data_blob(NULL, 24);
|
||||
DATA_BLOB lmv2_client_data = data_blob(mem_ctx, 8);
|
||||
DATA_BLOB final_response = data_blob(mem_ctx, 24);
|
||||
|
||||
/* LMv2 */
|
||||
/* client-supplied random data */
|
||||
@ -383,7 +386,8 @@ static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
|
||||
return final_response;
|
||||
}
|
||||
|
||||
BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t nt_hash[16],
|
||||
BOOL SMBNTLMv2encrypt_hash(TALLOC_CTX *mem_ctx,
|
||||
const char *user, const char *domain, const uint8_t nt_hash[16],
|
||||
const DATA_BLOB *server_chal,
|
||||
const DATA_BLOB *names_blob,
|
||||
DATA_BLOB *lm_response, DATA_BLOB *nt_response,
|
||||
@ -400,10 +404,11 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
|
||||
}
|
||||
|
||||
if (nt_response) {
|
||||
*nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal,
|
||||
*nt_response = NTLMv2_generate_response(mem_ctx,
|
||||
ntlm_v2_hash, server_chal,
|
||||
names_blob);
|
||||
if (user_session_key) {
|
||||
*user_session_key = data_blob(NULL, 16);
|
||||
*user_session_key = data_blob(mem_ctx, 16);
|
||||
|
||||
/* The NTLMv2 calculations also provide a session key, for signing etc later */
|
||||
/* use only the first 16 bytes of nt_response for session key */
|
||||
@ -414,9 +419,10 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
|
||||
/* LMv2 */
|
||||
|
||||
if (lm_response) {
|
||||
*lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
|
||||
*lm_response = LMv2_generate_response(mem_ctx,
|
||||
ntlm_v2_hash, server_chal);
|
||||
if (lm_session_key) {
|
||||
*lm_session_key = data_blob(NULL, 16);
|
||||
*lm_session_key = data_blob(mem_ctx, 16);
|
||||
|
||||
/* The NTLMv2 calculations also provide a session key, for signing etc later */
|
||||
/* use only the first 16 bytes of lm_response for session key */
|
||||
@ -427,7 +433,9 @@ BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uint8_t n
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
|
||||
BOOL SMBNTLMv2encrypt(TALLOC_CTX *mem_ctx,
|
||||
const char *user, const char *domain,
|
||||
const char *password,
|
||||
const DATA_BLOB *server_chal,
|
||||
const DATA_BLOB *names_blob,
|
||||
DATA_BLOB *lm_response, DATA_BLOB *nt_response,
|
||||
@ -436,7 +444,8 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
|
||||
uint8_t nt_hash[16];
|
||||
E_md4hash(password, nt_hash);
|
||||
|
||||
return SMBNTLMv2encrypt_hash(user, domain, nt_hash, server_chal, names_blob,
|
||||
return SMBNTLMv2encrypt_hash(mem_ctx,
|
||||
user, domain, nt_hash, server_chal, names_blob,
|
||||
lm_response, nt_response, lm_session_key, user_session_key);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "auth/auth.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
struct sesssetup_state {
|
||||
union smb_sesssetup setup;
|
||||
@ -50,10 +50,10 @@ static DATA_BLOB lanman_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB ch
|
||||
form an encrypted NT password from a plaintext password
|
||||
and the server supplied challenge
|
||||
*/
|
||||
static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const char *pass, DATA_BLOB challenge)
|
||||
static DATA_BLOB nt_blob(TALLOC_CTX *mem_ctx, const struct samr_Password *nt_hash, DATA_BLOB challenge)
|
||||
{
|
||||
DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24);
|
||||
SMBNTencrypt(pass, challenge.data, blob.data);
|
||||
SMBOWFencrypt(nt_hash->hash, challenge.data, blob.data);
|
||||
return blob;
|
||||
}
|
||||
|
||||
@ -68,26 +68,6 @@ static void set_user_session_key(struct smbcli_session *session,
|
||||
session_key->length);
|
||||
}
|
||||
|
||||
/*
|
||||
setup signing for a NT1 style session setup
|
||||
*/
|
||||
static void use_nt1_session_keys(struct smbcli_session *session,
|
||||
const char *password, const DATA_BLOB *nt_response)
|
||||
{
|
||||
struct smbcli_transport *transport = session->transport;
|
||||
uint8_t nt_hash[16];
|
||||
DATA_BLOB session_key = data_blob_talloc(session, NULL, 16);
|
||||
|
||||
E_md4hash(password, nt_hash);
|
||||
SMBsesskeygen_ntv1(nt_hash, session_key.data);
|
||||
|
||||
smbcli_transport_simple_set_signing(transport, session_key, *nt_response);
|
||||
|
||||
set_user_session_key(session, &session_key);
|
||||
data_blob_free(&session_key);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
handler for completion of a smbcli_request sub-request
|
||||
*/
|
||||
@ -169,6 +149,7 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
|
||||
struct smb_composite_sesssetup *io)
|
||||
{
|
||||
struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state);
|
||||
const struct samr_Password *nt_hash = cli_credentials_get_nt_hash(io->in.credentials, state);
|
||||
const char *password = cli_credentials_get_password(io->in.credentials);
|
||||
|
||||
state->setup.nt1.level = RAW_SESSSETUP_NT1;
|
||||
@ -178,7 +159,7 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
|
||||
state->setup.nt1.in.sesskey = io->in.sesskey;
|
||||
state->setup.nt1.in.capabilities = io->in.capabilities;
|
||||
state->setup.nt1.in.os = "Unix";
|
||||
state->setup.nt1.in.lanman = "Samba";
|
||||
state->setup.nt1.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
|
||||
state->setup.nt1.in.user = cli_credentials_get_username(io->in.credentials);
|
||||
state->setup.nt1.in.domain = cli_credentials_get_domain(io->in.credentials);
|
||||
|
||||
@ -187,14 +168,59 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c,
|
||||
state->setup.nt1.in.password2 = data_blob(NULL, 0);
|
||||
} else if (session->transport->negotiate.sec_mode &
|
||||
NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
|
||||
state->setup.nt1.in.password1 = lanman_blob(state, password,
|
||||
session->transport->negotiate.secblob);
|
||||
state->setup.nt1.in.password2 = nt_blob(state, password,
|
||||
session->transport->negotiate.secblob);
|
||||
use_nt1_session_keys(session, password, &state->setup.nt1.in.password2);
|
||||
} else {
|
||||
DATA_BLOB session_key;
|
||||
/* TODO: NTLMv2 in the client session setup */
|
||||
if (lp_client_ntlmv2_auth()) {
|
||||
DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_netbios_name(), lp_workgroup());
|
||||
DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key;
|
||||
|
||||
/* TODO - test with various domain cases, and without domain */
|
||||
if (!SMBNTLMv2encrypt_hash(state,
|
||||
state->setup.nt1.in.user, state->setup.nt1.in.domain,
|
||||
nt_hash->hash, &session->transport->negotiate.secblob,
|
||||
&names_blob,
|
||||
&lmv2_response, &ntlmv2_response,
|
||||
&lmv2_session_key, &session_key)) {
|
||||
data_blob_free(&names_blob);
|
||||
return NULL;
|
||||
}
|
||||
data_blob_free(&names_blob);
|
||||
state->setup.nt1.in.password1 = lmv2_response;
|
||||
state->setup.nt1.in.password2 = ntlmv2_response;
|
||||
|
||||
smbcli_transport_simple_set_signing(session->transport, session_key,
|
||||
state->setup.nt1.in.password2);
|
||||
set_user_session_key(session, &session_key);
|
||||
|
||||
data_blob_free(&lmv2_session_key);
|
||||
data_blob_free(&session_key);
|
||||
} else {
|
||||
|
||||
state->setup.nt1.in.password2 = nt_blob(state, nt_hash,
|
||||
session->transport->negotiate.secblob);
|
||||
if (lp_client_lanman_auth()) {
|
||||
state->setup.nt1.in.password1 = lanman_blob(state, password,
|
||||
session->transport->negotiate.secblob);
|
||||
} else {
|
||||
/* if not sending the LM password, send the NT password twice */
|
||||
state->setup.nt1.in.password1 = state->setup.nt1.in.password2;
|
||||
}
|
||||
|
||||
session_key = data_blob_talloc(session, NULL, 16);
|
||||
SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
|
||||
smbcli_transport_simple_set_signing(session->transport, session_key,
|
||||
state->setup.nt1.in.password2);
|
||||
set_user_session_key(session, &session_key);
|
||||
|
||||
data_blob_free(&session_key);
|
||||
}
|
||||
|
||||
} else if (lp_client_plaintext_auth()) {
|
||||
state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password));
|
||||
state->setup.nt1.in.password2 = data_blob(NULL, 0);
|
||||
} else {
|
||||
/* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return smb_raw_session_setup_send(session, &state->setup);
|
||||
@ -219,7 +245,7 @@ static struct smbcli_request *session_setup_old(struct composite_context *c,
|
||||
state->setup.old.in.domain = cli_credentials_get_domain(io->in.credentials);
|
||||
state->setup.old.in.user = cli_credentials_get_username(io->in.credentials);
|
||||
state->setup.old.in.os = "Unix";
|
||||
state->setup.old.in.lanman = "Samba";
|
||||
state->setup.old.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
|
||||
|
||||
if (!password) {
|
||||
state->setup.old.in.password = data_blob(NULL, 0);
|
||||
@ -256,7 +282,7 @@ static struct smbcli_request *session_setup_spnego(struct composite_context *c,
|
||||
state->setup.spnego.in.sesskey = io->in.sesskey;
|
||||
state->setup.spnego.in.capabilities = io->in.capabilities;
|
||||
state->setup.spnego.in.os = "Unix";
|
||||
state->setup.spnego.in.lanman = "Samba";
|
||||
state->setup.spnego.in.lanman = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
|
||||
state->setup.spnego.in.workgroup = io->in.workgroup;
|
||||
|
||||
state->setup.spnego.out.vuid = session->vuid;
|
||||
|
@ -235,11 +235,13 @@ typedef struct
|
||||
BOOL bNTSmbSupport;
|
||||
BOOL bNTStatusSupport;
|
||||
BOOL bAllowTrustedDomains;
|
||||
BOOL bPlaintextAuth;
|
||||
BOOL bLanmanAuth;
|
||||
BOOL bNTLMAuth;
|
||||
BOOL bUseSpnego;
|
||||
int server_signing;
|
||||
int client_signing;
|
||||
BOOL bClientPlaintextAuth;
|
||||
BOOL bClientLanManAuth;
|
||||
BOOL bClientNTLMv2Auth;
|
||||
BOOL bHostMSDfs;
|
||||
@ -561,10 +563,12 @@ static struct parm_struct parm_table[] = {
|
||||
{"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"plaintext auth", P_BOOL, P_GLOBAL, &Globals.bPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
|
||||
{"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
|
||||
{"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
|
||||
@ -1242,8 +1246,10 @@ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
|
||||
FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
|
||||
FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
|
||||
FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
|
||||
FN_GLOBAL_BOOL(lp_plaintext_auth, &Globals.bPlaintextAuth)
|
||||
FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
|
||||
FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
|
||||
FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
|
||||
FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
|
||||
FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
|
||||
FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
|
||||
|
@ -551,7 +551,8 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
|
||||
ZERO_STRUCT(user_session_key);
|
||||
|
||||
/* TODO - test with various domain cases, and without domain */
|
||||
if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain,
|
||||
if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
|
||||
samlogon_state->account_name, samlogon_state->account_domain,
|
||||
samlogon_state->password, &samlogon_state->chall,
|
||||
&names_blob,
|
||||
&lmv2_response, &ntlmv2_response,
|
||||
@ -681,7 +682,8 @@ static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, enum nt
|
||||
ZERO_STRUCT(user_session_key);
|
||||
|
||||
/* TODO - test with various domain cases, and without domain */
|
||||
if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain,
|
||||
if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
|
||||
samlogon_state->account_name, samlogon_state->account_domain,
|
||||
samlogon_state->password, &samlogon_state->chall,
|
||||
&names_blob,
|
||||
&lmv2_response, &ntlmv2_response,
|
||||
|
Loading…
Reference in New Issue
Block a user