mirror of
https://github.com/samba-team/samba.git
synced 2025-08-26 01:49:31 +03:00
auth/ntlmssp: provide a "ntlmssp_resume_ccache" backend
These can be used to implement the winbindd side of
the WINBINDD_CCACHE_NTLMAUTH call.
It can properly get the initial NEGOTIATE messages
injected if available.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11804
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
(cherry picked from commit b3d4523ff7
)
This commit is contained in:
@ -47,6 +47,10 @@ static const struct ntlmssp_callbacks {
|
||||
.role = NTLMSSP_CLIENT,
|
||||
.command = NTLMSSP_INITIAL,
|
||||
.sync_fn = ntlmssp_client_initial,
|
||||
},{
|
||||
.role = NTLMSSP_CLIENT,
|
||||
.command = NTLMSSP_NEGOTIATE,
|
||||
.sync_fn = gensec_ntlmssp_resume_ccache,
|
||||
},{
|
||||
.role = NTLMSSP_SERVER,
|
||||
.command = NTLMSSP_NEGOTIATE,
|
||||
@ -82,6 +86,15 @@ static NTSTATUS gensec_ntlmssp_update_find(struct gensec_security *gensec_securi
|
||||
if (!input.length) {
|
||||
switch (gensec_ntlmssp->ntlmssp_state->role) {
|
||||
case NTLMSSP_CLIENT:
|
||||
if (gensec_ntlmssp->ntlmssp_state->resume_ccache) {
|
||||
/*
|
||||
* make sure gensec_ntlmssp_resume_ccache()
|
||||
* will be called
|
||||
*/
|
||||
ntlmssp_command = NTLMSSP_NEGOTIATE;
|
||||
break;
|
||||
}
|
||||
|
||||
ntlmssp_command = NTLMSSP_INITIAL;
|
||||
break;
|
||||
case NTLMSSP_SERVER:
|
||||
@ -194,6 +207,15 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
|
||||
.priority = GENSEC_NTLMSSP
|
||||
};
|
||||
|
||||
static const struct gensec_security_ops gensec_ntlmssp_resume_ccache_ops = {
|
||||
.name = "ntlmssp_resume_ccache",
|
||||
.client_start = gensec_ntlmssp_resume_ccache_start,
|
||||
.update = gensec_ntlmssp_update,
|
||||
.session_key = gensec_ntlmssp_session_key,
|
||||
.have_feature = gensec_ntlmssp_have_feature,
|
||||
.enabled = true,
|
||||
.priority = GENSEC_NTLMSSP
|
||||
};
|
||||
|
||||
_PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
|
||||
{
|
||||
@ -206,6 +228,13 @@ _PUBLIC_ NTSTATUS gensec_ntlmssp_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gensec_register(&gensec_ntlmssp_resume_ccache_ops);
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,("Failed to register '%s' gensec backend!\n",
|
||||
gensec_ntlmssp_resume_ccache_ops.name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ struct ntlmssp_state
|
||||
bool unicode;
|
||||
bool use_ntlmv2;
|
||||
bool use_ccache;
|
||||
bool resume_ccache;
|
||||
bool use_nt_response; /* Set to 'False' to debug what happens when the NT response is omited */
|
||||
bool allow_lm_key; /* The LM_KEY code is not very secure... */
|
||||
|
||||
|
@ -114,6 +114,98 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
|
||||
return NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *out_mem_ctx,
|
||||
DATA_BLOB in, DATA_BLOB *out)
|
||||
{
|
||||
struct gensec_ntlmssp_context *gensec_ntlmssp =
|
||||
talloc_get_type_abort(gensec_security->private_data,
|
||||
struct gensec_ntlmssp_context);
|
||||
struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
|
||||
uint32_t neg_flags = 0;
|
||||
uint32_t ntlmssp_command;
|
||||
NTSTATUS status;
|
||||
bool ok;
|
||||
|
||||
*out = data_blob_null;
|
||||
|
||||
if (in.length == 0) {
|
||||
/*
|
||||
* This is compat code for older callers
|
||||
* which were missing the "initial_blob"
|
||||
*/
|
||||
ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
|
||||
return NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/* parse the NTLMSSP packet */
|
||||
|
||||
if (in.length > UINT16_MAX) {
|
||||
DEBUG(1, ("%s: reject large request of length %u\n",
|
||||
__func__, (unsigned int)in.length));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
|
||||
"NTLMSSP",
|
||||
&ntlmssp_command,
|
||||
&neg_flags);
|
||||
if (!ok) {
|
||||
DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
|
||||
__func__, (unsigned int)in.length));
|
||||
dump_data(2, in.data, in.length);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
|
||||
DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
|
||||
__func__, (unsigned int)in.length));
|
||||
dump_data(2, in.data, in.length);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ntlmssp_state->neg_flags = neg_flags;
|
||||
DEBUG(3, ("Imported Negotiate flags:\n"));
|
||||
debug_ntlmssp_flags(neg_flags);
|
||||
|
||||
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
|
||||
ntlmssp_state->unicode = true;
|
||||
} else {
|
||||
ntlmssp_state->unicode = false;
|
||||
}
|
||||
|
||||
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
|
||||
gensec_security->want_features |= GENSEC_FEATURE_SIGN;
|
||||
|
||||
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||
}
|
||||
|
||||
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
|
||||
gensec_security->want_features |= GENSEC_FEATURE_SEAL;
|
||||
|
||||
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
|
||||
}
|
||||
|
||||
if (DEBUGLEVEL >= 10) {
|
||||
struct NEGOTIATE_MESSAGE *negotiate = talloc(
|
||||
ntlmssp_state, struct NEGOTIATE_MESSAGE);
|
||||
if (negotiate != NULL) {
|
||||
status = ntlmssp_pull_NEGOTIATE_MESSAGE(
|
||||
&in, negotiate, negotiate);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
|
||||
negotiate);
|
||||
}
|
||||
TALLOC_FREE(negotiate);
|
||||
}
|
||||
}
|
||||
|
||||
ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
|
||||
|
||||
return NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Next state function for the Challenge Packet. Generate an auth packet.
|
||||
*
|
||||
@ -476,3 +568,22 @@ NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
|
||||
{
|
||||
struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = gensec_ntlmssp_client_start(gensec_security);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
|
||||
struct gensec_ntlmssp_context);
|
||||
gensec_ntlmssp->ntlmssp_state->use_ccache = false;
|
||||
gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
|
||||
gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -88,6 +88,10 @@ NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *out_mem_ctx,
|
||||
DATA_BLOB in, DATA_BLOB *out) ;
|
||||
|
||||
NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *out_mem_ctx,
|
||||
DATA_BLOB in, DATA_BLOB *out);
|
||||
|
||||
/**
|
||||
* Next state function for the Challenge Packet. Generate an auth packet.
|
||||
*
|
||||
@ -101,6 +105,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
|
||||
TALLOC_CTX *out_mem_ctx,
|
||||
const DATA_BLOB in, DATA_BLOB *out) ;
|
||||
NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security);
|
||||
NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security);
|
||||
|
||||
/* The following definitions come from auth/ntlmssp/gensec_ntlmssp_server.c */
|
||||
|
||||
|
Reference in New Issue
Block a user