auth4: use "anonymous sam winbind sam_ignoredomain" with ROLE_DOMAIN_MEMBER
[sfrench/samba-autobuild/.git] / source4 / auth / ntlm / auth.c
index ccfd20ad05f7cd259c5144d73ca88191f391528a..078b08b112535f46cc264ea46a6579f48681af8d 100644 (file)
@@ -32,6 +32,7 @@
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
 #include "auth/kerberos/kerberos_util.h"
+#include "libds/common/roles.h"
 
 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
                                                   TALLOC_CTX *mem_ctx,
@@ -154,7 +155,8 @@ static NTSTATUS auth_generate_session_info_principal(struct auth4_context *auth_
 _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
                             TALLOC_CTX *mem_ctx,
                             const struct auth_usersupplied_info *user_info, 
-                            struct auth_user_info_dc **user_info_dc)
+                            struct auth_user_info_dc **user_info_dc,
+                            uint8_t *pauthoritative)
 {
        struct tevent_req *subreq;
        struct tevent_context *ev;
@@ -177,42 +179,48 @@ _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
                return NT_STATUS_INTERNAL_ERROR;
        }
 
-       status = auth_check_password_recv(subreq, mem_ctx, user_info_dc);
+       status = auth_check_password_recv(subreq, mem_ctx,
+                                         user_info_dc, pauthoritative);
        TALLOC_FREE(subreq);
 
        return status;
 }
 
-_PUBLIC_ NTSTATUS auth_check_password_wrapper(struct auth4_context *auth_ctx,
-                                             TALLOC_CTX *mem_ctx,
-                                             const struct auth_usersupplied_info *user_info, 
-                                             void **server_returned_info,
-                                             DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
+static NTSTATUS auth_check_password_wrapper(struct auth4_context *auth_ctx,
+                                           TALLOC_CTX *mem_ctx,
+                                           const struct auth_usersupplied_info *user_info,
+                                           uint8_t *pauthoritative,
+                                           void **server_returned_info,
+                                           DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
 {
        struct auth_user_info_dc *user_info_dc;
-       NTSTATUS status = auth_check_password(auth_ctx, mem_ctx, user_info, &user_info_dc);
+       NTSTATUS status;
 
-       if (NT_STATUS_IS_OK(status)) {
-               *server_returned_info = user_info_dc;
+       status = auth_check_password(auth_ctx, mem_ctx, user_info,
+                                    &user_info_dc, pauthoritative);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-               if (user_session_key) {
-                       DEBUG(10, ("Got NT session key of length %u\n",
-                                  (unsigned)user_info_dc->user_session_key.length));
-                       *user_session_key = user_info_dc->user_session_key;
-                       talloc_steal(mem_ctx, user_session_key->data);
-                       user_info_dc->user_session_key = data_blob_null;
-               }
+       *server_returned_info = user_info_dc;
 
-               if (lm_session_key) {
-                       DEBUG(10, ("Got LM session key of length %u\n",
-                                  (unsigned)user_info_dc->lm_session_key.length));
-                       *lm_session_key = user_info_dc->lm_session_key;
-                       talloc_steal(mem_ctx, lm_session_key->data);
-                       user_info_dc->lm_session_key = data_blob_null;
-               }
+       if (user_session_key) {
+               DEBUG(10, ("Got NT session key of length %u\n",
+                          (unsigned)user_info_dc->user_session_key.length));
+               *user_session_key = user_info_dc->user_session_key;
+               talloc_steal(mem_ctx, user_session_key->data);
+               user_info_dc->user_session_key = data_blob_null;
        }
 
-       return status;
+       if (lm_session_key) {
+               DEBUG(10, ("Got LM session key of length %u\n",
+                          (unsigned)user_info_dc->lm_session_key.length));
+               *lm_session_key = user_info_dc->lm_session_key;
+               talloc_steal(mem_ctx, lm_session_key->data);
+               user_info_dc->lm_session_key = data_blob_null;
+       }
+
+       return NT_STATUS_OK;
 }
 
 struct auth_check_password_state {
@@ -220,6 +228,7 @@ struct auth_check_password_state {
        const struct auth_usersupplied_info *user_info;
        struct auth_user_info_dc *user_info_dc;
        struct auth_method_context *method;
+       uint8_t authoritative;
 };
 
 static void auth_check_password_async_trigger(struct tevent_context *ev,
@@ -261,7 +270,6 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
        /* if all the modules say 'not for me' this is reasonable */
        NTSTATUS nt_status;
        uint8_t chal[8];
-       struct auth_usersupplied_info *user_info_tmp;
        struct tevent_immediate *im;
 
        DEBUG(3,("auth_check_password_send: "
@@ -275,12 +283,23 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
+       /*
+        * We are authoritative by default.
+        */
+       state->authoritative    = 1;
        state->auth_ctx         = auth_ctx;
        state->user_info        = user_info;
 
        if (!user_info->mapped_state) {
-               nt_status = map_user_info(auth_ctx->sam_ctx, req, lpcfg_workgroup(auth_ctx->lp_ctx),
-                                         user_info, &user_info_tmp);
+               int server_role = lpcfg_server_role(auth_ctx->lp_ctx);
+               struct auth_usersupplied_info *user_info_tmp;
+
+               nt_status = map_user_info(
+                       auth_ctx->sam_ctx, req,
+                       server_role == ROLE_ACTIVE_DIRECTORY_DC,
+                       lpcfg_workgroup(auth_ctx->lp_ctx),
+                       user_info, &user_info_tmp);
+
                if (tevent_req_nterror(req, nt_status)) {
                        return tevent_req_post(req, ev);
                }
@@ -350,7 +369,7 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
                status = method->ops->want_check(method, req, state->user_info);
                if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
                        DEBUG(11,("auth_check_password_send: "
-                                 "%s had nothing to say\n",
+                                 "%s doesn't want to check\n",
                                  method->ops->name));
                        continue;
                }
@@ -363,15 +382,19 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
                                                     state,
                                                     state->user_info,
                                                     &state->user_info_dc);
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
-                       /* the backend has handled the request */
-                       break;
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+                       DEBUG(11,("auth_check_password_send: "
+                                 "%s passes to the next method\n",
+                                 method->ops->name));
+                       continue;
                }
+
+               /* the backend has handled the request */
+               break;
        }
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
-               /* don't expose the NT_STATUS_NOT_IMPLEMENTED
-                  internals */
+               state->authoritative = 0;
                status = NT_STATUS_NO_SUCH_USER;
        }
 
@@ -404,20 +427,32 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
 
 _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
                                  TALLOC_CTX *mem_ctx,
-                                 struct auth_user_info_dc **user_info_dc)
+                                 struct auth_user_info_dc **user_info_dc,
+                                 uint8_t *pauthoritative)
 {
        struct auth_check_password_state *state =
                tevent_req_data(req, struct auth_check_password_state);
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
+
+       *pauthoritative = state->authoritative;
 
        if (tevent_req_is_nterror(req, &status)) {
+               /*
+                * Please try not to change this string, it is probably in use
+                * in audit logging tools
+                */
                DEBUG(2,("auth_check_password_recv: "
                         "%s authentication for user [%s\\%s] "
-                        "FAILED with error %s\n",
+                        "FAILED with error %s, authoritative=%u\n",
                         (state->method ? state->method->ops->name : "NO_METHOD"),
                         state->user_info->mapped.domain_name,
                         state->user_info->mapped.account_name,
-                        nt_errstr(status)));
+                        nt_errstr(status), state->authoritative));
+
+               log_authentication_event(state->auth_ctx->msg_ctx,
+                                        state->auth_ctx->lp_ctx,
+                                        state->user_info, status,
+                                        NULL, NULL, NULL, NULL);
                tevent_req_received(req);
                return status;
        }
