LCOV - code coverage report
Current view: top level - source4/smb_server/smb - sesssetup.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 268 325 82.5 %
Date: 2021-09-23 10:06:22 Functions: 10 10 100.0 %

          Line data    Source code
       1             : 
       2             : /* 
       3             :    Unix SMB/CIFS implementation.
       4             :    handle SMBsessionsetup
       5             :    Copyright (C) Andrew Tridgell                      1998-2001
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
       7             :    Copyright (C) Jim McDonough                        2002
       8             :    Copyright (C) Luke Howard                          2003
       9             :    Copyright (C) Stefan Metzmacher                    2005
      10             :    
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             :    
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             :    
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include <tevent.h>
      27             : #include "version.h"
      28             : #include "auth/gensec/gensec.h"
      29             : #include "auth/auth.h"
      30             : #include "smb_server/smb_server.h"
      31             : #include "samba/service_stream.h"
      32             : #include "param/param.h"
      33             : #include "../lib/tsocket/tsocket.h"
      34             : #include "lib/stream/packet.h"
      35             : 
      36             : struct sesssetup_context {
      37             :         struct auth4_context *auth_context;
      38             :         struct smbsrv_request *req;
      39             : };
      40             : 
      41             : /*
      42             :  * Log the SMB authentication, as by not calling GENSEC we won't log
      43             :  * it during the gensec_session_info().
      44             :  */
      45          19 : void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
      46             :                                                struct auth_session_info *session_info)
      47             : {
      48             :         struct tsocket_address *local_address;
      49             :         struct tsocket_address *remote_address;
      50          19 :         TALLOC_CTX *frame = talloc_stackframe();
      51             : 
      52          19 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
      53             :                                                 frame);
      54          19 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket,
      55             :                                               frame);
      56             : 
      57          19 :         log_successful_authz_event(req->smb_conn->connection->msg_ctx,
      58          19 :                                    req->smb_conn->lp_ctx,
      59             :                                    remote_address,
      60             :                                    local_address,
      61             :                                    "SMB",
      62             :                                    "bare-NTLM",
      63             :                                    AUTHZ_TRANSPORT_PROTECTION_SMB,
      64             :                                    session_info);
      65             : 
      66          19 :         talloc_free(frame);
      67          19 :         return;
      68             : }
      69             : 
      70             : 
      71             : /*
      72             :   setup the OS, Lanman and domain portions of a session setup reply
      73             : */
      74        1196 : static void sesssetup_common_strings(struct smbsrv_request *req,
      75             :                                      char **os, char **lanman, char **domain)
      76             : {
      77        1196 :         (*os) = talloc_asprintf(req, "Unix");
      78        1196 :         (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING);
      79        1196 :         (*domain) = talloc_asprintf(req, "%s", 
      80        1196 :                                     lpcfg_workgroup(req->smb_conn->lp_ctx));
      81        1196 : }
      82             : 
      83        1196 : static void smbsrv_sesssetup_backend_send(struct smbsrv_request *req,
      84             :                                           union smb_sesssetup *sess,
      85             :                                           NTSTATUS status)
      86             : {
      87        1196 :         if (NT_STATUS_IS_OK(status)) {
      88        1002 :                 req->smb_conn->negotiate.done_sesssetup = true;
      89             :                 /* we need to keep the session long term */
      90        1002 :                 req->session = talloc_steal(req->smb_conn, req->session);
      91             :         }
      92        1196 :         smbsrv_reply_sesssetup_send(req, sess, status);
      93        1196 : }
      94             : 
      95           4 : static void sesssetup_old_send(struct tevent_req *subreq)
      96             : {
      97           4 :         struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
      98           4 :         struct smbsrv_request *req = state->req;
      99             : 
     100           4 :         union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
     101           4 :         struct auth_user_info_dc *user_info_dc = NULL;
     102             :         struct auth_session_info *session_info;
     103             :         struct smbsrv_session *smb_sess;
     104             :         NTSTATUS status;
     105           4 :         uint8_t authoritative = 0;
     106             :         uint32_t flags;
     107             : 
     108           4 :         status = auth_check_password_recv(subreq, req, &user_info_dc,
     109             :                                           &authoritative);
     110           4 :         TALLOC_FREE(subreq);
     111           4 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     112             : 
     113           4 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     114           4 :         if (user_info_dc->info->authenticated) {
     115           4 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     116             :         }
     117             :         /* This references user_info_dc into session_info */
     118           4 :         status = req->smb_conn->negotiate.auth_context->generate_session_info(req->smb_conn->negotiate.auth_context,
     119             :                                                                               req,
     120             :                                                                               user_info_dc, sess->old.in.user, 
     121             :                                                                               flags, &session_info);
     122           4 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     123             : 
     124             :         /* allocate a new session */
     125           4 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     126           4 :         if (!smb_sess) {
     127           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     128           0 :                 goto failed;
     129             :         }
     130             : 
     131           4 :         smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
     132             : 
     133             :         /* Ensure this is marked as a 'real' vuid, not one
     134             :          * simply valid for the session setup leg */
     135           4 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     136           4 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     137             : 
     138             :         /* To correctly process any AndX packet (like a tree connect)
     139             :          * we need to fill in the session on the request here */
     140           4 :         req->session = smb_sess;
     141           4 :         sess->old.out.vuid = smb_sess->vuid;
     142             : 
     143           4 : failed:
     144           4 :         status = nt_status_squash(status);
     145           4 :         smbsrv_sesssetup_backend_send(req, sess, status);
     146           4 : }
     147             : 
     148             : /*
     149             :   handler for old style session setup
     150             : */
     151           4 : static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
     152             : {
     153           4 :         struct auth_usersupplied_info *user_info = NULL;
     154             :         struct tsocket_address *remote_address, *local_address;
     155           4 :         const char *remote_machine = NULL;
     156             :         struct tevent_req *subreq;
     157             :         struct sesssetup_context *state;
     158             : 
     159           4 :         sess->old.out.vuid = 0;
     160           4 :         sess->old.out.action = 0;
     161             : 
     162           4 :         sesssetup_common_strings(req, 
     163             :                                  &sess->old.out.os,
     164             :                                  &sess->old.out.lanman,
     165             :                                  &sess->old.out.domain);
     166             : 
     167           4 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     168           4 :                 req->smb_conn->negotiate.max_send = sess->old.in.bufsize;
     169             :         }
     170             : 
     171           4 :         if (req->smb_conn->negotiate.calling_name) {
     172           0 :                 remote_machine = req->smb_conn->negotiate.calling_name->name;
     173             :         }
     174             :         
     175           4 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
     176           4 :         if (!remote_address) goto nomem;
     177             : 
     178           4 :         if (!remote_machine) {
     179           4 :                 remote_machine = tsocket_address_inet_addr_string(remote_address, req);
     180           4 :                 if (!remote_machine) goto nomem;
     181             :         }
     182             : 
     183           4 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
     184           4 :         if (!local_address) goto nomem;
     185             : 
     186           4 :         user_info = talloc_zero(req, struct auth_usersupplied_info);
     187           4 :         if (!user_info) goto nomem;
     188             : 
     189           4 :         user_info->service_description = "SMB";
     190             :         
     191           4 :         user_info->mapped_state = false;
     192           4 :         user_info->logon_parameters = 0;
     193           4 :         user_info->flags = 0;
     194           4 :         user_info->client.account_name = sess->old.in.user;
     195           4 :         user_info->client.domain_name = sess->old.in.domain;
     196           4 :         user_info->workstation_name = remote_machine;
     197             : 
     198           4 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     199           4 :         user_info->local_host = talloc_steal(user_info, local_address);
     200             :         
     201           4 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     202           4 :         user_info->password.response.lanman = sess->old.in.password;
     203           4 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
     204           4 :         user_info->password.response.nt = data_blob(NULL, 0);
     205             : 
     206           4 :         state = talloc(req, struct sesssetup_context);
     207           4 :         if (!state) goto nomem;
     208             : 
     209           4 :         if (req->smb_conn->negotiate.auth_context) {
     210           4 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     211             :         } else {
     212             :                 /* TODO: should we use just "anonymous" here? */
     213           0 :                 NTSTATUS status = auth_context_create(state,
     214           0 :                                                       req->smb_conn->connection->event.ctx,
     215           0 :                                                       req->smb_conn->connection->msg_ctx,
     216           0 :                                                       req->smb_conn->lp_ctx,
     217             :                                                       &state->auth_context);
     218           0 :                 if (!NT_STATUS_IS_OK(status)) {
     219           0 :                         smbsrv_sesssetup_backend_send(req, sess, status);
     220           0 :                         return;
     221             :                 }
     222             :         }
     223             : 
     224           4 :         state->req = req;
     225             : 
     226           6 :         subreq = auth_check_password_send(state,
     227           4 :                                           req->smb_conn->connection->event.ctx,
     228           4 :                                           req->smb_conn->negotiate.auth_context,
     229             :                                           user_info);
     230           4 :         if (!subreq) goto nomem;
     231           4 :         tevent_req_set_callback(subreq, sesssetup_old_send, state);
     232           4 :         return;
     233             : 
     234           0 : nomem:
     235           0 :         smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
     236             : }
     237             : 
     238          17 : static void sesssetup_nt1_send(struct tevent_req *subreq)
     239             : {
     240          17 :         struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
     241          17 :         struct smbsrv_request *req = state->req;
     242          17 :         union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
     243          17 :         struct auth_user_info_dc *user_info_dc = NULL;
     244             :         struct auth_session_info *session_info;
     245             :         struct smbsrv_session *smb_sess;
     246          17 :         uint8_t authoritative = 0;
     247             :         uint32_t flags;
     248             :         NTSTATUS status;
     249             : 
     250          17 :         status = auth_check_password_recv(subreq, req, &user_info_dc,
     251             :                                           &authoritative);
     252          17 :         TALLOC_FREE(subreq);
     253          17 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     254             : 
     255          15 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     256          15 :         if (user_info_dc->info->authenticated) {
     257          10 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     258             :         }
     259             :         /* This references user_info_dc into session_info */
     260          15 :         status = state->auth_context->generate_session_info(state->auth_context,
     261             :                                                             req,
     262             :                                                             user_info_dc,
     263             :                                                             sess->nt1.in.user,
     264             :                                                             flags,
     265             :                                                             &session_info);
     266          15 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     267             : 
     268             :         /* allocate a new session */
     269          15 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     270          15 :         if (!smb_sess) {
     271           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     272           0 :                 goto failed;
     273             :         }
     274             : 
     275          15 :         smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
     276             : 
     277             :         /* Ensure this is marked as a 'real' vuid, not one
     278             :          * simply valid for the session setup leg */
     279          15 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     280          15 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     281             : 
     282             :         /* To correctly process any AndX packet (like a tree connect)
     283             :          * we need to fill in the session on the request here */
     284          15 :         req->session = smb_sess;
     285          15 :         sess->nt1.out.vuid = smb_sess->vuid;
     286             : 
     287          15 :         if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
     288             :                 /* Already signing, or disabled */
     289           1 :                 goto done;
     290             :         }
     291             : 
     292          25 : done:
     293          15 :         status = NT_STATUS_OK;
     294          17 : failed:
     295          17 :         status = nt_status_squash(status);
     296          17 :         smbsrv_sesssetup_backend_send(req, sess, status);
     297          17 : }
     298             : 
     299             : /*
     300             :   handler for NT1 style session setup
     301             : */
     302          17 : static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
     303             : {
     304             :         NTSTATUS status;
     305          17 :         struct auth_usersupplied_info *user_info = NULL;
     306             :         struct tsocket_address *remote_address, *local_address;
     307          17 :         const char *remote_machine = NULL;
     308             :         struct tevent_req *subreq;
     309             :         struct sesssetup_context *state;
     310          17 :         bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
     311             : 
     312          17 :         sess->nt1.out.vuid = 0;
     313          17 :         sess->nt1.out.action = 0;
     314             : 
     315          17 :         sesssetup_common_strings(req, 
     316             :                                  &sess->nt1.out.os,
     317             :                                  &sess->nt1.out.lanman,
     318             :                                  &sess->nt1.out.domain);
     319             : 
     320          17 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     321          16 :                 req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
     322          16 :                 req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
     323             :         }
     324             : 
     325          17 :         state = talloc(req, struct sesssetup_context);
     326          17 :         if (!state) goto nomem;
     327             : 
     328          17 :         state->req = req;
     329             : 
     330          17 :         if (req->smb_conn->negotiate.oid) {
     331           2 :                 if (sess->nt1.in.user && *sess->nt1.in.user) {
     332             :                         /* We can't accept a normal login, because we
     333             :                          * don't have a challenge */
     334           0 :                         status = NT_STATUS_LOGON_FAILURE;
     335           0 :                         goto failed;
     336             :                 }
     337             : 
     338             :                 /* TODO: should we use just "anonymous" here? */
     339           8 :                 status = auth_context_create(state,
     340           2 :                                              req->smb_conn->connection->event.ctx,
     341           2 :                                              req->smb_conn->connection->msg_ctx,
     342           2 :                                              req->smb_conn->lp_ctx,
     343             :                                              &state->auth_context);
     344           2 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     345          15 :         } else if (req->smb_conn->negotiate.auth_context) {
     346          15 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     347             :         } else {
     348             :                 /* TODO: should we use just "anonymous" here? */
     349           0 :                 status = auth_context_create(state,
     350           0 :                                              req->smb_conn->connection->event.ctx,
     351           0 :                                              req->smb_conn->connection->msg_ctx,
     352           0 :                                              req->smb_conn->lp_ctx,
     353             :                                              &state->auth_context);
     354           0 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     355             :         }
     356             : 
     357          17 :         if (req->smb_conn->negotiate.calling_name) {
     358           0 :                 remote_machine = req->smb_conn->negotiate.calling_name->name;
     359             :         }
     360             : 
     361          17 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
     362          17 :         if (!remote_address) goto nomem;
     363             : 
     364          17 :         if (!remote_machine) {
     365          17 :                 remote_machine = tsocket_address_inet_addr_string(remote_address, req);
     366          17 :                 if (!remote_machine) goto nomem;
     367             :         }
     368             : 
     369          17 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
     370          17 :         if (!local_address) goto nomem;
     371             : 
     372          17 :         user_info = talloc_zero(req, struct auth_usersupplied_info);
     373          17 :         if (!user_info) goto nomem;
     374             : 
     375          17 :         user_info->service_description = "SMB";
     376          17 :         user_info->auth_description = "bare-NTLM";
     377             : 
     378          17 :         user_info->mapped_state = false;
     379          17 :         user_info->logon_parameters = 0;
     380          17 :         user_info->flags = 0;
     381          17 :         user_info->client.account_name = sess->nt1.in.user;
     382          17 :         user_info->client.domain_name = sess->nt1.in.domain;
     383          17 :         user_info->workstation_name = remote_machine;
     384          17 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     385          17 :         user_info->local_host = talloc_steal(user_info, local_address);
     386             :         
     387          17 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     388          17 :         user_info->password.response.lanman = sess->nt1.in.password1;
     389          17 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
     390          17 :         user_info->password.response.nt = sess->nt1.in.password2;
     391          17 :         user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
     392             : 
     393          17 :         if (!allow_raw && user_info->password.response.nt.length >= 48) {
     394             :                 /*
     395             :                  * NTLMv2_RESPONSE has at least 48 bytes
     396             :                  * and should only be supported via NTLMSSP.
     397             :                  */
     398           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     399           0 :                 goto failed;
     400             :         }
     401             : 
     402          30 :         subreq = auth_check_password_send(state,
     403          17 :                                           req->smb_conn->connection->event.ctx,
     404             :                                           state->auth_context,
     405             :                                           user_info);
     406          17 :         if (!subreq) goto nomem;
     407          17 :         tevent_req_set_callback(subreq, sesssetup_nt1_send, state);
     408             : 
     409          17 :         return;
     410             : 
     411           0 : nomem:
     412           0 :         status = NT_STATUS_NO_MEMORY;
     413           0 : failed:
     414           0 :         status = nt_status_squash(status);
     415           0 :         smbsrv_sesssetup_backend_send(req, sess, status);
     416             : }
     417             : 
     418             : struct sesssetup_spnego_state {
     419             :         struct smbsrv_request *req;
     420             :         union smb_sesssetup *sess;
     421             :         struct smbsrv_session *smb_sess;
     422             : };
     423             : 
     424        1172 : static void sesssetup_spnego_send(struct tevent_req *subreq)
     425             : {
     426        1172 :         struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq,
     427             :                                            struct sesssetup_spnego_state);
     428        1172 :         struct smbsrv_request *req = s->req;
     429        1172 :         union smb_sesssetup *sess = s->sess;
     430        1172 :         struct smbsrv_session *smb_sess = s->smb_sess;
     431        1172 :         struct auth_session_info *session_info = NULL;
     432             :         NTSTATUS status;
     433             :         NTSTATUS skey_status;
     434             :         DATA_BLOB session_key;
     435             : 
     436        1172 :         status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
     437        1172 :         packet_recv_enable(req->smb_conn->packet);
     438        1172 :         TALLOC_FREE(subreq);
     439        1172 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     440         185 :                 goto done;
     441         987 :         } else if (!NT_STATUS_IS_OK(status)) {
     442           4 :                 goto failed;
     443             :         }
     444             : 
     445         983 :         status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
     446         983 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     447             : 
     448             :         /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
     449         983 :         skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
     450         983 :         if (NT_STATUS_IS_OK(skey_status)) {
     451         983 :                 smbsrv_setup_signing(req->smb_conn, &session_key, NULL);
     452             :         }
     453             : 
     454             :         /* Ensure this is marked as a 'real' vuid, not one
     455             :          * simply valid for the session setup leg */
     456         983 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     457         983 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     458             : 
     459         983 :         req->session = smb_sess;
     460             : 
     461        1168 : done:
     462        1168 :         sess->spnego.out.vuid = smb_sess->vuid;
     463        1172 : failed:
     464        1172 :         status = nt_status_squash(status);
     465        1172 :         smbsrv_sesssetup_backend_send(req, sess, status);
     466        1314 :         if (!NT_STATUS_IS_OK(status) && 
     467         189 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     468           4 :                 talloc_free(smb_sess);
     469             :         }
     470        1172 : }
     471             : 
     472             : /*
     473             :   handler for SPNEGO style session setup
     474             : */
     475        1175 : static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
     476             : {
     477             :         NTSTATUS status;
     478        1175 :         struct smbsrv_session *smb_sess = NULL;
     479        1175 :         bool is_smb_sess_new = false;
     480        1175 :         struct sesssetup_spnego_state *s = NULL;
     481             :         uint16_t vuid;
     482             :         struct tevent_req *subreq;
     483             : 
     484        1175 :         sess->spnego.out.vuid = 0;
     485        1175 :         sess->spnego.out.action = 0;
     486             : 
     487        1175 :         sesssetup_common_strings(req, 
     488             :                                  &sess->spnego.out.os,
     489             :                                  &sess->spnego.out.lanman,
     490             :                                  &sess->spnego.out.workgroup);
     491             : 
     492        1175 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     493        1133 :                 req->smb_conn->negotiate.max_send = sess->spnego.in.bufsize;
     494        1133 :                 req->smb_conn->negotiate.client_caps = sess->spnego.in.capabilities;
     495             :         }
     496             : 
     497        1175 :         vuid = SVAL(req->in.hdr,HDR_UID);
     498             : 
     499             :         /* lookup an existing session */
     500        1175 :         if (vuid == 0) {
     501             :                 struct gensec_security *gensec_ctx;
     502             :                 struct tsocket_address *remote_address, *local_address;
     503        3801 :                 status = samba_server_gensec_start(req,
     504         987 :                                                    req->smb_conn->connection->event.ctx,
     505         987 :                                                    req->smb_conn->connection->msg_ctx,
     506         987 :                                                    req->smb_conn->lp_ctx,
     507         987 :                                                    req->smb_conn->negotiate.server_credentials,
     508             :                                                    "cifs",
     509             :                                                    &gensec_ctx);
     510         987 :                 if (!NT_STATUS_IS_OK(status)) {
     511           0 :                         DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
     512           0 :                         goto failed;
     513             :                 }
     514             : 
     515         987 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
     516         987 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
     517             : 
     518         987 :                 remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
     519             :                                                         req);
     520         987 :                 if (!remote_address) {
     521           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     522           0 :                         DBG_ERR("Failed to obtain remote address");
     523           0 :                         goto failed;
     524             :                 }
     525             : 
     526         987 :                 status = gensec_set_remote_address(gensec_ctx,
     527             :                                                    remote_address);
     528         987 :                 if (!NT_STATUS_IS_OK(status)) {
     529           0 :                         DBG_ERR("Failed to set remote address");
     530           0 :                         goto failed;
     531             :                 }
     532             : 
     533         987 :                 local_address = socket_get_local_addr(req->smb_conn->connection->socket,
     534             :                                                         req);
     535         987 :                 if (!local_address) {
     536           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     537           0 :                         DBG_ERR("Failed to obtain local address");
     538           0 :                         goto failed;
     539             :                 }
     540             : 
     541         987 :                 status = gensec_set_local_address(gensec_ctx,
     542             :                                                    local_address);
     543         987 :                 if (!NT_STATUS_IS_OK(status)) {
     544           0 :                         DBG_ERR("Failed to set local address");
     545           0 :                         goto failed;
     546             :                 }
     547             : 
     548         987 :                 status = gensec_set_target_service_description(gensec_ctx,
     549             :                                                                "SMB");
     550             : 
     551         987 :                 if (!NT_STATUS_IS_OK(status)) {
     552           0 :                         DBG_ERR("Failed to set service description");
     553           0 :                         goto failed;
     554             :                 }
     555             : 
     556         987 :                 status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
     557         987 :                 if (!NT_STATUS_IS_OK(status)) {
     558           0 :                         DEBUG(1, ("Failed to start GENSEC %s server code: %s\n", 
     559             :                                   gensec_get_name_by_oid(gensec_ctx, req->smb_conn->negotiate.oid), nt_errstr(status)));
     560           0 :                         goto failed;
     561             :                 }
     562             : 
     563             :                 /* allocate a new session */
     564         987 :                 smb_sess = smbsrv_session_new(req->smb_conn, req->smb_conn, gensec_ctx);
     565         987 :                 if (!smb_sess) {
     566           0 :                         status = NT_STATUS_INSUFFICIENT_RESOURCES;
     567           0 :                         goto failed;
     568             :                 }
     569         987 :                 is_smb_sess_new = true;
     570             :         } else {
     571         188 :                 smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
     572             :         }
     573             : 
     574        1175 :         if (!smb_sess) {
     575           1 :                 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
     576           1 :                 goto failed;
     577             :         }
     578             : 
     579        1174 :         if (smb_sess->session_info) {
     580           2 :                 status = NT_STATUS_INVALID_PARAMETER;
     581           2 :                 goto failed;
     582             :         }
     583             : 
     584        1172 :         if (!smb_sess->gensec_ctx) {
     585           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     586           0 :                 DEBUG(1, ("Internal ERROR: no gensec_ctx on session: %s\n", nt_errstr(status)));
     587           0 :                 goto failed;
     588             :         }
     589             : 
     590        1172 :         s = talloc(req, struct sesssetup_spnego_state);
     591        1172 :         if (!s) goto nomem;
     592        1172 :         s->req               = req;
     593        1172 :         s->sess              = sess;
     594        1172 :         s->smb_sess  = smb_sess;
     595             : 
     596        2249 :         subreq = gensec_update_send(s,
     597        1172 :                                     req->smb_conn->connection->event.ctx,
     598             :                                     smb_sess->gensec_ctx,
     599             :                                     sess->spnego.in.secblob);
     600        1172 :         if (!subreq) {
     601           0 :                 goto nomem;
     602             :         }
     603             :         /* disable receipt of more packets on this socket until we've
     604             :            finished with the session setup. This avoids a problem with
     605             :            crashes if we get EOF on the socket while processing a session
     606             :            setup */
     607        1172 :         packet_recv_disable(req->smb_conn->packet);
     608        1172 :         tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
     609             : 
     610        1172 :         return;
     611             : 
     612           0 : nomem:
     613           0 :         status = NT_STATUS_NO_MEMORY;
     614           3 : failed:
     615           3 :         if (is_smb_sess_new) {
     616           0 :                 talloc_free(smb_sess);
     617             :         }
     618           3 :         status = nt_status_squash(status);
     619           3 :         smbsrv_sesssetup_backend_send(req, sess, status);
     620             : }
     621             : 
     622             : /*
     623             :   backend for sessionsetup call - this takes all 3 variants of the call
     624             : */
     625        1196 : void smbsrv_sesssetup_backend(struct smbsrv_request *req,
     626             :                               union smb_sesssetup *sess)
     627             : {
     628        1196 :         switch (sess->old.level) {
     629           4 :                 case RAW_SESSSETUP_OLD:
     630           4 :                         sesssetup_old(req, sess);
     631         103 :                         return;
     632             : 
     633          17 :                 case RAW_SESSSETUP_NT1:
     634          17 :                         sesssetup_nt1(req, sess);
     635          17 :                         return;
     636             : 
     637        1175 :                 case RAW_SESSSETUP_SPNEGO:
     638        1175 :                         sesssetup_spnego(req, sess);
     639        1175 :                         return;
     640             : 
     641           0 :                 case RAW_SESSSETUP_SMB2:
     642           0 :                         break;
     643             :         }
     644             : 
     645           0 :         smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_INVALID_LEVEL);
     646             : }

Generated by: LCOV version 1.13