auth/common: add support for auth4_ctx->check_ntlm_password_send/recv()
authorStefan Metzmacher <metze@samba.org>
Fri, 16 Jun 2017 15:18:17 +0000 (17:18 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Mon, 7 Aug 2017 13:20:03 +0000 (15:20 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
auth/common_auth.h
auth/ntlmssp/ntlmssp_server.c
source3/auth/auth_generic.c

index 5079717..3de227e 100644 (file)
@@ -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]);
 
index 4990f77..417352b 100644 (file)
@@ -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)
index 6dedeed..167d4e0 100644 (file)
@@ -22,6 +22,8 @@
 */
 
 #include "includes.h"
+#include <tevent.h>
+#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,