@@ -428,6 +463,14 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
                 state->user_info_dc->info->domain_name,
                 state->user_info_dc->info->account_name));
 
+       log_authentication_event(state->auth_ctx->msg_ctx,
+                                state->auth_ctx->lp_ctx,
+                                state->user_info, status,
+                                state->user_info_dc->info->domain_name,
+                                state->user_info_dc->info->account_name,
+                                NULL,
+                                &state->user_info_dc->sids[0]);
+
        *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
 
        tevent_req_received(req);
@@ -520,7 +563,7 @@ static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
  Make a auth_info struct for the auth subsystem
  - Allow the caller to specify the methods to use, including optionally the SAM to use
 ***************************************************************************/
-_PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods, 
+_PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods, 
                                              struct tevent_context *ev,
                                              struct imessaging_context *msg,
                                              struct loadparm_context *lp_ctx,
@@ -565,7 +608,7 @@ _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **
                }
                method->auth_ctx        = ctx;
                method->depth           = i;
-               DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
+               DLIST_ADD_END(ctx->methods, method);
        }
 
        ctx->check_ntlm_password = auth_check_password_wrapper;
@@ -582,21 +625,48 @@ _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **
 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
 {
        char **auth_methods = NULL;
+       const char **const_auth_methods = NULL;
+
+       /*
+        * As 'auth methods' is deprecated it will be removed
+        * in future releases again, but for now give
+        * admins the flexibility to configure, the behavior
+        * from Samba 4.6: "auth methods = anonymous sam_ignoredomain",
+        * for a while.
+        */
+       const_auth_methods = lpcfg_auth_methods(lp_ctx);
+       if (const_auth_methods != NULL) {
+               DBG_NOTICE("using deprecated 'auth methods' values.\n");
+               return const_auth_methods;
+       }
 
        switch (lpcfg_server_role(lp_ctx)) {
        case ROLE_STANDALONE:
                auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
                break;
        case ROLE_DOMAIN_MEMBER:
-               auth_methods = str_list_make(mem_ctx, "anonymous sam winbind", NULL);
+               auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
                break;
        case ROLE_DOMAIN_BDC:
        case ROLE_DOMAIN_PDC:
        case ROLE_ACTIVE_DIRECTORY_DC:
-               auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind", NULL);
+               /*
+                * TODO: we should replace "winbind_rodc sam_failtrusts" with "winbind"
+                * if everything (gensec/auth4) is fully async without nested
+                * event loops!
+                *
+                * But for now we'll fail authentications for trusted
+                * domain consistently with NT_STATUS_NO_TRUST_LSA_SECRET,
+                * instead of silently mapping to local users.
+                */
+               auth_methods = str_list_make(mem_ctx,
+                                            "anonymous sam "
+                                            "winbind_rodc sam_failtrusts "
+                                            "sam_ignoredomain",
+                                            NULL);
                break;
        }
-       return (const char **) auth_methods;
+       return discard_const_p(const char *, auth_methods);
 }
 
 /***************************************************************************
@@ -625,6 +695,15 @@ _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
        return status;
 }
 
+_PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
+                                                  struct tevent_context *ev,
+                                                  struct imessaging_context *msg,
+                                                  struct loadparm_context *lp_ctx,
+                                                  struct auth4_context **auth_ctx)
+{
+       return auth_context_create(mem_ctx, ev, msg, lp_ctx, auth_ctx);
+}
+
 /* the list of currently registered AUTH backends */
 static struct auth_backend {
        const struct auth_operations *ops;