LCOV - code coverage report
Current view: top level - source4/auth/ntlm - auth.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 283 314 90.1 %
Date: 2024-04-21 15:09:00 Functions: 19 20 95.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Password and authentication handling
       4             :    Copyright (C) Andrew Bartlett         2001-2002
       5             :    Copyright (C) Stefan Metzmacher       2005
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include <tevent.h>
      23             : #include "../lib/util/tevent_ntstatus.h"
      24             : #include "../lib/util/dlinklist.h"
      25             : #include "auth/auth.h"
      26             : #include "auth/ntlm/auth_proto.h"
      27             : #include "param/param.h"
      28             : #include "dsdb/samdb/samdb.h"
      29             : #include "libcli/wbclient/wbclient.h"
      30             : #include "lib/util/samba_modules.h"
      31             : #include "auth/credentials/credentials.h"
      32             : #include "system/kerberos.h"
      33             : #include "auth/kerberos/kerberos.h"
      34             : #include "auth/kerberos/kerberos_util.h"
      35             : #include "libds/common/roles.h"
      36             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_AUTH
      39             : 
      40             : static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
      41             :                                                    TALLOC_CTX *mem_ctx,
      42             :                                                   void *server_returned_info,
      43             :                                                    const char *original_user_name,
      44             :                                                    uint32_t session_info_flags,
      45             :                                                    struct auth_session_info **session_info);
      46             : 
      47             : /***************************************************************************
      48             :  Set a fixed challenge
      49             : ***************************************************************************/
      50       14136 : _PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
      51             : {
      52       14136 :         auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
      53       14136 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
      54             : 
      55       14136 :         auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
      56       14136 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
      57             : 
      58       14136 :         return NT_STATUS_OK;
      59             : }
      60             : 
      61             : /****************************************************************************
      62             :  Try to get a challenge out of the various authentication modules.
      63             :  Returns a const char of length 8 bytes.
      64             : ****************************************************************************/
      65       44714 : _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t chal[8])
      66             : {
      67             : 
      68       44714 :         if (auth_ctx->challenge.data.length == 8) {
      69       29536 :                 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
      70             :                           auth_ctx->challenge.set_by));
      71       29536 :                 memcpy(chal, auth_ctx->challenge.data.data, 8);
      72       29536 :                 return NT_STATUS_OK;
      73             :         }
      74             : 
      75       15178 :         if (!auth_ctx->challenge.set_by) {
      76       15178 :                 generate_random_buffer(chal, 8);
      77             : 
      78       15178 :                 auth_ctx->challenge.data             = data_blob_talloc(auth_ctx, chal, 8);
      79       15178 :                 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
      80       15178 :                 auth_ctx->challenge.set_by           = "random";
      81             :         }
      82             : 
      83       15178 :         DEBUG(10,("auth_get_challenge: challenge set by %s\n",
      84             :                  auth_ctx->challenge.set_by));
      85             : 
      86       15178 :         return NT_STATUS_OK;
      87             : }
      88             : 
      89             : /**
      90             :  * Check a user's Plaintext, LM or NTLM password.
      91             :  * (sync version)
      92             :  *
      93             :  * Check a user's password, as given in the user_info struct and return various
      94             :  * interesting details in the user_info_dc struct.
      95             :  *
      96             :  * The return value takes precedence over the contents of the user_info_dc
      97             :  * struct.  When the return is other than NT_STATUS_OK the contents
      98             :  * of that structure is undefined.
      99             :  *
     100             :  * @param auth_ctx Supplies the challenges and some other data.
     101             :  *                  Must be created with auth_context_create(), and the challenges should be
     102             :  *                  filled in, either at creation or by calling the challenge generation
     103             :  *                  function auth_get_challenge().
     104             :  *
     105             :  * @param user_info Contains the user supplied components, including the passwords.
     106             :  *
     107             :  * @param mem_ctx The parent memory context for the user_info_dc structure
     108             :  *
     109             :  * @param user_info_dc If successful, contains information about the authentication,
     110             :  *                    including a SAM_ACCOUNT struct describing the user.
     111             :  *
     112             :  * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
     113             :  *
     114             :  **/
     115             : 
     116           1 : _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
     117             :                              TALLOC_CTX *mem_ctx,
     118             :                              const struct auth_usersupplied_info *user_info,
     119             :                              struct auth_user_info_dc **user_info_dc,
     120             :                              uint8_t *pauthoritative)
     121             : {
     122           0 :         struct tevent_req *subreq;
     123           0 :         struct tevent_context *ev;
     124           0 :         bool ok;
     125           0 :         NTSTATUS status;
     126             : 
     127             :         /*TODO: create a new event context here! */
     128           1 :         ev = auth_ctx->event_ctx;
     129             : 
     130             :         /*
     131             :          * We are authoritative by default
     132             :          */
     133           1 :         *pauthoritative = 1;
     134             : 
     135           1 :         subreq = auth_check_password_send(mem_ctx,
     136             :                                           ev,
     137             :                                           auth_ctx,
     138             :                                           user_info);
     139           1 :         if (subreq == NULL) {
     140           0 :                 return NT_STATUS_NO_MEMORY;
     141             :         }
     142             : 
     143           1 :         ok = tevent_req_poll(subreq, ev);
     144           1 :         if (!ok) {
     145           0 :                 return NT_STATUS_INTERNAL_ERROR;
     146             :         }
     147             : 
     148           1 :         status = auth_check_password_recv(subreq, mem_ctx,
     149             :                                           user_info_dc, pauthoritative);
     150           1 :         TALLOC_FREE(subreq);
     151             : 
     152           1 :         return status;
     153             : }
     154             : 
     155             : struct auth_check_password_state {
     156             :         struct tevent_context *ev;
     157             :         struct auth4_context *auth_ctx;
     158             :         const struct auth_usersupplied_info *user_info;
     159             :         struct auth_user_info_dc *user_info_dc;
     160             :         struct auth_method_context *method;
     161             :         const struct authn_audit_info *client_audit_info;
     162             :         const struct authn_audit_info *server_audit_info;
     163             :         uint8_t authoritative;
     164             : };
     165             : 
     166             : static void auth_check_password_next(struct tevent_req *req);
     167             : 
     168             : /**
     169             :  * Check a user's Plaintext, LM or NTLM password.
     170             :  * async send hook
     171             :  *
     172             :  * Check a user's password, as given in the user_info struct and return various
     173             :  * interesting details in the user_info_dc struct.
     174             :  *
     175             :  * The return value takes precedence over the contents of the user_info_dc
     176             :  * struct.  When the return is other than NT_STATUS_OK the contents
     177             :  * of that structure is undefined.
     178             :  *
     179             :  * @param mem_ctx The memory context the request should operate on
     180             :  *
     181             :  * @param ev The tevent context the request should operate on
     182             :  *
     183             :  * @param auth_ctx Supplies the challenges and some other data.  Must
     184             :  *                 be created with make_auth_context(), and the
     185             :  *                 challenges should be filled in, either at creation
     186             :  *                 or by calling the challenge generation function
     187             :  *                 auth_get_challenge().
     188             :  *
     189             :  * @param user_info Contains the user supplied components, including the passwords.
     190             :  *
     191             :  * @return The request handle or NULL on no memory error.
     192             :  *
     193             :  **/
     194             : 
     195       29195 : _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
     196             :                                 struct tevent_context *ev,
     197             :                                 struct auth4_context *auth_ctx,
     198             :                                 const struct auth_usersupplied_info *user_info)
     199             : {
     200        1420 :         struct tevent_req *req;
     201        1420 :         struct auth_check_password_state *state;
     202             :         /* if all the modules say 'not for me' this is reasonable */
     203        1420 :         NTSTATUS nt_status;
     204        1420 :         uint8_t chal[8];
     205             : 
     206       29195 :         DEBUG(3,("auth_check_password_send: "
     207             :                  "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
     208             :                  user_info->client.domain_name, user_info->client.account_name,
     209             :                  user_info->workstation_name));
     210             : 
     211       29195 :         req = tevent_req_create(mem_ctx, &state,
     212             :                                 struct auth_check_password_state);
     213       29195 :         if (req == NULL) {
     214           0 :                 return NULL;
     215             :         }
     216             : 
     217             :         /*
     218             :          * We are authoritative by default.
     219             :          */
     220       29195 :         state->ev            = ev;
     221       29195 :         state->auth_ctx              = auth_ctx;
     222       29195 :         state->user_info     = user_info;
     223       29195 :         state->authoritative = 1;
     224             : 
     225       29195 :         if (user_info->mapped.account_name == NULL) {
     226        1420 :                 struct auth_usersupplied_info *user_info_tmp;
     227             : 
     228             :                 /*
     229             :                  * We don't really do any mapping here.
     230             :                  *
     231             :                  * It's up to the backends to do mappings
     232             :                  * for their authentication.
     233             :                  */
     234       29181 :                 user_info_tmp = talloc_zero(state, struct auth_usersupplied_info);
     235       29181 :                 if (tevent_req_nomem(user_info_tmp, req)) {
     236           0 :                         return tevent_req_post(req, ev);
     237             :                 }
     238             : 
     239             :                 /*
     240             :                  * The lifetime of user_info is longer than
     241             :                  * user_info_tmp, so we don't need to copy the
     242             :                  * strings.
     243             :                  */
     244       29181 :                 *user_info_tmp = *user_info;
     245       29181 :                 user_info_tmp->mapped.domain_name = user_info->client.domain_name;
     246       29181 :                 user_info_tmp->mapped.account_name = user_info->client.account_name;
     247             : 
     248       29181 :                 user_info = user_info_tmp;
     249       29181 :                 state->user_info = user_info_tmp;
     250             :         }
     251             : 
     252       29195 :         DEBUGADD(3,("auth_check_password_send: "
     253             :                     "user is: [%s]\\[%s]@[%s]\n",
     254             :                     user_info->mapped.domain_name,
     255             :                     user_info->mapped.account_name,
     256             :                     user_info->workstation_name));
     257             : 
     258       29195 :         nt_status = auth_get_challenge(auth_ctx, chal);
     259       29195 :         if (tevent_req_nterror(req, nt_status)) {
     260           0 :                 DEBUG(0,("auth_check_password_send: "
     261             :                          "Invalid challenge (length %u) stored for "
     262             :                          "this auth context set_by %s - cannot continue: %s\n",
     263             :                         (unsigned)auth_ctx->challenge.data.length,
     264             :                         auth_ctx->challenge.set_by,
     265             :                         nt_errstr(nt_status)));
     266           0 :                 return tevent_req_post(req, ev);
     267             :         }
     268             : 
     269       29195 :         if (auth_ctx->challenge.set_by) {
     270       29195 :                 DEBUG(10,("auth_check_password_send: "
     271             :                           "auth_context challenge created by %s\n",
     272             :                           auth_ctx->challenge.set_by));
     273             :         }
     274             : 
     275       29195 :         DEBUG(10, ("auth_check_password_send: challenge is: \n"));
     276       29195 :         dump_data(5, auth_ctx->challenge.data.data,
     277       29195 :                   auth_ctx->challenge.data.length);
     278             : 
     279       29195 :         state->method = state->auth_ctx->methods;
     280       29195 :         auth_check_password_next(req);
     281       29195 :         if (!tevent_req_is_in_progress(req)) {
     282          14 :                 return tevent_req_post(req, ev);
     283             :         }
     284             : 
     285       27761 :         return req;
     286             : }
     287             : 
     288             : static void auth_check_password_done(struct tevent_req *subreq);
     289             : 
     290       45692 : static void auth_check_password_next(struct tevent_req *req)
     291             : {
     292        1568 :         struct auth_check_password_state *state =
     293       45834 :                 tevent_req_data(req, struct auth_check_password_state);
     294       45834 :         struct tevent_req *subreq = NULL;
     295        1568 :         NTSTATUS status;
     296             : 
     297       45834 :         if (state->method == NULL) {
     298          52 :                 state->authoritative = 0;
     299          52 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     300          52 :                 return;
     301             :         }
     302             : 
     303             :         /* check if the module wants to check the password */
     304       45782 :         status = state->method->ops->want_check(state->method, state,
     305             :                                                 state->user_info);
     306       45782 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     307       15283 :                 DEBUG(11,("auth_check_password_send: "
     308             :                           "%s doesn't want to check\n",
     309             :                           state->method->ops->name));
     310       15283 :                 state->method = state->method->next;
     311       15283 :                 auth_check_password_next(req);
     312       15141 :                 return;
     313             :         }
     314             : 
     315       30499 :         if (tevent_req_nterror(req, status)) {
     316           0 :                 return;
     317             :         }
     318             : 
     319       30499 :         subreq = state->method->ops->check_password_send(
     320             :                 state, state->ev, state->method, state->user_info);
     321       30499 :         if (tevent_req_nomem(subreq, req)) {
     322           0 :                 return;
     323             :         }
     324       30499 :         tevent_req_set_callback(subreq, auth_check_password_done, req);
     325             : }
     326             : 
     327       30499 : static void auth_check_password_done(struct tevent_req *subreq)
     328             : {
     329        1426 :         struct tevent_req *req =
     330       30499 :                 tevent_req_callback_data(subreq,
     331             :                 struct tevent_req);
     332        1426 :         struct auth_check_password_state *state =
     333       30499 :                 tevent_req_data(req,
     334             :                 struct auth_check_password_state);
     335       30499 :         bool authoritative = true;
     336        1426 :         NTSTATUS status;
     337             : 
     338       30499 :         status = state->method->ops->check_password_recv(subreq, state,
     339             :                                                          &state->user_info_dc,
     340             :                                                          &state->client_audit_info,
     341             :                                                          &state->server_audit_info,
     342             :                                                          &authoritative);
     343       30499 :         TALLOC_FREE(subreq);
     344       30499 :         if (!authoritative ||
     345       29268 :             NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     346        1356 :                 DEBUG(11,("auth_check_password_send: "
     347             :                           "%s passes to the next method\n",
     348             :                           state->method->ops->name));
     349        1356 :                 state->method = state->method->next;
     350        1356 :                 auth_check_password_next(req);
     351        1356 :                 return;
     352             :         }
     353             : 
     354             :         /* the backend has handled the request */
     355             : 
     356       29143 :         if (tevent_req_nterror(req, status)) {
     357        5252 :                 return;
     358             :         }
     359             : 
     360       23884 :         tevent_req_done(req);
     361             : }
     362             : 
     363             : /**
     364             :  * Check a user's Plaintext, LM or NTLM password.
     365             :  * async receive function
     366             :  *
     367             :  * The return value takes precedence over the contents of the user_info_dc
     368             :  * struct.  When the return is other than NT_STATUS_OK the contents
     369             :  * of that structure is undefined.
     370             :  *
     371             :  *
     372             :  * @param req The async request state
     373             :  *
     374             :  * @param mem_ctx The parent memory context for the user_info_dc structure
     375             :  *
     376             :  * @param user_info_dc If successful, contains information about the authentication,
     377             :  *                    including a SAM_ACCOUNT struct describing the user.
     378             :  *
     379             :  * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
     380             :  *
     381             :  **/
     382             : 
     383       29195 : _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
     384             :                                   TALLOC_CTX *mem_ctx,
     385             :                                   struct auth_user_info_dc **user_info_dc,
     386             :                                   uint8_t *pauthoritative)
     387             : {
     388        1420 :         struct auth_check_password_state *state =
     389       29195 :                 tevent_req_data(req, struct auth_check_password_state);
     390       29195 :         NTSTATUS status = NT_STATUS_OK;
     391             : 
     392       29195 :         *pauthoritative = state->authoritative;
     393             : 
     394       29195 :         if (tevent_req_is_nterror(req, &status)) {
     395             :                 /*
     396             :                  * Please try not to change this string, it is probably in use
     397             :                  * in audit logging tools
     398             :                  */
     399        5311 :                 DEBUG(2,("auth_check_password_recv: "
     400             :                          "%s authentication for user [%s\\%s] "
     401             :                          "FAILED with error %s, authoritative=%u\n",
     402             :                          (state->method ? state->method->ops->name : "NO_METHOD"),
     403             :                          state->user_info->mapped.domain_name,
     404             :                          state->user_info->mapped.account_name,
     405             :                          nt_errstr(status), state->authoritative));
     406             : 
     407        5311 :                 log_authentication_event(state->auth_ctx->msg_ctx,
     408        5304 :                                          state->auth_ctx->lp_ctx,
     409        5311 :                                          &state->auth_ctx->start_time,
     410             :                                          state->user_info, status,
     411             :                                          NULL, NULL, NULL,
     412             :                                          state->client_audit_info,
     413             :                                          state->server_audit_info);
     414        5311 :                 tevent_req_received(req);
     415        5311 :                 return status;
     416             :         }
     417             : 
     418       23884 :         DEBUG(5,("auth_check_password_recv: "
     419             :                  "%s authentication for user [%s\\%s] succeeded\n",
     420             :                  state->method->ops->name,
     421             :                  state->user_info_dc->info->domain_name,
     422             :                  state->user_info_dc->info->account_name));
     423             : 
     424       23884 :         log_authentication_event(state->auth_ctx->msg_ctx,
     425       22471 :                                  state->auth_ctx->lp_ctx,
     426       23884 :                                  &state->auth_ctx->start_time,
     427             :                                  state->user_info, status,
     428       22471 :                                  state->user_info_dc->info->domain_name,
     429       23884 :                                  state->user_info_dc->info->account_name,
     430       23884 :                                  &state->user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid,
     431             :                                  state->client_audit_info,
     432             :                                  state->server_audit_info);
     433             : 
     434             :         /*
     435             :          * Release our handle to state->user_info_dc.
     436             :          * state->{client,server}_audit_info, if non-NULL, becomes the new
     437             :          * parent.
     438             :         */
     439       23884 :         *user_info_dc = talloc_reparent(state, mem_ctx, state->user_info_dc);
     440       23884 :         state->user_info_dc = NULL;
     441             : 
     442       23884 :         tevent_req_received(req);
     443       23884 :         return NT_STATUS_OK;
     444             : }
     445             : 
     446             : struct auth_check_password_wrapper_state {
     447             :         uint8_t authoritative;
     448             :         struct auth_user_info_dc *user_info_dc;
     449             : };
     450             : 
     451             : static void auth_check_password_wrapper_done(struct tevent_req *subreq);
     452             : 
     453       13929 : static struct tevent_req *auth_check_password_wrapper_send(TALLOC_CTX *mem_ctx,
     454             :                                         struct tevent_context *ev,
     455             :                                         struct auth4_context *auth_ctx,
     456             :                                         const struct auth_usersupplied_info *user_info)
     457             : {
     458       13929 :         struct tevent_req *req = NULL;
     459       13929 :         struct auth_check_password_wrapper *state = NULL;
     460       13929 :         struct tevent_req *subreq = NULL;
     461             : 
     462       13929 :         req = tevent_req_create(mem_ctx, &state,
     463             :                                 struct auth_check_password_wrapper_state);
     464       13929 :         if (req == NULL) {
     465           0 :                 return NULL;
     466             :         }
     467             : 
     468       13929 :         subreq = auth_check_password_send(state, ev, auth_ctx, user_info);
     469       13929 :         if (tevent_req_nomem(subreq, req)) {
     470           0 :                 return tevent_req_post(req, ev);
     471             :         }
     472       13929 :         tevent_req_set_callback(subreq,
     473             :                                 auth_check_password_wrapper_done,
     474             :                                 req);
     475             : 
     476       13929 :         return req;
     477             : }
     478             : 
     479       13929 : static void auth_check_password_wrapper_done(struct tevent_req *subreq)
     480             : {
     481         146 :         struct tevent_req *req =
     482       13929 :                 tevent_req_callback_data(subreq,
     483             :                 struct tevent_req);
     484         146 :         struct auth_check_password_wrapper_state *state =
     485       13929 :                 tevent_req_data(req,
     486             :                 struct auth_check_password_wrapper_state);
     487         146 :         NTSTATUS status;
     488             : 
     489       13929 :         status = auth_check_password_recv(subreq, state,
     490             :                                           &state->user_info_dc,
     491             :                                           &state->authoritative);
     492       13929 :         TALLOC_FREE(subreq);
     493       13929 :         if (tevent_req_nterror(req, status)) {
     494        1434 :                 return;
     495             :         }
     496             : 
     497       12495 :         tevent_req_done(req);
     498             : }
     499             : 
     500       13929 : static NTSTATUS auth_check_password_wrapper_recv(struct tevent_req *req,
     501             :                                         TALLOC_CTX *mem_ctx,
     502             :                                         uint8_t *pauthoritative,
     503             :                                         void **server_returned_info,
     504             :                                         DATA_BLOB *user_session_key,
     505             :                                         DATA_BLOB *lm_session_key)
     506             : {
     507         146 :         struct auth_check_password_wrapper_state *state =
     508       13929 :                 tevent_req_data(req,
     509             :                 struct auth_check_password_wrapper_state);
     510       13929 :         struct auth_user_info_dc *user_info_dc = state->user_info_dc;
     511       13929 :         NTSTATUS status = NT_STATUS_OK;
     512             : 
     513       13929 :         *pauthoritative = state->authoritative;
     514             : 
     515       13929 :         if (tevent_req_is_nterror(req, &status)) {
     516        1434 :                 tevent_req_received(req);
     517        1434 :                 return status;
     518             :         }
     519             : 
     520       12495 :         talloc_steal(mem_ctx, user_info_dc);
     521       12495 :         *server_returned_info = user_info_dc;
     522             : 
     523       12495 :         if (user_session_key) {
     524       12484 :                 DEBUG(10, ("Got NT session key of length %u\n",
     525             :                            (unsigned)user_info_dc->user_session_key.length));
     526       12484 :                 *user_session_key = user_info_dc->user_session_key;
     527       12484 :                 talloc_steal(mem_ctx, user_session_key->data);
     528       12484 :                 user_info_dc->user_session_key = data_blob_null;
     529             :         }
     530             : 
     531       12495 :         if (lm_session_key) {
     532       12484 :                 DEBUG(10, ("Got LM session key of length %u\n",
     533             :                            (unsigned)user_info_dc->lm_session_key.length));
     534       12484 :                 *lm_session_key = user_info_dc->lm_session_key;
     535       12484 :                 talloc_steal(mem_ctx, lm_session_key->data);
     536       12484 :                 user_info_dc->lm_session_key = data_blob_null;
     537             :         }
     538             : 
     539       12495 :         tevent_req_received(req);
     540       12495 :         return NT_STATUS_OK;
     541             : }
     542             : 
     543             :  /* Wrapper because we don't want to expose all callers to needing to
     544             :   * know that session_info is generated from the main ldb, and because
     545             :   * we need to break a dependency loop between the DCE/RPC layer and the
     546             :   * generation of unix tokens via IRPC */
     547       46989 : static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
     548             :                                                    TALLOC_CTX *mem_ctx,
     549             :                                                    void *server_returned_info,
     550             :                                                    const char *original_user_name,
     551             :                                                   uint32_t session_info_flags,
     552             :                                                   struct auth_session_info **session_info)
     553             : {
     554        1348 :         NTSTATUS status;
     555       46989 :         struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
     556             : 
     557       46989 :         if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
     558       43992 :                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     559             :         }
     560             : 
     561       46989 :         status = auth_generate_session_info(mem_ctx,
     562             :                                             auth_context->lp_ctx,
     563             :                                             auth_context->sam_ctx,
     564             :                                             user_info_dc,
     565             :                                             session_info_flags,
     566             :                                             session_info);
     567       46989 :         if (!NT_STATUS_IS_OK(status)) {
     568           0 :                 return status;
     569             :         }
     570             : 
     571       46989 :         if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
     572        8560 :             && NT_STATUS_IS_OK(status)) {
     573        9362 :                 status = auth_session_info_fill_unix(auth_context->lp_ctx,
     574             :                                                      original_user_name,
     575             :                                                      *session_info);
     576        9362 :                 if (!NT_STATUS_IS_OK(status)) {
     577           0 :                         TALLOC_FREE(*session_info);
     578             :                 }
     579             :         }
     580       46989 :         return status;
     581             : }
     582             : 
     583             : /* Wrapper because we don't want to expose all callers to needing to
     584             :  * know anything about the PAC or auth subsystem internal structures
     585             :  * before we output a struct auth session_info */
     586       31335 : static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
     587             :                                                TALLOC_CTX *mem_ctx,
     588             :                                                struct smb_krb5_context *smb_krb5_context,
     589             :                                                DATA_BLOB *pac_blob,
     590             :                                                const char *principal_name,
     591             :                                                const struct tsocket_address *remote_address,
     592             :                                                uint32_t session_info_flags,
     593             :                                                struct auth_session_info **session_info)
     594             : {
     595         881 :         NTSTATUS status;
     596         881 :         struct auth_user_info_dc *user_info_dc;
     597         881 :         TALLOC_CTX *tmp_ctx;
     598             : 
     599       31335 :         if (!pac_blob) {
     600             :                 /*
     601             :                  * This should already have been caught at the main
     602             :                  * gensec layer, but better check twice
     603             :                  */
     604           0 :                 return NT_STATUS_INTERNAL_ERROR;
     605             :         }
     606             : 
     607       31335 :         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
     608       31335 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
     609             : 
     610             :         /*
     611             :          * FIXME: To correctly create the security token, we also need to get the
     612             :          * claims info, device info, and device claims info from the PAC. For now,
     613             :          * we support claims only in the KDC.
     614             :          */
     615       31335 :         status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
     616             :                                                    *pac_blob,
     617             :                                                    smb_krb5_context->krb5_context,
     618             :                                                    &user_info_dc, NULL, NULL);
     619       31335 :         if (!NT_STATUS_IS_OK(status)) {
     620           0 :                 talloc_free(tmp_ctx);
     621           0 :                 return status;
     622             :         }
     623             : 
     624       31335 :         if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
     625       31335 :                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     626             :         }
     627             : 
     628       31335 :         status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
     629             :                                                     user_info_dc,
     630       30454 :                                                     user_info_dc->info->account_name,
     631             :                                                     session_info_flags, session_info);
     632       31335 :         talloc_free(tmp_ctx);
     633       31335 :         return status;
     634             : }
     635             : 
     636             : /***************************************************************************
     637             :  Make a auth_info struct for the auth subsystem
     638             :  - Allow the caller to specify the methods to use, including optionally the SAM to use
     639             : ***************************************************************************/
     640      149739 : _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods,
     641             :                                               struct tevent_context *ev,
     642             :                                               struct imessaging_context *msg,
     643             :                                               struct loadparm_context *lp_ctx,
     644             :                                               struct ldb_context *sam_ctx,
     645             :                                               struct auth4_context **auth_ctx)
     646             : {
     647        4151 :         int i;
     648        4151 :         struct auth4_context *ctx;
     649             : 
     650      149739 :         auth4_init();
     651             : 
     652      149739 :         if (!ev) {
     653           0 :                 DEBUG(0,("auth_context_create: called with out event context\n"));
     654           0 :                 return NT_STATUS_INTERNAL_ERROR;
     655             :         }
     656             : 
     657      149739 :         ctx = talloc_zero(mem_ctx, struct auth4_context);
     658      149739 :         NT_STATUS_HAVE_NO_MEMORY(ctx);
     659      149739 :         ctx->challenge.data          = data_blob(NULL, 0);
     660      149739 :         ctx->methods                 = NULL;
     661      149739 :         ctx->event_ctx                       = ev;
     662      149739 :         ctx->msg_ctx                 = msg;
     663      149739 :         ctx->lp_ctx                  = lp_ctx;
     664      149739 :         ctx->start_time                 = timeval_current();
     665             : 
     666      149739 :         if (sam_ctx) {
     667           7 :                 ctx->sam_ctx = sam_ctx;
     668             :         } else {
     669      149732 :                 ctx->sam_ctx = samdb_connect(ctx,
     670             :                                              ctx->event_ctx,
     671             :                                              ctx->lp_ctx,
     672             :                                              system_session(ctx->lp_ctx),
     673             :                                              NULL,
     674             :                                              0);
     675             :         }
     676             : 
     677      719057 :         for (i=0; methods && methods[i] ; i++) {
     678       14056 :                 struct auth_method_context *method;
     679             : 
     680      569318 :                 method = talloc(ctx, struct auth_method_context);
     681      569318 :                 NT_STATUS_HAVE_NO_MEMORY(method);
     682             : 
     683      569318 :                 method->ops = auth_backend_byname(methods[i]);
     684      569318 :                 if (!method->ops) {
     685           0 :                         DEBUG(1,("auth_context_create: failed to find method=%s\n",
     686             :                                 methods[i]));
     687           0 :                         return NT_STATUS_INTERNAL_ERROR;
     688             :                 }
     689      569318 :                 method->auth_ctx     = ctx;
     690      569318 :                 method->depth                = i;
     691      569318 :                 DLIST_ADD_END(ctx->methods, method);
     692             :         }
     693             : 
     694      149739 :         ctx->check_ntlm_password_send = auth_check_password_wrapper_send;
     695      149739 :         ctx->check_ntlm_password_recv = auth_check_password_wrapper_recv;
     696      149739 :         ctx->get_ntlm_challenge = auth_get_challenge;
     697      149739 :         ctx->set_ntlm_challenge = auth_context_set_challenge;
     698      149739 :         ctx->generate_session_info = auth_generate_session_info_wrapper;
     699      149739 :         ctx->generate_session_info_pac = auth_generate_session_info_pac;
     700             : 
     701      149739 :         *auth_ctx = ctx;
     702             : 
     703      149739 :         return NT_STATUS_OK;
     704             : }
     705             : 
     706      134945 : const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
     707             : {
     708      134945 :         char **auth_methods = NULL;
     709             : 
     710      134945 :         switch (lpcfg_server_role(lp_ctx)) {
     711          20 :         case ROLE_STANDALONE:
     712          20 :                 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
     713          20 :                 break;
     714      134925 :         case ROLE_DOMAIN_MEMBER:
     715             :         case ROLE_DOMAIN_BDC:
     716             :         case ROLE_DOMAIN_PDC:
     717             :         case ROLE_ACTIVE_DIRECTORY_DC:
     718             :         case ROLE_IPA_DC:
     719      134925 :                 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
     720      134925 :                 break;
     721             :         }
     722      134945 :         return discard_const_p(const char *, auth_methods);
     723             : }
     724             : 
     725             : /***************************************************************************
     726             :  Make a auth_info struct for the auth subsystem
     727             :  - Uses default auth_methods, depending on server role and smb.conf settings
     728             : ***************************************************************************/
     729      134943 : _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
     730             :                              struct tevent_context *ev,
     731             :                              struct imessaging_context *msg,
     732             :                              struct loadparm_context *lp_ctx,
     733             :                              struct auth4_context **auth_ctx)
     734             : {
     735        2877 :         NTSTATUS status;
     736        2877 :         const char **auth_methods;
     737      134943 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     738      134943 :         if (!tmp_ctx) {
     739           0 :                 return NT_STATUS_NO_MEMORY;
     740             :         }
     741             : 
     742      134943 :         auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
     743      134943 :         if (!auth_methods) {
     744           0 :                 return NT_STATUS_INVALID_PARAMETER;
     745             :         }
     746      134943 :         status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
     747      134943 :         talloc_free(tmp_ctx);
     748      134943 :         return status;
     749             : }
     750             : 
     751       14789 : _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
     752             :                                                    struct tevent_context *ev,
     753             :                                                    struct imessaging_context *msg,
     754             :                                                    struct loadparm_context *lp_ctx,
     755             :                                                    struct auth4_context **auth_ctx)
     756             : {
     757        1274 :         NTSTATUS status;
     758       14789 :         char **_auth_methods = NULL;
     759       14789 :         const char **auth_methods = NULL;
     760             : 
     761             :         /*
     762             :          * Here we only allow 'sam winbind' instead of
     763             :          * the 'anonymous sam winbind sam_ignoredomain'
     764             :          * we typically use for authentication from clients.
     765             :          */
     766       14789 :         _auth_methods = str_list_make(mem_ctx, "sam winbind", NULL);
     767       14789 :         if (_auth_methods == NULL) {
     768           0 :                 return NT_STATUS_NO_MEMORY;
     769             :         }
     770       14789 :         auth_methods = discard_const_p(const char *, _auth_methods);
     771             : 
     772       14789 :         status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg,
     773             :                                              lp_ctx, NULL, auth_ctx);
     774       14789 :         talloc_free(_auth_methods);
     775       14789 :         return status;
     776             : }
     777             : 
     778             : /* the list of currently registered AUTH backends */
     779             : static struct auth_backend {
     780             :         const struct auth_operations *ops;
     781             : } *backends = NULL;
     782             : static int num_backends;
     783             : 
     784             : /*
     785             :   register a AUTH backend.
     786             : 
     787             :   The 'name' can be later used by other backends to find the operations
     788             :   structure for this backend.
     789             : */
     790       48405 : _PUBLIC_ NTSTATUS auth_register(TALLOC_CTX *mem_ctx,
     791             :                         const struct auth_operations *ops)
     792             : {
     793        4185 :         struct auth_operations *new_ops;
     794             : 
     795       48405 :         if (auth_backend_byname(ops->name) != NULL) {
     796             :                 /* its already registered! */
     797           0 :                 DEBUG(0,("AUTH backend '%s' already registered\n",
     798             :                          ops->name));
     799           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
     800             :         }
     801             : 
     802       48405 :         backends = talloc_realloc(mem_ctx, backends,
     803             :                                   struct auth_backend, num_backends+1);
     804       48405 :         NT_STATUS_HAVE_NO_MEMORY(backends);
     805             : 
     806       48405 :         new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
     807       48405 :         NT_STATUS_HAVE_NO_MEMORY(new_ops);
     808       48405 :         new_ops->name = talloc_strdup(new_ops, ops->name);
     809       48405 :         NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
     810             : 
     811       48405 :         backends[num_backends].ops = new_ops;
     812             : 
     813       48405 :         num_backends++;
     814             : 
     815       48405 :         DEBUG(3,("AUTH backend '%s' registered\n",
     816             :                  ops->name));
     817             : 
     818       48405 :         return NT_STATUS_OK;
     819             : }
     820             : 
     821             : /*
     822             :   return the operations structure for a named backend of the specified type
     823             : */
     824      617723 : const struct auth_operations *auth_backend_byname(const char *name)
     825             : {
     826       18241 :         int i;
     827             : 
     828     1568510 :         for (i=0;i<num_backends;i++) {
     829     1520105 :                 if (strcmp(backends[i].ops->name, name) == 0) {
     830      569318 :                         return backends[i].ops;
     831             :                 }
     832             :         }
     833             : 
     834       44220 :         return NULL;
     835             : }
     836             : 
     837             : /*
     838             :   return the AUTH interface version, and the size of some critical types
     839             :   This can be used by backends to either detect compilation errors, or provide
     840             :   multiple implementations for different smbd compilation options in one module
     841             : */
     842           0 : const struct auth_critical_sizes *auth_interface_version(void)
     843             : {
     844           0 :         static const struct auth_critical_sizes critical_sizes = {
     845             :                 AUTH4_INTERFACE_VERSION,
     846             :                 sizeof(struct auth_operations),
     847             :                 sizeof(struct auth_method_context),
     848             :                 sizeof(struct auth4_context),
     849             :                 sizeof(struct auth_usersupplied_info),
     850             :                 sizeof(struct auth_user_info_dc)
     851             :         };
     852             : 
     853           0 :         return &critical_sizes;
     854             : }
     855             : 
     856      149805 : _PUBLIC_ NTSTATUS auth4_init(void)
     857             : {
     858        4154 :         static bool initialized = false;
     859             : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
     860        4154 :         STATIC_auth4_MODULES_PROTO;
     861      149805 :         init_module_fn static_init[] = { STATIC_auth4_MODULES };
     862             : 
     863      149805 :         if (initialized) return NT_STATUS_OK;
     864        9681 :         initialized = true;
     865             : 
     866        9681 :         run_init_functions(NULL, static_init);
     867             : 
     868        9681 :         return NT_STATUS_OK;
     869             : }

Generated by: LCOV version 1.14