From e8264d9678dff1cf56f7ac97d8a1a59b9532b6b8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Jun 2017 17:18:17 +0200 Subject: [PATCH] auth/common: add support for auth4_ctx->check_ntlm_password_send/recv() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- auth/common_auth.h | 10 ++++++ auth/ntlmssp/ntlmssp_server.c | 65 +++++++++++++++++++++++++++++++++++ source3/auth/auth_generic.c | 49 ++++++++++++++++++++++---- 3 files changed, 117 insertions(+), 7 deletions(-) diff --git a/auth/common_auth.h b/auth/common_auth.h index 507971794f3..3de227ee354 100644 --- a/auth/common_auth.h +++ b/auth/common_auth.h @@ -131,6 +131,16 @@ struct auth4_context { uint8_t *pauthoritative, void **server_returned_info, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key); + struct tevent_req *(*check_ntlm_password_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct auth4_context *auth_ctx, + const struct auth_usersupplied_info *user_info); + NTSTATUS (*check_ntlm_password_recv)(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uint8_t *pauthoritative, + void **server_returned_info, + DATA_BLOB *nt_session_key, + DATA_BLOB *lm_session_key); NTSTATUS (*get_ntlm_challenge)(struct auth4_context *auth_ctx, uint8_t chal[8]); diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c index 4990f77f66f..417352bf259 100644 --- a/auth/ntlmssp/ntlmssp_server.c +++ b/auth/ntlmssp/ntlmssp_server.c @@ -296,6 +296,9 @@ NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security } struct ntlmssp_server_auth_state { + struct gensec_security *gensec_security; + struct gensec_ntlmssp_context *gensec_ntlmssp; + DATA_BLOB in; struct auth_usersupplied_info *user_info; DATA_BLOB user_session_key; DATA_BLOB lm_session_key; @@ -310,6 +313,7 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security, struct gensec_ntlmssp_context *gensec_ntlmssp, struct ntlmssp_server_auth_state *state, const DATA_BLOB request); +static void ntlmssp_server_auth_done(struct tevent_req *subreq); static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security, struct gensec_ntlmssp_context *gensec_ntlmssp, struct ntlmssp_server_auth_state *state, @@ -334,6 +338,9 @@ struct tevent_req *ntlmssp_server_auth_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + state->gensec_security = gensec_security; + state->gensec_ntlmssp = gensec_ntlmssp; + state->in = in; status = ntlmssp_server_preauth(gensec_security, gensec_ntlmssp, @@ -342,6 +349,21 @@ struct tevent_req *ntlmssp_server_auth_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + if (auth_context->check_ntlm_password_send != NULL) { + struct tevent_req *subreq = NULL; + + subreq = auth_context->check_ntlm_password_send(state, ev, + auth_context, + state->user_info); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, + ntlmssp_server_auth_done, + req); + return req; + } + if (auth_context->check_ntlm_password == NULL) { tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return tevent_req_post(req, ev); @@ -794,6 +816,49 @@ static NTSTATUS ntlmssp_server_preauth(struct gensec_security *gensec_security, return NT_STATUS_OK; } +static void ntlmssp_server_auth_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct ntlmssp_server_auth_state *state = + tevent_req_data(req, + struct ntlmssp_server_auth_state); + struct gensec_security *gensec_security = state->gensec_security; + struct gensec_ntlmssp_context *gensec_ntlmssp = state->gensec_ntlmssp; + struct auth4_context *auth_context = gensec_security->auth_context; + uint8_t authoritative = 0; + NTSTATUS status; + + status = auth_context->check_ntlm_password_recv(subreq, + gensec_ntlmssp, + &authoritative, + &gensec_ntlmssp->server_returned_info, + &state->user_session_key, + &state->lm_session_key); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + DBG_INFO("Checking NTLMSSP password for %s\\%s failed: %s\n", + state->user_info->client.domain_name, + state->user_info->client.account_name, + nt_errstr(status)); + } + if (tevent_req_nterror(req, status)) { + return; + } + talloc_steal(state, state->user_session_key.data); + talloc_steal(state, state->lm_session_key.data); + + status = ntlmssp_server_postauth(state->gensec_security, + state->gensec_ntlmssp, + state, state->in); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} + /** * Next state function for the Authenticate packet * (after authentication - figures out the session keys etc) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 6dedeedd302..167d4e00367 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -22,6 +22,8 @@ */ #include "includes.h" +#include +#include "../lib/util/tevent_ntstatus.h" #include "auth.h" #include "../lib/tsocket/tsocket.h" #include "auth/gensec/gensec.h" @@ -413,14 +415,47 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context, void *server_info; uint8_t authoritative = 0; - nt_status = auth_context->check_ntlm_password(auth_context, - talloc_tos(), - user_info, - &authoritative, - &server_info, NULL, NULL); + if (auth_context->check_ntlm_password_send != NULL) { + struct tevent_context *ev = NULL; + struct tevent_req *subreq = NULL; + bool ok; - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; + ev = samba_tevent_context_init(talloc_tos()); + if (ev == NULL) { + return NT_STATUS_NO_MEMORY; + } + + subreq = auth_context->check_ntlm_password_send(ev, ev, + auth_context, + user_info); + if (subreq == NULL) { + TALLOC_FREE(ev); + return NT_STATUS_NO_MEMORY; + } + ok = tevent_req_poll_ntstatus(subreq, ev, &nt_status); + if (!ok) { + TALLOC_FREE(ev); + return nt_status; + } + nt_status = auth_context->check_ntlm_password_recv(subreq, + talloc_tos(), + &authoritative, + &server_info, + NULL, NULL); + TALLOC_FREE(ev); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + } else { + nt_status = auth_context->check_ntlm_password(auth_context, + talloc_tos(), + user_info, + &authoritative, + &server_info, + NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } } nt_status = auth_context->generate_session_info(auth_context, -- 2.34.1