mirror of
https://github.com/samba-team/samba.git
synced 2025-01-12 09:18:10 +03:00
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 commit is contained in:
parent
2f22841c67
commit
5a6a57cd93
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user