LCOV - code coverage report
Current view: top level - source4/auth/ntlm - auth.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 260 286 90.9 %
Date: 2024-06-13 04:01:37 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       10163 : _PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by) 
      51             : {
      52       10163 :         auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
      53       10163 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
      54             : 
      55       10163 :         auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
      56       10163 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
      57             : 
      58       10163 :         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       29979 : _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t chal[8])
      66             : {
      67             : 
      68       29979 :         if (auth_ctx->challenge.data.length == 8) {
      69       19815 :                 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n", 
      70             :                           auth_ctx->challenge.set_by));
      71       19815 :                 memcpy(chal, auth_ctx->challenge.data.data, 8);
      72       19815 :                 return NT_STATUS_OK;
      73             :         }
      74             : 
      75       10164 :         if (!auth_ctx->challenge.set_by) {
      76       10164 :                 generate_random_buffer(chal, 8);
      77             : 
      78       10164 :                 auth_ctx->challenge.data             = data_blob_talloc(auth_ctx, chal, 8);
      79       10164 :                 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
      80       10164 :                 auth_ctx->challenge.set_by           = "random";
      81             :         }
      82             : 
      83       10164 :         DEBUG(10,("auth_get_challenge: challenge set by %s\n",
      84             :                  auth_ctx->challenge.set_by));
      85             : 
      86       10164 :         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 geneation 
     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             :         struct tevent_req *subreq;
     123             :         struct tevent_context *ev;
     124             :         bool ok;
     125             :         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             :         uint8_t authoritative;
     162             : };
     163             : 
     164             : static void auth_check_password_next(struct tevent_req *req);
     165             : 
     166             : /**
     167             :  * Check a user's Plaintext, LM or NTLM password.
     168             :  * async send hook
     169             :  *
     170             :  * Check a user's password, as given in the user_info struct and return various
     171             :  * interesting details in the user_info_dc struct.
     172             :  *
     173             :  * The return value takes precedence over the contents of the user_info_dc
     174             :  * struct.  When the return is other than NT_STATUS_OK the contents 
     175             :  * of that structure is undefined.
     176             :  *
     177             :  * @param mem_ctx The memory context the request should operate on
     178             :  *
     179             :  * @param ev The tevent context the request should operate on
     180             :  *
     181             :  * @param auth_ctx Supplies the challenges and some other data.  Must
     182             :  *                 be created with make_auth_context(), and the
     183             :  *                 challenges should be filled in, either at creation
     184             :  *                 or by calling the challenge generation function
     185             :  *                 auth_get_challenge().
     186             :  *
     187             :  * @param user_info Contains the user supplied components, including the passwords.
     188             :  *
     189             :  * @return The request handle or NULL on no memory error.
     190             :  *
     191             :  **/
     192             : 
     193       20318 : _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
     194             :                                 struct tevent_context *ev,
     195             :                                 struct auth4_context *auth_ctx,
     196             :                                 const struct auth_usersupplied_info *user_info)
     197             : {
     198             :         struct tevent_req *req;
     199             :         struct auth_check_password_state *state;
     200             :         /* if all the modules say 'not for me' this is reasonable */
     201             :         NTSTATUS nt_status;
     202             :         uint8_t chal[8];
     203             : 
     204       20318 :         DEBUG(3,("auth_check_password_send: "
     205             :                  "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
     206             :                  user_info->client.domain_name, user_info->client.account_name,
     207             :                  user_info->workstation_name));
     208             : 
     209       20318 :         req = tevent_req_create(mem_ctx, &state,
     210             :                                 struct auth_check_password_state);
     211       20318 :         if (req == NULL) {
     212           0 :                 return NULL;
     213             :         }
     214             : 
     215             :         /*
     216             :          * We are authoritative by default.
     217             :          */
     218       20318 :         state->ev            = ev;
     219       20318 :         state->auth_ctx              = auth_ctx;
     220       20318 :         state->user_info     = user_info;
     221       20318 :         state->authoritative = 1;
     222             : 
     223       20318 :         if (user_info->mapped.account_name == NULL) {
     224             :                 struct auth_usersupplied_info *user_info_tmp;
     225             : 
     226             :                 /*
     227             :                  * We don't really do any mapping here.
     228             :                  *
     229             :                  * It's up to the backends to do mappings
     230             :                  * for their authentication.
     231             :                  */
     232       20317 :                 user_info_tmp = talloc_zero(state, struct auth_usersupplied_info);
     233       20317 :                 if (tevent_req_nomem(user_info_tmp, req)) {
     234           0 :                         return tevent_req_post(req, ev);;
     235             :                 }
     236             : 
     237             :                 /*
     238             :                  * The lifetime of user_info is longer than
     239             :                  * user_info_tmp, so we don't need to copy the
     240             :                  * strings.
     241             :                  */
     242       20317 :                 *user_info_tmp = *user_info;
     243       20317 :                 user_info_tmp->mapped.domain_name = user_info->client.domain_name;
     244       20317 :                 user_info_tmp->mapped.account_name = user_info->client.account_name;
     245             : 
     246       20317 :                 user_info = user_info_tmp;
     247       20317 :                 state->user_info = user_info_tmp;
     248             :         }
     249             : 
     250       20318 :         DEBUGADD(3,("auth_check_password_send: "
     251             :                     "user is: [%s]\\[%s]@[%s]\n",
     252             :                     user_info->mapped.domain_name,
     253             :                     user_info->mapped.account_name,
     254             :                     user_info->workstation_name));
     255             : 
     256       20318 :         nt_status = auth_get_challenge(auth_ctx, chal);
     257       20318 :         if (tevent_req_nterror(req, nt_status)) {
     258           0 :                 DEBUG(0,("auth_check_password_send: "
     259             :                          "Invalid challenge (length %u) stored for "
     260             :                          "this auth context set_by %s - cannot continue: %s\n",
     261             :                         (unsigned)auth_ctx->challenge.data.length,
     262             :                         auth_ctx->challenge.set_by,
     263             :                         nt_errstr(nt_status)));
     264           0 :                 return tevent_req_post(req, ev);
     265             :         }
     266             : 
     267       20318 :         if (auth_ctx->challenge.set_by) {
     268       20318 :                 DEBUG(10,("auth_check_password_send: "
     269             :                           "auth_context challenge created by %s\n",
     270             :                           auth_ctx->challenge.set_by));
     271             :         }
     272             : 
     273       20318 :         DEBUG(10, ("auth_check_password_send: challenge is: \n"));
     274       20318 :         dump_data(5, auth_ctx->challenge.data.data,
     275       20318 :                   auth_ctx->challenge.data.length);
     276             : 
     277       20318 :         state->method = state->auth_ctx->methods;
     278       20318 :         auth_check_password_next(req);
     279       20318 :         if (!tevent_req_is_in_progress(req)) {
     280          10 :                 return tevent_req_post(req, ev);
     281             :         }
     282             : 
     283       20308 :         return req;
     284             : }
     285             : 
     286             : static void auth_check_password_done(struct tevent_req *subreq);
     287             : 
     288       30335 : static void auth_check_password_next(struct tevent_req *req)
     289             : {
     290       24828 :         struct auth_check_password_state *state =
     291       30335 :                 tevent_req_data(req, struct auth_check_password_state);
     292       30335 :         struct tevent_req *subreq = NULL;
     293             :         NTSTATUS status;
     294             : 
     295       30335 :         if (state->method == NULL) {
     296          48 :                 state->authoritative = 0;
     297          48 :                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
     298          48 :                 return;
     299             :         }
     300             : 
     301             :         /* check if the module wants to check the password */
     302       30287 :         status = state->method->ops->want_check(state->method, state,
     303             :                                                 state->user_info);
     304       30287 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     305        9704 :                 DEBUG(11,("auth_check_password_send: "
     306             :                           "%s doesn't want to check\n",
     307             :                           state->method->ops->name));
     308        9704 :                 state->method = state->method->next;
     309        9704 :                 auth_check_password_next(req);
     310        9704 :                 return;
     311             :         }
     312             : 
     313       20583 :         if (tevent_req_nterror(req, status)) {
     314           0 :                 return;
     315             :         }
     316             : 
     317       20583 :         subreq = state->method->ops->check_password_send(
     318             :                 state, state->ev, state->method, state->user_info);
     319       20583 :         if (tevent_req_nomem(subreq, req)) {
     320           0 :                 return;
     321             :         }
     322       20583 :         tevent_req_set_callback(subreq, auth_check_password_done, req);
     323             : }
     324             : 
     325       20583 : static void auth_check_password_done(struct tevent_req *subreq)
     326             : {
     327       17687 :         struct tevent_req *req =
     328       20583 :                 tevent_req_callback_data(subreq,
     329             :                 struct tevent_req);
     330       17687 :         struct auth_check_password_state *state =
     331       20583 :                 tevent_req_data(req,
     332             :                 struct auth_check_password_state);
     333       20583 :         bool authoritative = true;
     334             :         NTSTATUS status;
     335             : 
     336       20583 :         status = state->method->ops->check_password_recv(subreq, state,
     337             :                                                          &state->user_info_dc,
     338             :                                                          &authoritative);
     339       20583 :         TALLOC_FREE(subreq);
     340       38113 :         if (!authoritative ||
     341       20395 :             NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     342         313 :                 DEBUG(11,("auth_check_password_send: "
     343             :                           "%s passes to the next method\n",
     344             :                           state->method->ops->name));
     345         313 :                 state->method = state->method->next;
     346         313 :                 auth_check_password_next(req);
     347         313 :                 return;
     348             :         }
     349             : 
     350             :         /* the backend has handled the request */
     351             : 
     352       20270 :         if (tevent_req_nterror(req, status)) {
     353        4003 :                 return;
     354             :         }
     355             : 
     356       16267 :         tevent_req_done(req);
     357             : }
     358             : 
     359             : /**
     360             :  * Check a user's Plaintext, LM or NTLM password.
     361             :  * async receive function
     362             :  *
     363             :  * The return value takes precedence over the contents of the user_info_dc
     364             :  * struct.  When the return is other than NT_STATUS_OK the contents 
     365             :  * of that structure is undefined.
     366             :  *
     367             :  *
     368             :  * @param req The async request state
     369             :  *
     370             :  * @param mem_ctx The parent memory context for the user_info_dc structure
     371             :  *
     372             :  * @param user_info_dc If successful, contains information about the authentication,
     373             :  *                    including a SAM_ACCOUNT struct describing the user.
     374             :  *
     375             :  * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
     376             :  *
     377             :  **/
     378             : 
     379       20318 : _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
     380             :                                   TALLOC_CTX *mem_ctx,
     381             :                                   struct auth_user_info_dc **user_info_dc,
     382             :                                   uint8_t *pauthoritative)
     383             : {
     384       17430 :         struct auth_check_password_state *state =
     385       20318 :                 tevent_req_data(req, struct auth_check_password_state);
     386       20318 :         NTSTATUS status = NT_STATUS_OK;
     387             : 
     388       20318 :         *pauthoritative = state->authoritative;
     389             : 
     390       20318 :         if (tevent_req_is_nterror(req, &status)) {
     391             :                 /*
     392             :                  * Please try not to change this string, it is probably in use
     393             :                  * in audit logging tools
     394             :                  */
     395        4051 :                 DEBUG(2,("auth_check_password_recv: "
     396             :                          "%s authentication for user [%s\\%s] "
     397             :                          "FAILED with error %s, authoritative=%u\n",
     398             :                          (state->method ? state->method->ops->name : "NO_METHOD"),
     399             :                          state->user_info->mapped.domain_name,
     400             :                          state->user_info->mapped.account_name,
     401             :                          nt_errstr(status), state->authoritative));
     402             : 
     403        7982 :                 log_authentication_event(state->auth_ctx->msg_ctx,
     404        4051 :                                          state->auth_ctx->lp_ctx,
     405        4051 :                                          &state->auth_ctx->start_time,
     406             :                                          state->user_info, status,
     407             :                                          NULL, NULL, NULL);
     408        4051 :                 tevent_req_received(req);
     409        4051 :                 return status;
     410             :         }
     411             : 
     412       16267 :         DEBUG(5,("auth_check_password_recv: "
     413             :                  "%s authentication for user [%s\\%s] succeeded\n",
     414             :                  state->method->ops->name,
     415             :                  state->user_info_dc->info->domain_name,
     416             :                  state->user_info_dc->info->account_name));
     417             : 
     418       56764 :         log_authentication_event(state->auth_ctx->msg_ctx,
     419       16267 :                                  state->auth_ctx->lp_ctx,
     420       16267 :                                  &state->auth_ctx->start_time,
     421             :                                  state->user_info, status,
     422       16267 :                                  state->user_info_dc->info->domain_name,
     423       16267 :                                  state->user_info_dc->info->account_name,
     424       16267 :                                  &state->user_info_dc->sids[0]);
     425             : 
     426       16267 :         *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
     427             : 
     428       16267 :         tevent_req_received(req);
     429       16267 :         return NT_STATUS_OK;
     430             : }
     431             : 
     432             : struct auth_check_password_wrapper_state {
     433             :         uint8_t authoritative;
     434             :         struct auth_user_info_dc *user_info_dc;
     435             : };
     436             : 
     437             : static void auth_check_password_wrapper_done(struct tevent_req *subreq);
     438             : 
     439        9217 : static struct tevent_req *auth_check_password_wrapper_send(TALLOC_CTX *mem_ctx,
     440             :                                         struct tevent_context *ev,
     441             :                                         struct auth4_context *auth_ctx,
     442             :                                         const struct auth_usersupplied_info *user_info)
     443             : {
     444        9217 :         struct tevent_req *req = NULL;
     445        9217 :         struct auth_check_password_wrapper *state = NULL;
     446        9217 :         struct tevent_req *subreq = NULL;
     447             : 
     448        9217 :         req = tevent_req_create(mem_ctx, &state,
     449             :                                 struct auth_check_password_wrapper_state);
     450        9217 :         if (req == NULL) {
     451           0 :                 return NULL;
     452             :         }
     453             : 
     454        9217 :         subreq = auth_check_password_send(state, ev, auth_ctx, user_info);
     455        9217 :         if (tevent_req_nomem(subreq, req)) {
     456           0 :                 return tevent_req_post(req, ev);
     457             :         }
     458        9217 :         tevent_req_set_callback(subreq,
     459             :                                 auth_check_password_wrapper_done,
     460             :                                 req);
     461             : 
     462        9217 :         return req;
     463             : }
     464             : 
     465        9217 : static void auth_check_password_wrapper_done(struct tevent_req *subreq)
     466             : {
     467        6778 :         struct tevent_req *req =
     468        9217 :                 tevent_req_callback_data(subreq,
     469             :                 struct tevent_req);
     470        6778 :         struct auth_check_password_wrapper_state *state =
     471        9217 :                 tevent_req_data(req,
     472             :                 struct auth_check_password_wrapper_state);
     473             :         NTSTATUS status;
     474             : 
     475        9217 :         status = auth_check_password_recv(subreq, state,
     476             :                                           &state->user_info_dc,
     477             :                                           &state->authoritative);
     478        9217 :         TALLOC_FREE(subreq);
     479        9217 :         if (tevent_req_nterror(req, status)) {
     480         303 :                 return;
     481             :         }
     482             : 
     483        8914 :         tevent_req_done(req);
     484             : }
     485             : 
     486        9217 : static NTSTATUS auth_check_password_wrapper_recv(struct tevent_req *req,
     487             :                                         TALLOC_CTX *mem_ctx,
     488             :                                         uint8_t *pauthoritative,
     489             :                                         void **server_returned_info,
     490             :                                         DATA_BLOB *user_session_key,
     491             :                                         DATA_BLOB *lm_session_key)
     492             : {
     493        6778 :         struct auth_check_password_wrapper_state *state =
     494        9217 :                 tevent_req_data(req,
     495             :                 struct auth_check_password_wrapper_state);
     496        9217 :         struct auth_user_info_dc *user_info_dc = state->user_info_dc;
     497        9217 :         NTSTATUS status = NT_STATUS_OK;
     498             : 
     499        9217 :         *pauthoritative = state->authoritative;
     500             : 
     501        9217 :         if (tevent_req_is_nterror(req, &status)) {
     502         303 :                 tevent_req_received(req);
     503         303 :                 return status;
     504             :         }
     505             : 
     506        8914 :         talloc_steal(mem_ctx, user_info_dc);
     507        8914 :         *server_returned_info = user_info_dc;
     508             : 
     509        8914 :         if (user_session_key) {
     510        8914 :                 DEBUG(10, ("Got NT session key of length %u\n",
     511             :                            (unsigned)user_info_dc->user_session_key.length));
     512        8914 :                 *user_session_key = user_info_dc->user_session_key;
     513        8914 :                 talloc_steal(mem_ctx, user_session_key->data);
     514        8914 :                 user_info_dc->user_session_key = data_blob_null;
     515             :         }
     516             : 
     517        8914 :         if (lm_session_key) {
     518        8914 :                 DEBUG(10, ("Got LM session key of length %u\n",
     519             :                            (unsigned)user_info_dc->lm_session_key.length));
     520        8914 :                 *lm_session_key = user_info_dc->lm_session_key;
     521        8914 :                 talloc_steal(mem_ctx, lm_session_key->data);
     522        8914 :                 user_info_dc->lm_session_key = data_blob_null;
     523             :         }
     524             : 
     525        8914 :         tevent_req_received(req);
     526        8914 :         return NT_STATUS_OK;
     527             : }
     528             : 
     529             :  /* Wrapper because we don't want to expose all callers to needing to
     530             :   * know that session_info is generated from the main ldb, and because
     531             :   * we need to break a depenency loop between the DCE/RPC layer and the
     532             :   * generation of unix tokens via IRPC */
     533       32530 : static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
     534             :                                                    TALLOC_CTX *mem_ctx,
     535             :                                                    void *server_returned_info,
     536             :                                                    const char *original_user_name,
     537             :                                                   uint32_t session_info_flags,
     538             :                                                   struct auth_session_info **session_info)
     539             : {
     540             :         NTSTATUS status;
     541       32530 :         struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
     542             : 
     543       32530 :         if (user_info_dc->info->authenticated) {
     544       31086 :                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     545             :         }
     546             : 
     547       32530 :         status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
     548             :                                             auth_context->sam_ctx, user_info_dc,
     549             :                                             session_info_flags, session_info);
     550       32530 :         if (!NT_STATUS_IS_OK(status)) {
     551           0 :                 return status;
     552             :         }
     553             : 
     554       32530 :         if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
     555        3675 :             && NT_STATUS_IS_OK(status)) {
     556        3675 :                 status = auth_session_info_fill_unix(auth_context->lp_ctx,
     557             :                                                      original_user_name,
     558             :                                                      *session_info);
     559        3675 :                 if (!NT_STATUS_IS_OK(status)) {
     560           0 :                         TALLOC_FREE(*session_info);
     561             :                 }
     562             :         }
     563       32530 :         return status;
     564             : }
     565             : 
     566             : /* Wrapper because we don't want to expose all callers to needing to
     567             :  * know anything about the PAC or auth subsystem internal structures
     568             :  * before we output a struct auth session_info */
     569       21834 : static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
     570             :                                                TALLOC_CTX *mem_ctx,
     571             :                                                struct smb_krb5_context *smb_krb5_context,
     572             :                                                DATA_BLOB *pac_blob,
     573             :                                                const char *principal_name,
     574             :                                                const struct tsocket_address *remote_address,
     575             :                                                uint32_t session_info_flags,
     576             :                                                struct auth_session_info **session_info)
     577             : {
     578             :         NTSTATUS status;
     579             :         struct auth_user_info_dc *user_info_dc;
     580             :         TALLOC_CTX *tmp_ctx;
     581             : 
     582       21834 :         if (!pac_blob) {
     583             :                 /*
     584             :                  * This should already be catched at the main
     585             :                  * gensec layer, but better check twice
     586             :                  */
     587           0 :                 return NT_STATUS_INTERNAL_ERROR;
     588             :         }
     589             : 
     590       21834 :         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
     591       21834 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
     592             : 
     593       21834 :         status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
     594             :                                                    *pac_blob,
     595             :                                                    smb_krb5_context->krb5_context,
     596             :                                                    &user_info_dc, NULL, NULL);
     597       21834 :         if (!NT_STATUS_IS_OK(status)) {
     598           0 :                 talloc_free(tmp_ctx);
     599           0 :                 return status;
     600             :         }
     601             : 
     602       21834 :         if (user_info_dc->info->authenticated) {
     603       21834 :                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     604             :         }
     605             : 
     606       21834 :         status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx, 
     607             :                                                     user_info_dc,
     608       21834 :                                                     user_info_dc->info->account_name,
     609             :                                                     session_info_flags, session_info);
     610       21834 :         talloc_free(tmp_ctx);
     611       21834 :         return status;
     612             : }
     613             : 
     614             : /***************************************************************************
     615             :  Make a auth_info struct for the auth subsystem
     616             :  - Allow the caller to specify the methods to use, including optionally the SAM to use
     617             : ***************************************************************************/
     618       91585 : _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods, 
     619             :                                               struct tevent_context *ev,
     620             :                                               struct imessaging_context *msg,
     621             :                                               struct loadparm_context *lp_ctx,
     622             :                                               struct ldb_context *sam_ctx,
     623             :                                               struct auth4_context **auth_ctx)
     624             : {
     625             :         int i;
     626             :         struct auth4_context *ctx;
     627             : 
     628       91585 :         auth4_init();
     629             : 
     630       91585 :         if (!ev) {
     631           0 :                 DEBUG(0,("auth_context_create: called with out event context\n"));
     632           0 :                 return NT_STATUS_INTERNAL_ERROR;
     633             :         }
     634             : 
     635       91585 :         ctx = talloc_zero(mem_ctx, struct auth4_context);
     636       91585 :         NT_STATUS_HAVE_NO_MEMORY(ctx);
     637       91585 :         ctx->challenge.data          = data_blob(NULL, 0);
     638       91585 :         ctx->methods                 = NULL;
     639       91585 :         ctx->event_ctx                       = ev;
     640       91585 :         ctx->msg_ctx                 = msg;
     641       91585 :         ctx->lp_ctx                  = lp_ctx;
     642       91585 :         ctx->start_time                 = timeval_current();
     643             : 
     644       91585 :         if (sam_ctx) {
     645           5 :                 ctx->sam_ctx = sam_ctx;
     646             :         } else {
     647       91580 :                 ctx->sam_ctx = samdb_connect(ctx,
     648             :                                              ctx->event_ctx,
     649             :                                              ctx->lp_ctx,
     650             :                                              system_session(ctx->lp_ctx),
     651             :                                              NULL,
     652             :                                              0);
     653             :         }
     654             : 
     655      436477 :         for (i=0; methods && methods[i] ; i++) {
     656             :                 struct auth_method_context *method;
     657             : 
     658      344892 :                 method = talloc(ctx, struct auth_method_context);
     659      344892 :                 NT_STATUS_HAVE_NO_MEMORY(method);
     660             : 
     661      344892 :                 method->ops = auth_backend_byname(methods[i]);
     662      344892 :                 if (!method->ops) {
     663           0 :                         DEBUG(1,("auth_context_create: failed to find method=%s\n",
     664             :                                 methods[i]));
     665           0 :                         return NT_STATUS_INTERNAL_ERROR;
     666             :                 }
     667      344892 :                 method->auth_ctx     = ctx;
     668      344892 :                 method->depth                = i;
     669      344892 :                 DLIST_ADD_END(ctx->methods, method);
     670             :         }
     671             : 
     672       91585 :         ctx->check_ntlm_password_send = auth_check_password_wrapper_send;
     673       91585 :         ctx->check_ntlm_password_recv = auth_check_password_wrapper_recv;
     674       91585 :         ctx->get_ntlm_challenge = auth_get_challenge;
     675       91585 :         ctx->set_ntlm_challenge = auth_context_set_challenge;
     676       91585 :         ctx->generate_session_info = auth_generate_session_info_wrapper;
     677       91585 :         ctx->generate_session_info_pac = auth_generate_session_info_pac;
     678             : 
     679       91585 :         *auth_ctx = ctx;
     680             : 
     681       91585 :         return NT_STATUS_OK;
     682             : }
     683             : 
     684       80870 : const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
     685             : {
     686       80870 :         char **auth_methods = NULL;
     687             : 
     688       80870 :         switch (lpcfg_server_role(lp_ctx)) {
     689           4 :         case ROLE_STANDALONE:
     690           4 :                 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
     691           4 :                 break;
     692       80866 :         case ROLE_DOMAIN_MEMBER:
     693             :         case ROLE_DOMAIN_BDC:
     694             :         case ROLE_DOMAIN_PDC:
     695             :         case ROLE_ACTIVE_DIRECTORY_DC:
     696             :         case ROLE_IPA_DC:
     697       80866 :                 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
     698       80866 :                 break;
     699             :         }
     700       80870 :         return discard_const_p(const char *, auth_methods);
     701             : }
     702             : 
     703             : /***************************************************************************
     704             :  Make a auth_info struct for the auth subsystem
     705             :  - Uses default auth_methods, depending on server role and smb.conf settings
     706             : ***************************************************************************/
     707       80870 : _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
     708             :                              struct tevent_context *ev,
     709             :                              struct imessaging_context *msg,
     710             :                              struct loadparm_context *lp_ctx,
     711             :                              struct auth4_context **auth_ctx)
     712             : {
     713             :         NTSTATUS status;
     714             :         const char **auth_methods;
     715       80870 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     716       80870 :         if (!tmp_ctx) {
     717           0 :                 return NT_STATUS_NO_MEMORY;
     718             :         }
     719             : 
     720       80870 :         auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
     721       80870 :         if (!auth_methods) {
     722           0 :                 return NT_STATUS_INVALID_PARAMETER;
     723             :         }
     724       80870 :         status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
     725       80870 :         talloc_free(tmp_ctx);
     726       80870 :         return status;
     727             : }
     728             : 
     729       10710 : _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(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             :         NTSTATUS status;
     736       10710 :         char **_auth_methods = NULL;
     737       10710 :         const char **auth_methods = NULL;
     738             : 
     739             :         /*
     740             :          * Here we only allow 'sam winbind' instead of
     741             :          * the 'anonymous sam winbind sam_ignoredomain'
     742             :          * we typically use for authentication from clients.
     743             :          */
     744       10710 :         _auth_methods = str_list_make(mem_ctx, "sam winbind", NULL);
     745       10710 :         if (_auth_methods == NULL) {
     746           0 :                 return NT_STATUS_NO_MEMORY;
     747             :         }
     748       10710 :         auth_methods = discard_const_p(const char *, _auth_methods);
     749             : 
     750       10710 :         status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg,
     751             :                                              lp_ctx, NULL, auth_ctx);
     752       10710 :         talloc_free(_auth_methods);
     753       10710 :         return status;
     754             : }
     755             : 
     756             : /* the list of currently registered AUTH backends */
     757             : static struct auth_backend {
     758             :         const struct auth_operations *ops;
     759             : } *backends = NULL;
     760             : static int num_backends;
     761             : 
     762             : /*
     763             :   register a AUTH backend. 
     764             : 
     765             :   The 'name' can be later used by other backends to find the operations
     766             :   structure for this backend.
     767             : */
     768       18880 : _PUBLIC_ NTSTATUS auth_register(TALLOC_CTX *mem_ctx,
     769             :                         const struct auth_operations *ops)
     770             : {
     771             :         struct auth_operations *new_ops;
     772             :         
     773       18880 :         if (auth_backend_byname(ops->name) != NULL) {
     774             :                 /* its already registered! */
     775           0 :                 DEBUG(0,("AUTH backend '%s' already registered\n", 
     776             :                          ops->name));
     777           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
     778             :         }
     779             : 
     780       18880 :         backends = talloc_realloc(mem_ctx, backends,
     781             :                                   struct auth_backend, num_backends+1);
     782       18880 :         NT_STATUS_HAVE_NO_MEMORY(backends);
     783             : 
     784       18880 :         new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
     785       18880 :         NT_STATUS_HAVE_NO_MEMORY(new_ops);
     786       18880 :         new_ops->name = talloc_strdup(new_ops, ops->name);
     787       18880 :         NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
     788             : 
     789       18880 :         backends[num_backends].ops = new_ops;
     790             : 
     791       18880 :         num_backends++;
     792             : 
     793       18880 :         DEBUG(3,("AUTH backend '%s' registered\n", 
     794             :                  ops->name));
     795             : 
     796       18880 :         return NT_STATUS_OK;
     797             : }
     798             : 
     799             : /*
     800             :   return the operations structure for a named backend of the specified type
     801             : */
     802      363772 : const struct auth_operations *auth_backend_byname(const char *name)
     803             : {
     804             :         int i;
     805             : 
     806      918870 :         for (i=0;i<num_backends;i++) {
     807      899990 :                 if (strcmp(backends[i].ops->name, name) == 0) {
     808      344892 :                         return backends[i].ops;
     809             :                 }
     810             :         }
     811             : 
     812       18880 :         return NULL;
     813             : }
     814             : 
     815             : /*
     816             :   return the AUTH interface version, and the size of some critical types
     817             :   This can be used by backends to either detect compilation errors, or provide
     818             :   multiple implementations for different smbd compilation options in one module
     819             : */
     820           0 : const struct auth_critical_sizes *auth_interface_version(void)
     821             : {
     822             :         static const struct auth_critical_sizes critical_sizes = {
     823             :                 AUTH4_INTERFACE_VERSION,
     824             :                 sizeof(struct auth_operations),
     825             :                 sizeof(struct auth_method_context),
     826             :                 sizeof(struct auth4_context),
     827             :                 sizeof(struct auth_usersupplied_info),
     828             :                 sizeof(struct auth_user_info_dc)
     829             :         };
     830             : 
     831           0 :         return &critical_sizes;
     832             : }
     833             : 
     834       91638 : _PUBLIC_ NTSTATUS auth4_init(void)
     835             : {
     836             :         static bool initialized = false;
     837             : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
     838             :         STATIC_auth4_MODULES_PROTO;
     839       91638 :         init_module_fn static_init[] = { STATIC_auth4_MODULES };
     840             :         
     841       91638 :         if (initialized) return NT_STATUS_OK;
     842        3776 :         initialized = true;
     843             :         
     844        3776 :         run_init_functions(NULL, static_init);
     845             :         
     846        3776 :         return NT_STATUS_OK;    
     847             : }

Generated by: LCOV version 1.13