diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-06-19 13:26:32 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:18:32 -0500 |
commit | e578c33c2c8bc23a9a78259613f33b65d7d1668f (patch) | |
tree | c4d81bd1c4bcd31b456533e8ce6e20353344c0cf /source4/libcli | |
parent | 3e73885ba4eb0d60d6ed997360e0ea3e17dc154d (diff) | |
download | samba-e578c33c2c8bc23a9a78259613f33b65d7d1668f.tar.gz samba-e578c33c2c8bc23a9a78259613f33b65d7d1668f.tar.bz2 samba-e578c33c2c8bc23a9a78259613f33b65d7d1668f.zip |
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)
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/auth/smbencrypt.c | 35 | ||||
-rw-r--r-- | source4/libcli/composite/sesssetup.c | 90 |
2 files changed, 80 insertions, 45 deletions
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; } @@ -69,26 +69,6 @@ static void set_user_session_key(struct smbcli_session *session, } /* - 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 */ static void request_handler(struct smbcli_request *req) @@ -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; |