From e578c33c2c8bc23a9a78259613f33b65d7d1668f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 19 Jun 2005 13:26:32 +0000 Subject: 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 used to be commit 3f35cdb218a3dae08a05e77452ca9f73716ceb28) --- source4/auth/ntlmssp/ntlmssp_client.c | 3 +- source4/libcli/auth/smbencrypt.c | 35 +++++++++----- source4/libcli/composite/sesssetup.c | 90 ++++++++++++++++++++++------------- source4/param/loadparm.c | 6 +++ source4/torture/rpc/samlogon.c | 6 ++- 5 files changed, 92 insertions(+), 48 deletions(-) diff --git a/source4/auth/ntlmssp/ntlmssp_client.c b/source4/auth/ntlmssp/ntlmssp_client.c index 23fe8f5cc9..726885c82f 100644 --- a/source4/auth/ntlmssp/ntlmssp_client.c +++ b/source4/auth/ntlmssp/ntlmssp_client.c @@ -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, diff --git a/source4/libcli/auth/smbencrypt.c b/source4/libcli/auth/smbencrypt.c index 3a4a724789..a9a7bb9903 100644 --- a/source4/libcli/auth/smbencrypt.c +++ b/source4/libcli/auth/smbencrypt.c @@ -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); } diff --git a/source4/libcli/composite/sesssetup.c b/source4/libcli/composite/sesssetup.c index 2736d91262..2a75fb4e20 100644 --- a/source4/libcli/composite/sesssetup.c +++ b/source4/libcli/composite/sesssetup.c @@ -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; diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 26466797ad..49bb52230e 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -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) diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index 37b9025194..a7d57899aa 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -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, -- cgit