From 874cd2db86e7feb82eedd2b436c5c301d3cbe5fa Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Apr 2005 06:33:20 +0000 Subject: r6460: Push the client credentials into NTLMSSP, allowing logins of the form user@REALM for the first time. Fix the build for smbencrypt.c Andrew Bartlett (This used to be commit 5a6a57cd93e22e612bfbb8a8f7bc29269a9a3ac6) --- source4/auth/ntlmssp/ntlmssp.c | 69 ++-------------------------------- source4/auth/ntlmssp/ntlmssp.h | 1 - source4/auth/ntlmssp/ntlmssp_client.c | 71 ++++++++++++++++++----------------- source4/auth/ntlmssp/ntlmssp_server.c | 53 +++++++++++++++++++++++++- source4/libcli/auth/smbencrypt.c | 2 +- 5 files changed, 93 insertions(+), 103 deletions(-) diff --git a/source4/auth/ntlmssp/ntlmssp.c b/source4/auth/ntlmssp/ntlmssp.c index d0bd98419e..9bb0ed99fa 100644 --- a/source4/auth/ntlmssp/ntlmssp.c +++ b/source4/auth/ntlmssp/ntlmssp.c @@ -35,7 +35,7 @@ static const struct ntlmssp_callbacks { enum ntlmssp_role role; enum ntlmssp_message_type ntlmssp_command; - NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state, + NTSTATUS (*fn)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, DATA_BLOB in, DATA_BLOB *out); } ntlmssp_callbacks[] = { @@ -89,68 +89,6 @@ void debug_ntlmssp_flags(uint32_t neg_flags) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n")); } -/** - * Set a username on an NTLMSSP context - ensures it is talloc()ed - * - */ - -NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user) -{ - if (!user) { - /* it should be at least "" */ - DEBUG(1, ("NTLMSSP failed to set username - cannot accept NULL username\n")); - return NT_STATUS_INVALID_PARAMETER; - } - ntlmssp_state->user = talloc_strdup(ntlmssp_state, user); - if (!ntlmssp_state->user) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Set a password on an NTLMSSP context - ensures it is talloc()ed - * - */ -NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password) -{ - if (!password) { - ntlmssp_state->password = NULL; - } else { - ntlmssp_state->password = talloc_strdup(ntlmssp_state, password); - if (!ntlmssp_state->password) { - return NT_STATUS_NO_MEMORY; - } - } - return NT_STATUS_OK; -} - -/** - * Set a domain on an NTLMSSP context - ensures it is talloc()ed - * - */ -NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain) -{ - ntlmssp_state->domain = talloc_strdup(ntlmssp_state, domain); - if (!ntlmssp_state->domain) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Set a workstation on an NTLMSSP context - ensures it is talloc()ed - * - */ -NTSTATUS ntlmssp_set_workstation(struct ntlmssp_state *ntlmssp_state, const char *workstation) -{ - ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation); - if (!ntlmssp_state->workstation) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - /** * Store a DATA_BLOB containing an NTLMSSP response, for use later. * This copies the data blob @@ -175,7 +113,8 @@ NTSTATUS ntlmssp_store_response(struct ntlmssp_state *ntlmssp_state, * or NT_STATUS_OK if the user is authenticated. */ -static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, +static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, + TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; @@ -236,7 +175,7 @@ static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, T for (i=0; i < ARRAY_SIZE(ntlmssp_callbacks); i++) { if (ntlmssp_callbacks[i].role == ntlmssp_state->role && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) { - status = ntlmssp_callbacks[i].fn(ntlmssp_state, out_mem_ctx, input, out); + status = ntlmssp_callbacks[i].fn(gensec_security, out_mem_ctx, input, out); break; } } diff --git a/source4/auth/ntlmssp/ntlmssp.h b/source4/auth/ntlmssp/ntlmssp.h index 0fe04a7c0f..7e7aeaad98 100644 --- a/source4/auth/ntlmssp/ntlmssp.h +++ b/source4/auth/ntlmssp/ntlmssp.h @@ -96,7 +96,6 @@ struct ntlmssp_state char *user; char *domain; const char *workstation; - char *password; char *server_domain; DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */ diff --git a/source4/auth/ntlmssp/ntlmssp_client.c b/source4/auth/ntlmssp/ntlmssp_client.c index bbde1d954b..dcd52af1f5 100644 --- a/source4/auth/ntlmssp/ntlmssp_client.c +++ b/source4/auth/ntlmssp/ntlmssp_client.c @@ -41,10 +41,13 @@ * @return Errors or NT_STATUS_OK. */ -NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, +NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, DATA_BLOB in, DATA_BLOB *out) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; + if (ntlmssp_state->unicode) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; } else { @@ -62,7 +65,7 @@ NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, NTLMSSP_NEGOTIATE, ntlmssp_state->neg_flags, ntlmssp_state->get_domain(), - ntlmssp_state->workstation); + cli_credentials_get_workstation(gensec_security->credentials)); ntlmssp_state->expected_state = NTLMSSP_CHALLENGE; @@ -78,10 +81,12 @@ NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, * @return Errors or NT_STATUS_OK. */ -NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, +NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; uint32_t chal_flags, ntlmssp_command, unkn1, unkn2; DATA_BLOB server_domain_blob; DATA_BLOB challenge_blob; @@ -97,6 +102,8 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB encrypted_session_key = data_blob(NULL, 0); NTSTATUS nt_status; + const char *user, *domain, *password; + if (!msrpc_parse(ntlmssp_state, &in, "CdBd", "NTLMSSP", @@ -156,7 +163,21 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } - if (!ntlmssp_state->password) { + /* Correctly handle username in the original form of user@REALM, which is valid */ + if (gensec_security->credentials->realm_obtained + > gensec_security->credentials->domain_obtained) { + user = talloc_asprintf(out_mem_ctx, "%s@%s", + cli_credentials_get_username(gensec_security->credentials), + cli_credentials_get_realm(gensec_security->credentials)); + domain = NULL; + } else { + user = cli_credentials_get_username(gensec_security->credentials); + domain = cli_credentials_get_domain(gensec_security->credentials); + } + + password = cli_credentials_get_password(gensec_security->credentials); + + if (!password) { static const uint8_t zeros[16]; /* do nothing - blobs are zero length */ @@ -177,9 +198,9 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ - if (!SMBNTLMv2encrypt(ntlmssp_state->user, - ntlmssp_state->domain, - ntlmssp_state->password, &challenge_blob, + if (!SMBNTLMv2encrypt(user, + domain, + password, &challenge_blob, &struct_blob, &lm_response, &nt_response, NULL, &session_key)) { @@ -197,7 +218,7 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, uint8_t session_nonce[16]; uint8_t session_nonce_hash[16]; uint8_t user_session_key[16]; - E_md4hash(ntlmssp_state->password, nt_hash); + E_md4hash(password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state, NULL, 24); generate_random_buffer(lm_response.data, 8); @@ -216,7 +237,7 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, dump_data(5, session_nonce_hash, 8); nt_response = data_blob_talloc(ntlmssp_state, NULL, 24); - SMBNTencrypt(ntlmssp_state->password, + SMBNTencrypt(password, session_nonce_hash, nt_response.data); @@ -233,9 +254,9 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, if (ntlmssp_state->use_nt_response) { nt_response = data_blob_talloc(ntlmssp_state, NULL, 24); - SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, + SMBNTencrypt(password,challenge_blob.data, nt_response.data); - E_md4hash(ntlmssp_state->password, nt_hash); + E_md4hash(password, nt_hash); session_key = data_blob_talloc(ntlmssp_state, NULL, 16); SMBsesskeygen_ntv1(nt_hash, session_key.data); dump_data_pw("NT session key:\n", session_key.data, session_key.length); @@ -244,7 +265,7 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { lm_response = data_blob_talloc(ntlmssp_state, NULL, 24); - if (!SMBencrypt(ntlmssp_state->password,challenge_blob.data, + if (!SMBencrypt(password,challenge_blob.data, lm_response.data)) { /* If the LM password was too long (and therefore the LM hash being of the first 14 chars only), don't send it */ @@ -253,7 +274,7 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* LM Key is incompatible with 'long' passwords */ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } else { - E_deshash(ntlmssp_state->password, lm_hash); + E_deshash(password, lm_hash); lm_session_key = data_blob_talloc(ntlmssp_state, NULL, 16); memcpy(lm_session_key.data, lm_hash, 8); memset(&lm_session_key.data[8], '\0', 8); @@ -310,9 +331,9 @@ NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, NTLMSSP_AUTH, lm_response.data, lm_response.length, nt_response.data, nt_response.length, - ntlmssp_state->domain, - ntlmssp_state->user, - ntlmssp_state->workstation, + domain, + user, + cli_credentials_get_workstation(gensec_security->credentials), encrypted_session_key.data, encrypted_session_key.length, ntlmssp_state->neg_flags)) { @@ -351,7 +372,6 @@ static NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state * (*ntlmssp_state)->role = NTLMSSP_CLIENT; - (*ntlmssp_state)->workstation = lp_netbios_name(); (*ntlmssp_state)->get_domain = lp_workgroup; (*ntlmssp_state)->unicode = lp_parm_bool(-1, "ntlmssp_client", "unicode", True); @@ -392,7 +412,6 @@ static NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state * NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) { struct gensec_ntlmssp_state *gensec_ntlmssp_state; - const char *password = NULL; NTSTATUS nt_status; nt_status = gensec_ntlmssp_start(gensec_security); @@ -422,22 +441,6 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } - nt_status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_domain(gensec_security->credentials)); - NT_STATUS_NOT_OK_RETURN(nt_status); - - nt_status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_username(gensec_security->credentials)); - NT_STATUS_NOT_OK_RETURN(nt_status); - - password = cli_credentials_get_password(gensec_security->credentials); - - nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); - NT_STATUS_NOT_OK_RETURN(nt_status); - - nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_workstation(gensec_security->credentials)); - gensec_security->private_data = gensec_ntlmssp_state; return NT_STATUS_OK; diff --git a/source4/auth/ntlmssp/ntlmssp_server.c b/source4/auth/ntlmssp/ntlmssp_server.c index d1e97aeb1f..852d32ed2b 100644 --- a/source4/auth/ntlmssp/ntlmssp_server.c +++ b/source4/auth/ntlmssp/ntlmssp_server.c @@ -28,6 +28,51 @@ #include "lib/crypto/crypto.h" #include "pstring.h" +/** + * Set a username on an NTLMSSP context - ensures it is talloc()ed + * + */ + +static NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user) +{ + if (!user) { + /* it should be at least "" */ + DEBUG(1, ("NTLMSSP failed to set username - cannot accept NULL username\n")); + return NT_STATUS_INVALID_PARAMETER; + } + ntlmssp_state->user = talloc_strdup(ntlmssp_state, user); + if (!ntlmssp_state->user) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Set a domain on an NTLMSSP context - ensures it is talloc()ed + * + */ +static NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain) +{ + ntlmssp_state->domain = talloc_strdup(ntlmssp_state, domain); + if (!ntlmssp_state->domain) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Set a workstation on an NTLMSSP context - ensures it is talloc()ed + * + */ +static NTSTATUS ntlmssp_set_workstation(struct ntlmssp_state *ntlmssp_state, const char *workstation) +{ + ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation); + if (!ntlmssp_state->workstation) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + /** * Default challenge generation code. * @@ -102,10 +147,12 @@ static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state, * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. */ -NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, +NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; DATA_BLOB struct_blob; fstring dnsname, dnsdomname; uint32_t neg_flags = 0; @@ -516,10 +563,12 @@ static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state, * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. */ -NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, +NTSTATUS ntlmssp_server_auth(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; DATA_BLOB user_session_key = data_blob(NULL, 0); DATA_BLOB lm_session_key = data_blob(NULL, 0); NTSTATUS nt_status; diff --git a/source4/libcli/auth/smbencrypt.c b/source4/libcli/auth/smbencrypt.c index f2b6eb00d7..3a4a724789 100644 --- a/source4/libcli/auth/smbencrypt.c +++ b/source4/libcli/auth/smbencrypt.c @@ -24,7 +24,7 @@ #include "includes.h" #include "system/time.h" -#include "auth/auth.h" +#include "auth/ntlmssp/ntlmssp.h" #include "lib/crypto/crypto.h" #include "pstring.h" -- cgit