LCOV - code coverage report
Current view: top level - source4/smb_server/smb - sesssetup.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 254 348 73.0 %
Date: 2024-04-21 15:09:00 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          11 : void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request *req,
      46             :                                                struct auth_session_info *session_info)
      47             : {
      48           0 :         struct tsocket_address *local_address;
      49           0 :         struct tsocket_address *remote_address;
      50          11 :         TALLOC_CTX *frame = talloc_stackframe();
      51             : 
      52          11 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
      53             :                                                 frame);
      54          11 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket,
      55             :                                               frame);
      56             : 
      57          11 :         log_successful_authz_event(req->smb_conn->connection->msg_ctx,
      58          11 :                                    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             :                                    NULL /* client_audit_info */,
      66             :                                    NULL /* server_audit_info */);
      67             : 
      68          11 :         talloc_free(frame);
      69          11 :         return;
      70             : }
      71             : 
      72             : 
      73             : /*
      74             :   setup the OS, Lanman and domain portions of a session setup reply
      75             : */
      76        1150 : static void sesssetup_common_strings(struct smbsrv_request *req,
      77             :                                      char **os, char **lanman, char **domain)
      78             : {
      79        1150 :         (*os) = talloc_asprintf(req, "Unix");
      80        1150 :         (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING);
      81        1150 :         (*domain) = talloc_asprintf(req, "%s", 
      82        1150 :                                     lpcfg_workgroup(req->smb_conn->lp_ctx));
      83        1150 : }
      84             : 
      85        1150 : static void smbsrv_sesssetup_backend_send(struct smbsrv_request *req,
      86             :                                           union smb_sesssetup *sess,
      87             :                                           NTSTATUS status)
      88             : {
      89        1150 :         if (NT_STATUS_IS_OK(status)) {
      90         962 :                 req->smb_conn->negotiate.done_sesssetup = true;
      91             :                 /* we need to keep the session long term */
      92         962 :                 req->session = talloc_steal(req->smb_conn, req->session);
      93             :         }
      94        1150 :         smbsrv_reply_sesssetup_send(req, sess, status);
      95        1150 : }
      96             : 
      97           4 : static void sesssetup_old_send(struct tevent_req *subreq)
      98             : {
      99           4 :         struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
     100           4 :         struct smbsrv_request *req = state->req;
     101             : 
     102           4 :         union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
     103           4 :         struct auth_user_info_dc *user_info_dc = NULL;
     104           0 :         struct auth_session_info *session_info;
     105           0 :         struct smbsrv_session *smb_sess;
     106           0 :         NTSTATUS status;
     107           4 :         uint8_t authoritative = 1;
     108           0 :         uint32_t flags;
     109             : 
     110           4 :         status = auth_check_password_recv(subreq, req, &user_info_dc,
     111             :                                           &authoritative);
     112           4 :         TALLOC_FREE(subreq);
     113           4 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     114             : 
     115           0 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     116           0 :         if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
     117           0 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     118             :         }
     119             :         /* This references user_info_dc into session_info */
     120           0 :         status = req->smb_conn->negotiate.auth_context->generate_session_info(req->smb_conn->negotiate.auth_context,
     121             :                                                                               req,
     122             :                                                                               user_info_dc, sess->old.in.user, 
     123             :                                                                               flags, &session_info);
     124           0 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     125             : 
     126             :         /* allocate a new session */
     127           0 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     128           0 :         if (!smb_sess) {
     129           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     130           0 :                 goto failed;
     131             :         }
     132             : 
     133           0 :         smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
     134             : 
     135             :         /* Ensure this is marked as a 'real' vuid, not one
     136             :          * simply valid for the session setup leg */
     137           0 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     138           0 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     139             : 
     140             :         /* To correctly process any AndX packet (like a tree connect)
     141             :          * we need to fill in the session on the request here */
     142           0 :         req->session = smb_sess;
     143           0 :         sess->old.out.vuid = smb_sess->vuid;
     144             : 
     145           4 : failed:
     146           4 :         status = nt_status_squash(status);
     147           4 :         smbsrv_sesssetup_backend_send(req, sess, status);
     148           4 : }
     149             : 
     150             : /*
     151             :   handler for old style session setup
     152             : */
     153           4 : static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
     154             : {
     155           4 :         struct auth_usersupplied_info *user_info = NULL;
     156           0 :         struct tsocket_address *remote_address, *local_address;
     157           4 :         const char *remote_machine = NULL;
     158           0 :         struct tevent_req *subreq;
     159           0 :         struct sesssetup_context *state;
     160             : 
     161           4 :         sess->old.out.vuid = 0;
     162           4 :         sess->old.out.action = 0;
     163             : 
     164           4 :         sesssetup_common_strings(req, 
     165             :                                  &sess->old.out.os,
     166             :                                  &sess->old.out.lanman,
     167             :                                  &sess->old.out.domain);
     168             : 
     169           4 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     170           4 :                 req->smb_conn->negotiate.max_send = sess->old.in.bufsize;
     171             :         }
     172             : 
     173           4 :         if (req->smb_conn->negotiate.calling_name) {
     174           0 :                 remote_machine = req->smb_conn->negotiate.calling_name->name;
     175             :         }
     176             :         
     177           4 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
     178           4 :         if (!remote_address) goto nomem;
     179             : 
     180           4 :         if (!remote_machine) {
     181           4 :                 remote_machine = tsocket_address_inet_addr_string(remote_address, req);
     182           4 :                 if (!remote_machine) goto nomem;
     183             :         }
     184             : 
     185           4 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
     186           4 :         if (!local_address) goto nomem;
     187             : 
     188           4 :         user_info = talloc_zero(req, struct auth_usersupplied_info);
     189           4 :         if (!user_info) goto nomem;
     190             : 
     191           4 :         user_info->service_description = "SMB";
     192             :         
     193           4 :         user_info->logon_parameters = 0;
     194           4 :         user_info->flags = 0;
     195           4 :         user_info->client.account_name = sess->old.in.user;
     196           4 :         user_info->client.domain_name = sess->old.in.domain;
     197           4 :         user_info->workstation_name = remote_machine;
     198             : 
     199           4 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     200           4 :         user_info->local_host = talloc_steal(user_info, local_address);
     201             :         
     202           4 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     203           4 :         user_info->password.response.lanman = sess->old.in.password;
     204           4 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
     205           4 :         user_info->password.response.nt = data_blob(NULL, 0);
     206             : 
     207           4 :         state = talloc(req, struct sesssetup_context);
     208           4 :         if (!state) goto nomem;
     209             : 
     210           4 :         if (req->smb_conn->negotiate.auth_context) {
     211           4 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     212             :         } else {
     213             :                 /* TODO: should we use just "anonymous" here? */
     214           0 :                 NTSTATUS status = auth_context_create(state,
     215           0 :                                                       req->smb_conn->connection->event.ctx,
     216           0 :                                                       req->smb_conn->connection->msg_ctx,
     217           0 :                                                       req->smb_conn->lp_ctx,
     218             :                                                       &state->auth_context);
     219           0 :                 if (!NT_STATUS_IS_OK(status)) {
     220           0 :                         smbsrv_sesssetup_backend_send(req, sess, status);
     221           0 :                         return;
     222             :                 }
     223             :         }
     224             : 
     225           4 :         state->req = req;
     226             : 
     227           4 :         subreq = auth_check_password_send(state,
     228           4 :                                           req->smb_conn->connection->event.ctx,
     229           4 :                                           req->smb_conn->negotiate.auth_context,
     230             :                                           user_info);
     231           4 :         if (!subreq) goto nomem;
     232           4 :         tevent_req_set_callback(subreq, sesssetup_old_send, state);
     233           4 :         return;
     234             : 
     235           0 : nomem:
     236           0 :         smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
     237             : }
     238             : 
     239          13 : static void sesssetup_nt1_send(struct tevent_req *subreq)
     240             : {
     241          13 :         struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
     242          13 :         struct smbsrv_request *req = state->req;
     243          13 :         union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
     244          13 :         struct auth_user_info_dc *user_info_dc = NULL;
     245           0 :         struct auth_session_info *session_info;
     246           0 :         struct smbsrv_session *smb_sess;
     247          13 :         uint8_t authoritative = 1;
     248           0 :         uint32_t flags;
     249           0 :         NTSTATUS status;
     250             : 
     251          13 :         status = auth_check_password_recv(subreq, req, &user_info_dc,
     252             :                                           &authoritative);
     253          13 :         TALLOC_FREE(subreq);
     254          13 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     255             : 
     256          11 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     257          11 :         if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
     258           7 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     259             :         }
     260             :         /* This references user_info_dc into session_info */
     261          11 :         status = state->auth_context->generate_session_info(state->auth_context,
     262             :                                                             req,
     263             :                                                             user_info_dc,
     264             :                                                             sess->nt1.in.user,
     265             :                                                             flags,
     266             :                                                             &session_info);
     267          11 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     268             : 
     269             :         /* allocate a new session */
     270          11 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     271          11 :         if (!smb_sess) {
     272           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     273           0 :                 goto failed;
     274             :         }
     275             : 
     276          11 :         smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
     277             : 
     278             :         /* Ensure this is marked as a 'real' vuid, not one
     279             :          * simply valid for the session setup leg */
     280          11 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     281          11 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     282             : 
     283             :         /* To correctly process any AndX packet (like a tree connect)
     284             :          * we need to fill in the session on the request here */
     285          11 :         req->session = smb_sess;
     286          11 :         sess->nt1.out.vuid = smb_sess->vuid;
     287             : 
     288          11 :         if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
     289             :                 /* Already signing, or disabled */
     290           1 :                 goto done;
     291             :         }
     292             : 
     293          10 : done:
     294          11 :         status = NT_STATUS_OK;
     295          13 : failed:
     296          13 :         status = nt_status_squash(status);
     297          13 :         smbsrv_sesssetup_backend_send(req, sess, status);
     298          13 : }
     299             : 
     300             : /*
     301             :   handler for NT1 style session setup
     302             : */
     303          13 : static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
     304             : {
     305           0 :         NTSTATUS status;
     306          13 :         struct auth_usersupplied_info *user_info = NULL;
     307           0 :         struct tsocket_address *remote_address, *local_address;
     308          13 :         const char *remote_machine = NULL;
     309           0 :         struct tevent_req *subreq;
     310           0 :         struct sesssetup_context *state;
     311          13 :         bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
     312             : 
     313          13 :         sess->nt1.out.vuid = 0;
     314          13 :         sess->nt1.out.action = 0;
     315             : 
     316          13 :         sesssetup_common_strings(req, 
     317             :                                  &sess->nt1.out.os,
     318             :                                  &sess->nt1.out.lanman,
     319             :                                  &sess->nt1.out.domain);
     320             : 
     321          13 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     322          12 :                 req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
     323          12 :                 req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
     324             :         }
     325             : 
     326          13 :         state = talloc(req, struct sesssetup_context);
     327          13 :         if (!state) goto nomem;
     328             : 
     329          13 :         state->req = req;
     330             : 
     331          13 :         if (req->smb_conn->negotiate.oid) {
     332           2 :                 if (sess->nt1.in.user && *sess->nt1.in.user) {
     333             :                         /* We can't accept a normal login, because we
     334             :                          * don't have a challenge */
     335           0 :                         status = NT_STATUS_LOGON_FAILURE;
     336           0 :                         goto failed;
     337             :                 }
     338             : 
     339             :                 /* TODO: should we use just "anonymous" here? */
     340           2 :                 status = auth_context_create(state,
     341           2 :                                              req->smb_conn->connection->event.ctx,
     342           2 :                                              req->smb_conn->connection->msg_ctx,
     343           2 :                                              req->smb_conn->lp_ctx,
     344             :                                              &state->auth_context);
     345           2 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     346          11 :         } else if (req->smb_conn->negotiate.auth_context) {
     347          11 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     348             :         } else {
     349             :                 /* TODO: should we use just "anonymous" here? */
     350           0 :                 status = auth_context_create(state,
     351           0 :                                              req->smb_conn->connection->event.ctx,
     352           0 :                                              req->smb_conn->connection->msg_ctx,
     353           0 :                                              req->smb_conn->lp_ctx,
     354             :                                              &state->auth_context);
     355           0 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     356             :         }
     357             : 
     358          13 :         if (req->smb_conn->negotiate.calling_name) {
     359           0 :                 remote_machine = req->smb_conn->negotiate.calling_name->name;
     360             :         }
     361             : 
     362          13 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
     363          13 :         if (!remote_address) goto nomem;
     364             : 
     365          13 :         if (!remote_machine) {
     366          13 :                 remote_machine = tsocket_address_inet_addr_string(remote_address, req);
     367          13 :                 if (!remote_machine) goto nomem;
     368             :         }
     369             : 
     370          13 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
     371          13 :         if (!local_address) goto nomem;
     372             : 
     373          13 :         user_info = talloc_zero(req, struct auth_usersupplied_info);
     374          13 :         if (!user_info) goto nomem;
     375             : 
     376          13 :         user_info->service_description = "SMB";
     377          13 :         user_info->auth_description = "bare-NTLM";
     378             : 
     379          13 :         user_info->logon_parameters = 0;
     380          13 :         user_info->flags = 0;
     381          13 :         user_info->client.account_name = sess->nt1.in.user;
     382          13 :         user_info->client.domain_name = sess->nt1.in.domain;
     383          13 :         user_info->workstation_name = remote_machine;
     384          13 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     385          13 :         user_info->local_host = talloc_steal(user_info, local_address);
     386             :         
     387          13 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     388          13 :         user_info->password.response.lanman = sess->nt1.in.password1;
     389          13 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
     390          13 :         user_info->password.response.nt = sess->nt1.in.password2;
     391          13 :         user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
     392             : 
     393          13 :         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          13 :         subreq = auth_check_password_send(state,
     403          13 :                                           req->smb_conn->connection->event.ctx,
     404             :                                           state->auth_context,
     405             :                                           user_info);
     406          13 :         if (!subreq) goto nomem;
     407          13 :         tevent_req_set_callback(subreq, sesssetup_nt1_send, state);
     408             : 
     409          13 :         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        1130 : static void sesssetup_spnego_send(struct tevent_req *subreq)
     425             : {
     426        1130 :         struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq,
     427             :                                            struct sesssetup_spnego_state);
     428        1130 :         struct smbsrv_request *req = s->req;
     429        1130 :         union smb_sesssetup *sess = s->sess;
     430        1130 :         struct smbsrv_session *smb_sess = s->smb_sess;
     431        1130 :         struct auth_session_info *session_info = NULL;
     432           0 :         NTSTATUS status;
     433           0 :         NTSTATUS skey_status;
     434           0 :         DATA_BLOB session_key;
     435             : 
     436        1130 :         status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
     437        1130 :         packet_recv_enable(req->smb_conn->packet);
     438        1130 :         TALLOC_FREE(subreq);
     439        1130 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     440         176 :                 goto done;
     441         954 :         } else if (!NT_STATUS_IS_OK(status)) {
     442           3 :                 goto failed;
     443             :         }
     444             : 
     445         951 :         status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
     446         951 :         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         951 :         skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
     450         951 :         if (NT_STATUS_IS_OK(skey_status)) {
     451         951 :                 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         951 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     457         951 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     458             : 
     459         951 :         req->session = smb_sess;
     460             : 
     461        1127 : done:
     462        1127 :         sess->spnego.out.vuid = smb_sess->vuid;
     463        1130 : failed:
     464        1130 :         status = nt_status_squash(status);
     465        1130 :         smbsrv_sesssetup_backend_send(req, sess, status);
     466        1130 :         if (!NT_STATUS_IS_OK(status) && 
     467         179 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     468           3 :                 talloc_free(smb_sess);
     469             :         }
     470        1130 : }
     471             : 
     472             : /*
     473             :   handler for SPNEGO style session setup
     474             : */
     475        1133 : static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
     476             : {
     477           0 :         NTSTATUS status;
     478        1133 :         struct smbsrv_session *smb_sess = NULL;
     479        1133 :         bool is_smb_sess_new = false;
     480        1133 :         struct sesssetup_spnego_state *s = NULL;
     481           0 :         uint16_t vuid;
     482           0 :         struct tevent_req *subreq;
     483             : 
     484        1133 :         sess->spnego.out.vuid = 0;
     485        1133 :         sess->spnego.out.action = 0;
     486             : 
     487        1133 :         sesssetup_common_strings(req, 
     488             :                                  &sess->spnego.out.os,
     489             :                                  &sess->spnego.out.lanman,
     490             :                                  &sess->spnego.out.workgroup);
     491             : 
     492        1133 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     493        1091 :                 req->smb_conn->negotiate.max_send = sess->spnego.in.bufsize;
     494        1091 :                 req->smb_conn->negotiate.client_caps = sess->spnego.in.capabilities;
     495             :         }
     496             : 
     497        1133 :         vuid = SVAL(req->in.hdr,HDR_UID);
     498             : 
     499             :         /* lookup an existing session */
     500        1133 :         if (vuid == 0) {
     501           0 :                 struct gensec_security *gensec_ctx;
     502           0 :                 struct tsocket_address *remote_address, *local_address;
     503         954 :                 status = samba_server_gensec_start(req,
     504         954 :                                                    req->smb_conn->connection->event.ctx,
     505         954 :                                                    req->smb_conn->connection->msg_ctx,
     506         954 :                                                    req->smb_conn->lp_ctx,
     507         954 :                                                    req->smb_conn->negotiate.server_credentials,
     508             :                                                    "cifs",
     509             :                                                    &gensec_ctx);
     510         954 :                 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         954 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
     516         954 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
     517             : 
     518         954 :                 remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
     519             :                                                         req);
     520         954 :                 if (!remote_address) {
     521           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     522           0 :                         DBG_ERR("Failed to obtain remote address\n");
     523           0 :                         goto failed;
     524             :                 }
     525             : 
     526         954 :                 status = gensec_set_remote_address(gensec_ctx,
     527             :                                                    remote_address);
     528         954 :                 if (!NT_STATUS_IS_OK(status)) {
     529           0 :                         DBG_ERR("Failed to set remote address\n");
     530           0 :                         goto failed;
     531             :                 }
     532             : 
     533         954 :                 local_address = socket_get_local_addr(req->smb_conn->connection->socket,
     534             :                                                         req);
     535         954 :                 if (!local_address) {
     536           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     537           0 :                         DBG_ERR("Failed to obtain local address\n");
     538           0 :                         goto failed;
     539             :                 }
     540             : 
     541         954 :                 status = gensec_set_local_address(gensec_ctx,
     542             :                                                    local_address);
     543         954 :                 if (!NT_STATUS_IS_OK(status)) {
     544           0 :                         DBG_ERR("Failed to set local address\n");
     545           0 :                         goto failed;
     546             :                 }
     547             : 
     548         954 :                 status = gensec_set_target_service_description(gensec_ctx,
     549             :                                                                "SMB");
     550             : 
     551         954 :                 if (!NT_STATUS_IS_OK(status)) {
     552           0 :                         DBG_ERR("Failed to set service description\n");
     553           0 :                         goto failed;
     554             :                 }
     555             : 
     556         954 :                 status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
     557         954 :                 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         954 :                 smb_sess = smbsrv_session_new(req->smb_conn, req->smb_conn, gensec_ctx);
     565         954 :                 if (!smb_sess) {
     566           0 :                         status = NT_STATUS_INSUFFICIENT_RESOURCES;
     567           0 :                         goto failed;
     568             :                 }
     569         954 :                 is_smb_sess_new = true;
     570             :         } else {
     571         179 :                 smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
     572             :         }
     573             : 
     574        1133 :         if (!smb_sess) {
     575           1 :                 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
     576           1 :                 goto failed;
     577             :         }
     578             : 
     579        1132 :         if (smb_sess->session_info) {
     580           2 :                 status = NT_STATUS_INVALID_PARAMETER;
     581           2 :                 goto failed;
     582             :         }
     583             : 
     584        1130 :         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        1130 :         s = talloc(req, struct sesssetup_spnego_state);
     591        1130 :         if (!s) goto nomem;
     592        1130 :         s->req               = req;
     593        1130 :         s->sess              = sess;
     594        1130 :         s->smb_sess  = smb_sess;
     595             : 
     596        1130 :         subreq = gensec_update_send(s,
     597        1130 :                                     req->smb_conn->connection->event.ctx,
     598             :                                     smb_sess->gensec_ctx,
     599             :                                     sess->spnego.in.secblob);
     600        1130 :         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        1130 :         packet_recv_disable(req->smb_conn->packet);
     608        1130 :         tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
     609             : 
     610        1130 :         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        1150 : void smbsrv_sesssetup_backend(struct smbsrv_request *req,
     626             :                               union smb_sesssetup *sess)
     627             : {
     628        1150 :         switch (sess->old.level) {
     629           4 :                 case RAW_SESSSETUP_OLD:
     630           4 :                         sesssetup_old(req, sess);
     631        1150 :                         return;
     632             : 
     633          13 :                 case RAW_SESSSETUP_NT1:
     634          13 :                         sesssetup_nt1(req, sess);
     635          13 :                         return;
     636             : 
     637        1133 :                 case RAW_SESSSETUP_SPNEGO:
     638        1133 :                         sesssetup_spnego(req, sess);
     639        1133 :                         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.14