summaryrefslogtreecommitdiff
path: root/source4/libcli
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-06-19 13:26:32 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:18:32 -0500
commite578c33c2c8bc23a9a78259613f33b65d7d1668f (patch)
treec4d81bd1c4bcd31b456533e8ce6e20353344c0cf /source4/libcli
parent3e73885ba4eb0d60d6ed997360e0ea3e17dc154d (diff)
downloadsamba-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.c35
-rw-r--r--source4/libcli/composite/sesssetup.c90
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;