LCOV - code coverage report
Current view: top level - source4/smb_server/smb - sesssetup.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 254 323 78.6 %
Date: 2024-06-13 04:01:37 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          13 : 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          13 :         TALLOC_CTX *frame = talloc_stackframe();
      51             : 
      52          13 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
      53             :                                                 frame);
      54          13 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket,
      55             :                                               frame);
      56             : 
      57          13 :         log_successful_authz_event(req->smb_conn->connection->msg_ctx,
      58          13 :                                    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          13 :         talloc_free(frame);
      67          13 :         return;
      68             : }
      69             : 
      70             : 
      71             : /*
      72             :   setup the OS, Lanman and domain portions of a session setup reply
      73             : */
      74        1177 : static void sesssetup_common_strings(struct smbsrv_request *req,
      75             :                                      char **os, char **lanman, char **domain)
      76             : {
      77        1177 :         (*os) = talloc_asprintf(req, "Unix");
      78        1177 :         (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING);
      79        1177 :         (*domain) = talloc_asprintf(req, "%s", 
      80        1177 :                                     lpcfg_workgroup(req->smb_conn->lp_ctx));
      81        1177 : }
      82             : 
      83        1177 : static void smbsrv_sesssetup_backend_send(struct smbsrv_request *req,
      84             :                                           union smb_sesssetup *sess,
      85             :                                           NTSTATUS status)
      86             : {
      87        1177 :         if (NT_STATUS_IS_OK(status)) {
      88         986 :                 req->smb_conn->negotiate.done_sesssetup = true;
      89             :                 /* we need to keep the session long term */
      90         986 :                 req->session = talloc_steal(req->smb_conn, req->session);
      91             :         }
      92        1177 :         smbsrv_reply_sesssetup_send(req, sess, status);
      93        1177 : }
      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 = 1;
     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           0 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     114           0 :         if (user_info_dc->info->authenticated) {
     115           0 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     116             :         }
     117             :         /* This references user_info_dc into session_info */
     118           0 :         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           0 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     123             : 
     124             :         /* allocate a new session */
     125           0 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     126           0 :         if (!smb_sess) {
     127           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     128           0 :                 goto failed;
     129             :         }
     130             : 
     131           0 :         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           0 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     136           0 :         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           0 :         req->session = smb_sess;
     141           0 :         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->logon_parameters = 0;
     192           4 :         user_info->flags = 0;
     193           4 :         user_info->client.account_name = sess->old.in.user;
     194           4 :         user_info->client.domain_name = sess->old.in.domain;
     195           4 :         user_info->workstation_name = remote_machine;
     196             : 
     197           4 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     198           4 :         user_info->local_host = talloc_steal(user_info, local_address);
     199             :         
     200           4 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     201           4 :         user_info->password.response.lanman = sess->old.in.password;
     202           4 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
     203           4 :         user_info->password.response.nt = data_blob(NULL, 0);
     204             : 
     205           4 :         state = talloc(req, struct sesssetup_context);
     206           4 :         if (!state) goto nomem;
     207             : 
     208           4 :         if (req->smb_conn->negotiate.auth_context) {
     209           4 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     210             :         } else {
     211             :                 /* TODO: should we use just "anonymous" here? */
     212           0 :                 NTSTATUS status = auth_context_create(state,
     213           0 :                                                       req->smb_conn->connection->event.ctx,
     214           0 :                                                       req->smb_conn->connection->msg_ctx,
     215           0 :                                                       req->smb_conn->lp_ctx,
     216             :                                                       &state->auth_context);
     217           0 :                 if (!NT_STATUS_IS_OK(status)) {
     218           0 :                         smbsrv_sesssetup_backend_send(req, sess, status);
     219           0 :                         return;
     220             :                 }
     221             :         }
     222             : 
     223           4 :         state->req = req;
     224             : 
     225           6 :         subreq = auth_check_password_send(state,
     226           4 :                                           req->smb_conn->connection->event.ctx,
     227           4 :                                           req->smb_conn->negotiate.auth_context,
     228             :                                           user_info);
     229           4 :         if (!subreq) goto nomem;
     230           4 :         tevent_req_set_callback(subreq, sesssetup_old_send, state);
     231           4 :         return;
     232             : 
     233           0 : nomem:
     234           0 :         smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
     235             : }
     236             : 
     237          15 : static void sesssetup_nt1_send(struct tevent_req *subreq)
     238             : {
     239          15 :         struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
     240          15 :         struct smbsrv_request *req = state->req;
     241          15 :         union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
     242          15 :         struct auth_user_info_dc *user_info_dc = NULL;
     243             :         struct auth_session_info *session_info;
     244             :         struct smbsrv_session *smb_sess;
     245          15 :         uint8_t authoritative = 1;
     246             :         uint32_t flags;
     247             :         NTSTATUS status;
     248             : 
     249          15 :         status = auth_check_password_recv(subreq, req, &user_info_dc,
     250             :                                           &authoritative);
     251          15 :         TALLOC_FREE(subreq);
     252          15 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     253             : 
     254          13 :         flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
     255          13 :         if (user_info_dc->info->authenticated) {
     256           8 :                 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
     257             :         }
     258             :         /* This references user_info_dc into session_info */
     259          13 :         status = state->auth_context->generate_session_info(state->auth_context,
     260             :                                                             req,
     261             :                                                             user_info_dc,
     262             :                                                             sess->nt1.in.user,
     263             :                                                             flags,
     264             :                                                             &session_info);
     265          13 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     266             : 
     267             :         /* allocate a new session */
     268          13 :         smb_sess = smbsrv_session_new(req->smb_conn, req, NULL);
     269          13 :         if (!smb_sess) {
     270           0 :                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
     271           0 :                 goto failed;
     272             :         }
     273             : 
     274          13 :         smbsrv_not_spengo_sesssetup_authz_log(req, session_info);
     275             : 
     276             :         /* Ensure this is marked as a 'real' vuid, not one
     277             :          * simply valid for the session setup leg */
     278          13 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     279          13 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     280             : 
     281             :         /* To correctly process any AndX packet (like a tree connect)
     282             :          * we need to fill in the session on the request here */
     283          13 :         req->session = smb_sess;
     284          13 :         sess->nt1.out.vuid = smb_sess->vuid;
     285             : 
     286          13 :         if (!smbsrv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
     287             :                 /* Already signing, or disabled */
     288           1 :                 goto done;
     289             :         }
     290             : 
     291          22 : done:
     292          13 :         status = NT_STATUS_OK;
     293          15 : failed:
     294          15 :         status = nt_status_squash(status);
     295          15 :         smbsrv_sesssetup_backend_send(req, sess, status);
     296          15 : }
     297             : 
     298             : /*
     299             :   handler for NT1 style session setup
     300             : */
     301          15 : static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
     302             : {
     303             :         NTSTATUS status;
     304          15 :         struct auth_usersupplied_info *user_info = NULL;
     305             :         struct tsocket_address *remote_address, *local_address;
     306          15 :         const char *remote_machine = NULL;
     307             :         struct tevent_req *subreq;
     308             :         struct sesssetup_context *state;
     309          15 :         bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
     310             : 
     311          15 :         sess->nt1.out.vuid = 0;
     312          15 :         sess->nt1.out.action = 0;
     313             : 
     314          15 :         sesssetup_common_strings(req, 
     315             :                                  &sess->nt1.out.os,
     316             :                                  &sess->nt1.out.lanman,
     317             :                                  &sess->nt1.out.domain);
     318             : 
     319          15 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     320          14 :                 req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
     321          14 :                 req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
     322             :         }
     323             : 
     324          15 :         state = talloc(req, struct sesssetup_context);
     325          15 :         if (!state) goto nomem;
     326             : 
     327          15 :         state->req = req;
     328             : 
     329          15 :         if (req->smb_conn->negotiate.oid) {
     330           2 :                 if (sess->nt1.in.user && *sess->nt1.in.user) {
     331             :                         /* We can't accept a normal login, because we
     332             :                          * don't have a challenge */
     333           0 :                         status = NT_STATUS_LOGON_FAILURE;
     334           0 :                         goto failed;
     335             :                 }
     336             : 
     337             :                 /* TODO: should we use just "anonymous" here? */
     338           8 :                 status = auth_context_create(state,
     339           2 :                                              req->smb_conn->connection->event.ctx,
     340           2 :                                              req->smb_conn->connection->msg_ctx,
     341           2 :                                              req->smb_conn->lp_ctx,
     342             :                                              &state->auth_context);
     343           2 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     344          13 :         } else if (req->smb_conn->negotiate.auth_context) {
     345          13 :                 state->auth_context = req->smb_conn->negotiate.auth_context;
     346             :         } else {
     347             :                 /* TODO: should we use just "anonymous" here? */
     348           0 :                 status = auth_context_create(state,
     349           0 :                                              req->smb_conn->connection->event.ctx,
     350           0 :                                              req->smb_conn->connection->msg_ctx,
     351           0 :                                              req->smb_conn->lp_ctx,
     352             :                                              &state->auth_context);
     353           0 :                 if (!NT_STATUS_IS_OK(status)) goto failed;
     354             :         }
     355             : 
     356          15 :         if (req->smb_conn->negotiate.calling_name) {
     357           0 :                 remote_machine = req->smb_conn->negotiate.calling_name->name;
     358             :         }
     359             : 
     360          15 :         remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
     361          15 :         if (!remote_address) goto nomem;
     362             : 
     363          15 :         if (!remote_machine) {
     364          15 :                 remote_machine = tsocket_address_inet_addr_string(remote_address, req);
     365          15 :                 if (!remote_machine) goto nomem;
     366             :         }
     367             : 
     368          15 :         local_address = socket_get_local_addr(req->smb_conn->connection->socket, req);
     369          15 :         if (!local_address) goto nomem;
     370             : 
     371          15 :         user_info = talloc_zero(req, struct auth_usersupplied_info);
     372          15 :         if (!user_info) goto nomem;
     373             : 
     374          15 :         user_info->service_description = "SMB";
     375          15 :         user_info->auth_description = "bare-NTLM";
     376             : 
     377          15 :         user_info->logon_parameters = 0;
     378          15 :         user_info->flags = 0;
     379          15 :         user_info->client.account_name = sess->nt1.in.user;
     380          15 :         user_info->client.domain_name = sess->nt1.in.domain;
     381          15 :         user_info->workstation_name = remote_machine;
     382          15 :         user_info->remote_host = talloc_steal(user_info, remote_address);
     383          15 :         user_info->local_host = talloc_steal(user_info, local_address);
     384             :         
     385          15 :         user_info->password_state = AUTH_PASSWORD_RESPONSE;
     386          15 :         user_info->password.response.lanman = sess->nt1.in.password1;
     387          15 :         user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
     388          15 :         user_info->password.response.nt = sess->nt1.in.password2;
     389          15 :         user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
     390             : 
     391          15 :         if (!allow_raw && user_info->password.response.nt.length >= 48) {
     392             :                 /*
     393             :                  * NTLMv2_RESPONSE has at least 48 bytes
     394             :                  * and should only be supported via NTLMSSP.
     395             :                  */
     396           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     397           0 :                 goto failed;
     398             :         }
     399             : 
     400          27 :         subreq = auth_check_password_send(state,
     401          15 :                                           req->smb_conn->connection->event.ctx,
     402             :                                           state->auth_context,
     403             :                                           user_info);
     404          15 :         if (!subreq) goto nomem;
     405          15 :         tevent_req_set_callback(subreq, sesssetup_nt1_send, state);
     406             : 
     407          15 :         return;
     408             : 
     409           0 : nomem:
     410           0 :         status = NT_STATUS_NO_MEMORY;
     411           0 : failed:
     412           0 :         status = nt_status_squash(status);
     413           0 :         smbsrv_sesssetup_backend_send(req, sess, status);
     414             : }
     415             : 
     416             : struct sesssetup_spnego_state {
     417             :         struct smbsrv_request *req;
     418             :         union smb_sesssetup *sess;
     419             :         struct smbsrv_session *smb_sess;
     420             : };
     421             : 
     422        1155 : static void sesssetup_spnego_send(struct tevent_req *subreq)
     423             : {
     424        1155 :         struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq,
     425             :                                            struct sesssetup_spnego_state);
     426        1155 :         struct smbsrv_request *req = s->req;
     427        1155 :         union smb_sesssetup *sess = s->sess;
     428        1155 :         struct smbsrv_session *smb_sess = s->smb_sess;
     429        1155 :         struct auth_session_info *session_info = NULL;
     430             :         NTSTATUS status;
     431             :         NTSTATUS skey_status;
     432             :         DATA_BLOB session_key;
     433             : 
     434        1155 :         status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
     435        1155 :         packet_recv_enable(req->smb_conn->packet);
     436        1155 :         TALLOC_FREE(subreq);
     437        1155 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     438         178 :                 goto done;
     439         977 :         } else if (!NT_STATUS_IS_OK(status)) {
     440           4 :                 goto failed;
     441             :         }
     442             : 
     443         973 :         status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
     444         973 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     445             : 
     446             :         /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
     447         973 :         skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
     448         973 :         if (NT_STATUS_IS_OK(skey_status)) {
     449         973 :                 smbsrv_setup_signing(req->smb_conn, &session_key, NULL);
     450             :         }
     451             : 
     452             :         /* Ensure this is marked as a 'real' vuid, not one
     453             :          * simply valid for the session setup leg */
     454         973 :         status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
     455         973 :         if (!NT_STATUS_IS_OK(status)) goto failed;
     456             : 
     457         973 :         req->session = smb_sess;
     458             : 
     459        1151 : done:
     460        1151 :         sess->spnego.out.vuid = smb_sess->vuid;
     461        1155 : failed:
     462        1155 :         status = nt_status_squash(status);
     463        1155 :         smbsrv_sesssetup_backend_send(req, sess, status);
     464        1293 :         if (!NT_STATUS_IS_OK(status) && 
     465         182 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     466           4 :                 talloc_free(smb_sess);
     467             :         }
     468        1155 : }
     469             : 
     470             : /*
     471             :   handler for SPNEGO style session setup
     472             : */
     473        1158 : static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
     474             : {
     475             :         NTSTATUS status;
     476        1158 :         struct smbsrv_session *smb_sess = NULL;
     477        1158 :         bool is_smb_sess_new = false;
     478        1158 :         struct sesssetup_spnego_state *s = NULL;
     479             :         uint16_t vuid;
     480             :         struct tevent_req *subreq;
     481             : 
     482        1158 :         sess->spnego.out.vuid = 0;
     483        1158 :         sess->spnego.out.action = 0;
     484             : 
     485        1158 :         sesssetup_common_strings(req, 
     486             :                                  &sess->spnego.out.os,
     487             :                                  &sess->spnego.out.lanman,
     488             :                                  &sess->spnego.out.workgroup);
     489             : 
     490        1158 :         if (!req->smb_conn->negotiate.done_sesssetup) {
     491        1116 :                 req->smb_conn->negotiate.max_send = sess->spnego.in.bufsize;
     492        1116 :                 req->smb_conn->negotiate.client_caps = sess->spnego.in.capabilities;
     493             :         }
     494             : 
     495        1158 :         vuid = SVAL(req->in.hdr,HDR_UID);
     496             : 
     497             :         /* lookup an existing session */
     498        1158 :         if (vuid == 0) {
     499             :                 struct gensec_security *gensec_ctx;
     500             :                 struct tsocket_address *remote_address, *local_address;
     501        3776 :                 status = samba_server_gensec_start(req,
     502         977 :                                                    req->smb_conn->connection->event.ctx,
     503         977 :                                                    req->smb_conn->connection->msg_ctx,
     504         977 :                                                    req->smb_conn->lp_ctx,
     505         977 :                                                    req->smb_conn->negotiate.server_credentials,
     506             :                                                    "cifs",
     507             :                                                    &gensec_ctx);
     508         977 :                 if (!NT_STATUS_IS_OK(status)) {
     509           0 :                         DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
     510           0 :                         goto failed;
     511             :                 }
     512             : 
     513         977 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
     514         977 :                 gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SMB_TRANSPORT);
     515             : 
     516         977 :                 remote_address = socket_get_remote_addr(req->smb_conn->connection->socket,
     517             :                                                         req);
     518         977 :                 if (!remote_address) {
     519           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     520           0 :                         DBG_ERR("Failed to obtain remote address");
     521           0 :                         goto failed;
     522             :                 }
     523             : 
     524         977 :                 status = gensec_set_remote_address(gensec_ctx,
     525             :                                                    remote_address);
     526         977 :                 if (!NT_STATUS_IS_OK(status)) {
     527           0 :                         DBG_ERR("Failed to set remote address");
     528           0 :                         goto failed;
     529             :                 }
     530             : 
     531         977 :                 local_address = socket_get_local_addr(req->smb_conn->connection->socket,
     532             :                                                         req);
     533         977 :                 if (!local_address) {
     534           0 :                         status = NT_STATUS_INTERNAL_ERROR;
     535           0 :                         DBG_ERR("Failed to obtain local address");
     536           0 :                         goto failed;
     537             :                 }
     538             : 
     539         977 :                 status = gensec_set_local_address(gensec_ctx,
     540             :                                                    local_address);
     541         977 :                 if (!NT_STATUS_IS_OK(status)) {
     542           0 :                         DBG_ERR("Failed to set local address");
     543           0 :                         goto failed;
     544             :                 }
     545             : 
     546         977 :                 status = gensec_set_target_service_description(gensec_ctx,
     547             :                                                                "SMB");
     548             : 
     549         977 :                 if (!NT_STATUS_IS_OK(status)) {
     550           0 :                         DBG_ERR("Failed to set service description");
     551           0 :                         goto failed;
     552             :                 }
     553             : 
     554         977 :                 status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
     555         977 :                 if (!NT_STATUS_IS_OK(status)) {
     556           0 :                         DEBUG(1, ("Failed to start GENSEC %s server code: %s\n", 
     557             :                                   gensec_get_name_by_oid(gensec_ctx, req->smb_conn->negotiate.oid), nt_errstr(status)));
     558           0 :                         goto failed;
     559             :                 }
     560             : 
     561             :                 /* allocate a new session */
     562         977 :                 smb_sess = smbsrv_session_new(req->smb_conn, req->smb_conn, gensec_ctx);
     563         977 :                 if (!smb_sess) {
     564           0 :                         status = NT_STATUS_INSUFFICIENT_RESOURCES;
     565           0 :                         goto failed;
     566             :                 }
     567         977 :                 is_smb_sess_new = true;
     568             :         } else {
     569         181 :                 smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
     570             :         }
     571             : 
     572        1158 :         if (!smb_sess) {
     573           1 :                 status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
     574           1 :                 goto failed;
     575             :         }
     576             : 
     577        1157 :         if (smb_sess->session_info) {
     578           2 :                 status = NT_STATUS_INVALID_PARAMETER;
     579           2 :                 goto failed;
     580             :         }
     581             : 
     582        1155 :         if (!smb_sess->gensec_ctx) {
     583           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     584           0 :                 DEBUG(1, ("Internal ERROR: no gensec_ctx on session: %s\n", nt_errstr(status)));
     585           0 :                 goto failed;
     586             :         }
     587             : 
     588        1155 :         s = talloc(req, struct sesssetup_spnego_state);
     589        1155 :         if (!s) goto nomem;
     590        1155 :         s->req               = req;
     591        1155 :         s->sess              = sess;
     592        1155 :         s->smb_sess  = smb_sess;
     593             : 
     594        2223 :         subreq = gensec_update_send(s,
     595        1155 :                                     req->smb_conn->connection->event.ctx,
     596             :                                     smb_sess->gensec_ctx,
     597             :                                     sess->spnego.in.secblob);
     598        1155 :         if (!subreq) {
     599           0 :                 goto nomem;
     600             :         }
     601             :         /* disable receipt of more packets on this socket until we've
     602             :            finished with the session setup. This avoids a problem with
     603             :            crashes if we get EOF on the socket while processing a session
     604             :            setup */
     605        1155 :         packet_recv_disable(req->smb_conn->packet);
     606        1155 :         tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
     607             : 
     608        1155 :         return;
     609             : 
     610           0 : nomem:
     611           0 :         status = NT_STATUS_NO_MEMORY;
     612           3 : failed:
     613           3 :         if (is_smb_sess_new) {
     614           0 :                 talloc_free(smb_sess);
     615             :         }
     616           3 :         status = nt_status_squash(status);
     617           3 :         smbsrv_sesssetup_backend_send(req, sess, status);
     618             : }
     619             : 
     620             : /*
     621             :   backend for sessionsetup call - this takes all 3 variants of the call
     622             : */
     623        1177 : void smbsrv_sesssetup_backend(struct smbsrv_request *req,
     624             :                               union smb_sesssetup *sess)
     625             : {
     626        1177 :         switch (sess->old.level) {
     627           4 :                 case RAW_SESSSETUP_OLD:
     628           4 :                         sesssetup_old(req, sess);
     629          94 :                         return;
     630             : 
     631          15 :                 case RAW_SESSSETUP_NT1:
     632          15 :                         sesssetup_nt1(req, sess);
     633          15 :                         return;
     634             : 
     635        1158 :                 case RAW_SESSSETUP_SPNEGO:
     636        1158 :                         sesssetup_spnego(req, sess);
     637        1158 :                         return;
     638             : 
     639           0 :                 case RAW_SESSSETUP_SMB2:
     640           0 :                         break;
     641             :         }
     642             : 
     643           0 :         smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_INVALID_LEVEL);
     644             : }

Generated by: LCOV version 1.13