LCOV - code coverage report
Current view: top level - source3/smbd - smb2_server.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1252 2163 57.9 %
Date: 2024-06-13 04:01:37 Functions: 49 76 64.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             :    Copyright (C) Jeremy Allison 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/network.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "smbd/smbXsrv_open.h"
      27             : #include "lib/param/param.h"
      28             : #include "../libcli/smb/smb_common.h"
      29             : #include "../lib/tsocket/tsocket.h"
      30             : #include "../lib/util/tevent_ntstatus.h"
      31             : #include "smbprofile.h"
      32             : #include "../lib/util/bitmap.h"
      33             : #include "../librpc/gen_ndr/krb5pac.h"
      34             : #include "lib/util/iov_buf.h"
      35             : #include "auth.h"
      36             : #include "libcli/smb/smbXcli_base.h"
      37             : #include "source3/lib/substitute.h"
      38             : 
      39             : #if defined(LINUX)
      40             : /* SIOCOUTQ TIOCOUTQ are the same */
      41             : #define __IOCTL_SEND_QUEUE_SIZE_OPCODE TIOCOUTQ
      42             : #define __HAVE_TCP_INFO_RTO 1
      43             : #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
      44             : #elif defined(FREEBSD)
      45             : #define __IOCTL_SEND_QUEUE_SIZE_OPCODE FIONWRITE
      46             : #define __HAVE_TCP_INFO_RTO 1
      47             : #define __ALLOW_MULTI_CHANNEL_SUPPORT 1
      48             : #endif
      49             : 
      50             : #include "lib/crypto/gnutls_helpers.h"
      51             : #include <gnutls/gnutls.h>
      52             : #include <gnutls/crypto.h>
      53             : 
      54             : #undef DBGC_CLASS
      55             : #define DBGC_CLASS DBGC_SMB2
      56             : 
      57             : static void smbd_smb2_connection_handler(struct tevent_context *ev,
      58             :                                          struct tevent_fd *fde,
      59             :                                          uint16_t flags,
      60             :                                          void *private_data);
      61             : static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn);
      62             : 
      63             : static const struct smbd_smb2_dispatch_table {
      64             :         uint16_t opcode;
      65             :         const char *name;
      66             :         bool need_session;
      67             :         bool need_tcon;
      68             :         bool as_root;
      69             :         uint16_t fileid_ofs;
      70             :         bool modify;
      71             : } smbd_smb2_table[] = {
      72             : #define _OP(o) .opcode = o, .name = #o
      73             :         {
      74             :                 _OP(SMB2_OP_NEGPROT),
      75             :                 .as_root = true,
      76             :         },{
      77             :                 _OP(SMB2_OP_SESSSETUP),
      78             :                 .as_root = true,
      79             :         },{
      80             :                 _OP(SMB2_OP_LOGOFF),
      81             :                 .need_session = true,
      82             :                 .as_root = true,
      83             :         },{
      84             :                 _OP(SMB2_OP_TCON),
      85             :                 .need_session = true,
      86             :                 /*
      87             :                  * This call needs to be run as root.
      88             :                  *
      89             :                  * smbd_smb2_request_process_tcon()
      90             :                  * calls make_connection_snum(), which will call
      91             :                  * change_to_user(), when needed.
      92             :                  */
      93             :                 .as_root = true,
      94             :         },{
      95             :                 _OP(SMB2_OP_TDIS),
      96             :                 .need_session = true,
      97             :                 .need_tcon = true,
      98             :                 .as_root = true,
      99             :         },{
     100             :                 _OP(SMB2_OP_CREATE),
     101             :                 .need_session = true,
     102             :                 .need_tcon = true,
     103             :         },{
     104             :                 _OP(SMB2_OP_CLOSE),
     105             :                 .need_session = true,
     106             :                 .need_tcon = true,
     107             :                 .fileid_ofs = 0x08,
     108             :         },{
     109             :                 _OP(SMB2_OP_FLUSH),
     110             :                 .need_session = true,
     111             :                 .need_tcon = true,
     112             :                 .fileid_ofs = 0x08,
     113             :         },{
     114             :                 _OP(SMB2_OP_READ),
     115             :                 .need_session = true,
     116             :                 .need_tcon = true,
     117             :                 .fileid_ofs = 0x10,
     118             :         },{
     119             :                 _OP(SMB2_OP_WRITE),
     120             :                 .need_session = true,
     121             :                 .need_tcon = true,
     122             :                 .fileid_ofs = 0x10,
     123             :                 .modify = true,
     124             :         },{
     125             :                 _OP(SMB2_OP_LOCK),
     126             :                 .need_session = true,
     127             :                 .need_tcon = true,
     128             :                 .fileid_ofs = 0x08,
     129             :         },{
     130             :                 _OP(SMB2_OP_IOCTL),
     131             :                 .need_session = true,
     132             :                 .need_tcon = true,
     133             :                 .fileid_ofs = 0x08,
     134             :                 .modify = true,
     135             :         },{
     136             :                 _OP(SMB2_OP_CANCEL),
     137             :                 .as_root = true,
     138             :         },{
     139             :                 _OP(SMB2_OP_KEEPALIVE),
     140             :                 .as_root = true,
     141             :         },{
     142             :                 _OP(SMB2_OP_QUERY_DIRECTORY),
     143             :                 .need_session = true,
     144             :                 .need_tcon = true,
     145             :                 .fileid_ofs = 0x08,
     146             :         },{
     147             :                 _OP(SMB2_OP_NOTIFY),
     148             :                 .need_session = true,
     149             :                 .need_tcon = true,
     150             :                 .fileid_ofs = 0x08,
     151             :         },{
     152             :                 _OP(SMB2_OP_GETINFO),
     153             :                 .need_session = true,
     154             :                 .need_tcon = true,
     155             :                 .fileid_ofs = 0x18,
     156             :         },{
     157             :                 _OP(SMB2_OP_SETINFO),
     158             :                 .need_session = true,
     159             :                 .need_tcon = true,
     160             :                 .fileid_ofs = 0x10,
     161             :                 .modify = true,
     162             :         },{
     163             :                 _OP(SMB2_OP_BREAK),
     164             :                 .need_session = true,
     165             :                 .need_tcon = true,
     166             :                 /*
     167             :                  * we do not set
     168             :                  * .fileid_ofs here
     169             :                  * as LEASE breaks does not
     170             :                  * have a file id
     171             :                  */
     172             :         }
     173             : };
     174             : 
     175           0 : const char *smb2_opcode_name(uint16_t opcode)
     176             : {
     177           0 :         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
     178           0 :                 return "Bad SMB2 opcode";
     179             :         }
     180           0 :         return smbd_smb2_table[opcode].name;
     181             : }
     182             : 
     183      157044 : static const struct smbd_smb2_dispatch_table *smbd_smb2_call(uint16_t opcode)
     184             : {
     185      157044 :         const struct smbd_smb2_dispatch_table *ret = NULL;
     186             : 
     187      157044 :         if (opcode >= ARRAY_SIZE(smbd_smb2_table)) {
     188           0 :                 return NULL;
     189             :         }
     190             : 
     191      157044 :         ret = &smbd_smb2_table[opcode];
     192             : 
     193      157044 :         SMB_ASSERT(ret->opcode == opcode);
     194             : 
     195      157044 :         return ret;
     196             : }
     197             : 
     198           0 : static void print_req_vectors(const struct smbd_smb2_request *req)
     199             : {
     200             :         int i;
     201             : 
     202           0 :         for (i = 0; i < req->in.vector_count; i++) {
     203           0 :                 dbgtext("\treq->in.vector[%u].iov_len = %u\n",
     204             :                         (unsigned int)i,
     205           0 :                         (unsigned int)req->in.vector[i].iov_len);
     206             :         }
     207           0 :         for (i = 0; i < req->out.vector_count; i++) {
     208           0 :                 dbgtext("\treq->out.vector[%u].iov_len = %u\n",
     209             :                         (unsigned int)i,
     210           0 :                         (unsigned int)req->out.vector[i].iov_len);
     211             :         }
     212           0 : }
     213             : 
     214        1817 : bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
     215             : {
     216        1817 :         if (size < (4 + SMB2_HDR_BODY)) {
     217          18 :                 return false;
     218             :         }
     219             : 
     220        1799 :         if (IVAL(inbuf, 4) != SMB2_MAGIC) {
     221         118 :                 return false;
     222             :         }
     223             : 
     224        1681 :         return true;
     225             : }
     226             : 
     227        2577 : bool smbd_smb2_is_compound(const struct smbd_smb2_request *req)
     228             : {
     229        2577 :         return req->in.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ);
     230             : }
     231             : 
     232           0 : bool smbd_smb2_is_last_in_compound(const struct smbd_smb2_request *req)
     233             : {
     234           0 :         return (req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ ==
     235           0 :                 req->in.vector_count);
     236             : }
     237             : 
     238        5052 : static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn,
     239             :                                      uint64_t expected_seq_low)
     240             : {
     241             :         int rc;
     242             : 
     243        5052 :         xconn->smb2.credits.seq_low = expected_seq_low;
     244        5052 :         xconn->smb2.credits.seq_range = 1;
     245        5052 :         xconn->smb2.credits.granted = 1;
     246        5052 :         xconn->smb2.credits.max = lp_smb2_max_credits();
     247        6601 :         xconn->smb2.credits.bitmap = bitmap_talloc(xconn,
     248        5052 :                                                    xconn->smb2.credits.max);
     249        5052 :         if (xconn->smb2.credits.bitmap == NULL) {
     250           0 :                 return NT_STATUS_NO_MEMORY;
     251             :         }
     252             : 
     253        5052 :         tevent_fd_set_close_fn(xconn->transport.fde, NULL);
     254        5052 :         TALLOC_FREE(xconn->transport.fde);
     255             : 
     256        5052 :         xconn->transport.fde = tevent_add_fd(
     257             :                                         xconn->client->raw_ev_ctx,
     258             :                                         xconn,
     259             :                                         xconn->transport.sock,
     260             :                                         TEVENT_FD_READ,
     261             :                                         smbd_smb2_connection_handler,
     262             :                                         xconn);
     263        5052 :         if (xconn->transport.fde == NULL) {
     264           0 :                 close(xconn->transport.sock);
     265           0 :                 xconn->transport.sock = -1;
     266           0 :                 return NT_STATUS_NO_MEMORY;
     267             :         }
     268        5052 :         tevent_fd_set_auto_close(xconn->transport.fde);
     269             : 
     270             :         /* Ensure child is set to non-blocking mode */
     271        5052 :         rc = set_blocking(xconn->transport.sock, false);
     272        5052 :         if (rc < 0) {
     273           0 :                 return NT_STATUS_INTERNAL_ERROR;
     274             :         }
     275             : 
     276        5052 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279             : #define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
     280             : #define _smb2_setlen(_buf,len) do { \
     281             :         uint8_t *buf = (uint8_t *)_buf; \
     282             :         buf[0] = 0; \
     283             :         buf[1] = ((len)&0xFF0000)>>16; \
     284             :         buf[2] = ((len)&0xFF00)>>8; \
     285             :         buf[3] = (len)&0xFF; \
     286             : } while (0)
     287             : 
     288      335666 : static bool smb2_setup_nbt_length(struct iovec *vector, int count)
     289             : {
     290             :         ssize_t len;
     291             : 
     292      335666 :         if (count == 0) {
     293           0 :                 return false;
     294             :         }
     295             : 
     296      335666 :         len = iov_buflen(vector+1, count-1);
     297             : 
     298      335666 :         if ((len == -1) || (len > 0xFFFFFF)) {
     299           0 :                 return false;
     300             :         }
     301             : 
     302      335666 :         _smb2_setlen(vector[0].iov_base, len);
     303      335666 :         return true;
     304             : }
     305             : 
     306      159604 : static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
     307             : {
     308      159604 :         TALLOC_FREE(req->first_enc_key);
     309      159604 :         TALLOC_FREE(req->last_sign_key);
     310      159604 :         return 0;
     311             : }
     312             : 
     313           0 : void smb2_request_set_async_internal(struct smbd_smb2_request *req,
     314             :                                      bool async_internal)
     315             : {
     316           0 :         req->async_internal = async_internal;
     317           0 : }
     318             : 
     319      159604 : static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
     320             : {
     321             :         TALLOC_CTX *mem_pool;
     322             :         struct smbd_smb2_request *req;
     323             : 
     324             : #if 0
     325             :         /* Enable this to find subtle valgrind errors. */
     326             :         mem_pool = talloc_init("smbd_smb2_request_allocate");
     327             : #else
     328      159604 :         mem_pool = talloc_tos();
     329             : #endif
     330      159604 :         if (mem_pool == NULL) {
     331           0 :                 return NULL;
     332             :         }
     333             : 
     334      159604 :         req = talloc_zero(mem_pool, struct smbd_smb2_request);
     335      159604 :         if (req == NULL) {
     336           0 :                 talloc_free(mem_pool);
     337           0 :                 return NULL;
     338             :         }
     339      159604 :         talloc_reparent(mem_pool, mem_ctx, req);
     340             : #if 0
     341             :         TALLOC_FREE(mem_pool);
     342             : #endif
     343             : 
     344      159604 :         req->last_session_id = UINT64_MAX;
     345      159604 :         req->last_tid = UINT32_MAX;
     346             : 
     347      159604 :         talloc_set_destructor(req, smbd_smb2_request_destructor);
     348             : 
     349      159604 :         return req;
     350             : }
     351             : 
     352      157044 : static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
     353             :                                                NTTIME now,
     354             :                                                uint8_t *buf,
     355             :                                                size_t buflen,
     356             :                                                struct smbd_smb2_request *req,
     357             :                                                struct iovec **piov,
     358             :                                                int *pnum_iov)
     359             : {
     360      157044 :         TALLOC_CTX *mem_ctx = req;
     361             :         struct iovec *iov;
     362      157044 :         int num_iov = 1;
     363      157044 :         size_t taken = 0;
     364      157044 :         uint8_t *first_hdr = buf;
     365      157044 :         size_t verified_buflen = 0;
     366      157044 :         uint8_t *tf = NULL;
     367      157044 :         size_t tf_len = 0;
     368             : 
     369             :         /*
     370             :          * Note: index '0' is reserved for the transport protocol
     371             :          */
     372      157044 :         iov = req->in._vector;
     373             : 
     374      434197 :         while (taken < buflen) {
     375      157044 :                 size_t len = buflen - taken;
     376      157044 :                 uint8_t *hdr = first_hdr + taken;
     377             :                 struct iovec *cur;
     378             :                 size_t full_size;
     379             :                 size_t next_command_ofs;
     380             :                 uint16_t body_size;
     381      157044 :                 uint8_t *body = NULL;
     382             :                 uint32_t dyn_size;
     383      157044 :                 uint8_t *dyn = NULL;
     384      157044 :                 struct iovec *iov_alloc = NULL;
     385             : 
     386      157044 :                 if (iov != req->in._vector) {
     387           0 :                         iov_alloc = iov;
     388             :                 }
     389             : 
     390      157044 :                 if (verified_buflen > taken) {
     391           0 :                         len = verified_buflen - taken;
     392             :                 } else {
     393      157044 :                         tf = NULL;
     394      157044 :                         tf_len = 0;
     395             :                 }
     396             : 
     397      157044 :                 if (len < 4) {
     398           0 :                         DEBUG(10, ("%d bytes left, expected at least %d\n",
     399             :                                    (int)len, 4));
     400           0 :                         goto inval;
     401             :                 }
     402      157044 :                 if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
     403         624 :                         struct smbXsrv_session *s = NULL;
     404             :                         uint64_t uid;
     405             :                         struct iovec tf_iov[2];
     406             :                         NTSTATUS status;
     407             :                         size_t enc_len;
     408             : 
     409         624 :                         if (xconn->protocol < PROTOCOL_SMB3_00) {
     410           0 :                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
     411             :                                            "but dialect[0x%04X] is used\n",
     412             :                                            xconn->smb2.server.dialect));
     413           0 :                                 goto inval;
     414             :                         }
     415             : 
     416         624 :                         if (xconn->smb2.server.cipher == 0) {
     417           0 :                                 DEBUG(10, ("Got SMB2_TRANSFORM header, "
     418             :                                            "but not negotiated "
     419             :                                            "client[0x%08X] server[0x%08X]\n",
     420             :                                            xconn->smb2.client.capabilities,
     421             :                                            xconn->smb2.server.capabilities));
     422           0 :                                 goto inval;
     423             :                         }
     424             : 
     425         624 :                         if (len < SMB2_TF_HDR_SIZE) {
     426           0 :                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
     427             :                                            (int)len, SMB2_TF_HDR_SIZE));
     428           0 :                                 goto inval;
     429             :                         }
     430         624 :                         tf = hdr;
     431         624 :                         tf_len = SMB2_TF_HDR_SIZE;
     432         624 :                         taken += tf_len;
     433             : 
     434         624 :                         hdr = first_hdr + taken;
     435         624 :                         enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
     436         624 :                         uid = BVAL(tf, SMB2_TF_SESSION_ID);
     437             : 
     438         624 :                         if (len < SMB2_TF_HDR_SIZE + enc_len) {
     439           0 :                                 DEBUG(1, ("%d bytes left, expected at least %d\n",
     440             :                                            (int)len,
     441             :                                            (int)(SMB2_TF_HDR_SIZE + enc_len)));
     442           0 :                                 goto inval;
     443             :                         }
     444             : 
     445         624 :                         status = smb2srv_session_lookup_conn(xconn, uid, now,
     446             :                                                              &s);
     447         624 :                         if (s == NULL) {
     448           0 :                                 status = smb2srv_session_lookup_global(xconn->client,
     449             :                                                                        uid, req, &s);
     450             :                         }
     451         624 :                         if (s == NULL) {
     452           0 :                                 DEBUG(1, ("invalid session[%llu] in "
     453             :                                           "SMB2_TRANSFORM header\n",
     454             :                                            (unsigned long long)uid));
     455           0 :                                 TALLOC_FREE(iov_alloc);
     456           0 :                                 return NT_STATUS_USER_SESSION_DELETED;
     457             :                         }
     458             : 
     459         624 :                         tf_iov[0].iov_base = (void *)tf;
     460         624 :                         tf_iov[0].iov_len = tf_len;
     461         624 :                         tf_iov[1].iov_base = (void *)hdr;
     462         624 :                         tf_iov[1].iov_len = enc_len;
     463             : 
     464         624 :                         status = smb2_signing_decrypt_pdu(s->global->decryption_key,
     465             :                                                           tf_iov, 2);
     466         624 :                         if (!NT_STATUS_IS_OK(status)) {
     467           0 :                                 TALLOC_FREE(iov_alloc);
     468           0 :                                 return status;
     469             :                         }
     470             : 
     471         624 :                         verified_buflen = taken + enc_len;
     472         624 :                         len = enc_len;
     473             :                 }
     474             : 
     475             :                 /*
     476             :                  * We need the header plus the body length field
     477             :                  */
     478             : 
     479      157044 :                 if (len < SMB2_HDR_BODY + 2) {
     480             : 
     481           0 :                         if ((len == 5) &&
     482           0 :                             (IVAL(hdr, 0) == SMB_SUICIDE_PACKET) &&
     483           0 :                             lp_parm_bool(-1, "smbd", "suicide mode", false)) {
     484           0 :                                 uint8_t exitcode = CVAL(hdr, 4);
     485           0 :                                 DBG_WARNING("SUICIDE: Exiting immediately "
     486             :                                             "with code %"PRIu8"\n",
     487             :                                             exitcode);
     488           0 :                                 exit(exitcode);
     489             :                         }
     490             : 
     491           0 :                         DEBUG(10, ("%d bytes left, expected at least %d\n",
     492             :                                    (int)len, SMB2_HDR_BODY));
     493           0 :                         goto inval;
     494             :                 }
     495      157044 :                 if (IVAL(hdr, 0) != SMB2_MAGIC) {
     496           0 :                         DEBUG(10, ("Got non-SMB2 PDU: %x\n",
     497             :                                    IVAL(hdr, 0)));
     498           0 :                         goto inval;
     499             :                 }
     500      157044 :                 if (SVAL(hdr, 4) != SMB2_HDR_BODY) {
     501           0 :                         DEBUG(10, ("Got HDR len %d, expected %d\n",
     502             :                                    SVAL(hdr, 4), SMB2_HDR_BODY));
     503           0 :                         goto inval;
     504             :                 }
     505             : 
     506      157044 :                 full_size = len;
     507      157044 :                 next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
     508      157044 :                 body_size = SVAL(hdr, SMB2_HDR_BODY);
     509             : 
     510      157044 :                 if (next_command_ofs != 0) {
     511           0 :                         if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
     512           0 :                                 goto inval;
     513             :                         }
     514           0 :                         if (next_command_ofs > full_size) {
     515           0 :                                 goto inval;
     516             :                         }
     517           0 :                         full_size = next_command_ofs;
     518             :                 }
     519      157044 :                 if (body_size < 2) {
     520           0 :                         goto inval;
     521             :                 }
     522      157044 :                 body_size &= 0xfffe;
     523             : 
     524      157044 :                 if (body_size > (full_size - SMB2_HDR_BODY)) {
     525             :                         /*
     526             :                          * let the caller handle the error
     527             :                          */
     528           0 :                         body_size = full_size - SMB2_HDR_BODY;
     529             :                 }
     530      157044 :                 body = hdr + SMB2_HDR_BODY;
     531      157044 :                 dyn = body + body_size;
     532      157044 :                 dyn_size = full_size - (SMB2_HDR_BODY + body_size);
     533             : 
     534      157044 :                 if (num_iov >= ARRAY_SIZE(req->in._vector)) {
     535           0 :                         struct iovec *iov_tmp = NULL;
     536             : 
     537           0 :                         iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
     538             :                                                  struct iovec,
     539             :                                                  num_iov +
     540             :                                                  SMBD_SMB2_NUM_IOV_PER_REQ);
     541           0 :                         if (iov_tmp == NULL) {
     542           0 :                                 TALLOC_FREE(iov_alloc);
     543           0 :                                 return NT_STATUS_NO_MEMORY;
     544             :                         }
     545             : 
     546           0 :                         if (iov_alloc == NULL) {
     547           0 :                                 memcpy(iov_tmp,
     548           0 :                                        req->in._vector,
     549             :                                        sizeof(req->in._vector));
     550             :                         }
     551             : 
     552           0 :                         iov = iov_tmp;
     553             :                 }
     554      157044 :                 cur = &iov[num_iov];
     555      157044 :                 num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
     556             : 
     557      157044 :                 cur[SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
     558      157044 :                 cur[SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
     559      157044 :                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
     560      157044 :                 cur[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
     561      157044 :                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
     562      157044 :                 cur[SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_size;
     563      157044 :                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
     564      157044 :                 cur[SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_size;
     565             : 
     566      157044 :                 taken += full_size;
     567             :         }
     568             : 
     569      157044 :         *piov = iov;
     570      157044 :         *pnum_iov = num_iov;
     571      157044 :         return NT_STATUS_OK;
     572             : 
     573           0 : inval:
     574           0 :         if (iov != req->in._vector) {
     575           0 :                 TALLOC_FREE(iov);
     576             :         }
     577           0 :         return NT_STATUS_INVALID_PARAMETER;
     578             : }
     579             : 
     580        5052 : static NTSTATUS smbd_smb2_request_create(struct smbXsrv_connection *xconn,
     581             :                                          const uint8_t *_inpdu, size_t size,
     582             :                                          struct smbd_smb2_request **_req)
     583             : {
     584        5052 :         struct smbd_server_connection *sconn = xconn->client->sconn;
     585             :         struct smbd_smb2_request *req;
     586             :         uint32_t protocol_version;
     587        5052 :         uint8_t *inpdu = NULL;
     588        5052 :         const uint8_t *inhdr = NULL;
     589             :         uint16_t cmd;
     590             :         uint32_t next_command_ofs;
     591             :         NTSTATUS status;
     592             :         NTTIME now;
     593             : 
     594        5052 :         if (size < (SMB2_HDR_BODY + 2)) {
     595           0 :                 DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
     596           0 :                 return NT_STATUS_INVALID_PARAMETER;
     597             :         }
     598             : 
     599        5052 :         inhdr = _inpdu;
     600             : 
     601        5052 :         protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
     602        5052 :         if (protocol_version != SMB2_MAGIC) {
     603           0 :                 DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
     604             :                          protocol_version));
     605           0 :                 return NT_STATUS_INVALID_PARAMETER;
     606             :         }
     607             : 
     608        5052 :         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
     609        5052 :         if (cmd != SMB2_OP_NEGPROT) {
     610           0 :                 DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
     611             :                          cmd));
     612           0 :                 return NT_STATUS_INVALID_PARAMETER;
     613             :         }
     614             : 
     615        5052 :         next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
     616        5052 :         if (next_command_ofs != 0) {
     617           0 :                 DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
     618             :                          next_command_ofs));
     619           0 :                 return NT_STATUS_INVALID_PARAMETER;
     620             :         }
     621             : 
     622        5052 :         req = smbd_smb2_request_allocate(xconn);
     623        5052 :         if (req == NULL) {
     624           0 :                 return NT_STATUS_NO_MEMORY;
     625             :         }
     626        5052 :         req->sconn = sconn;
     627        5052 :         req->xconn = xconn;
     628             : 
     629        5052 :         inpdu = talloc_memdup(req, _inpdu, size);
     630        5052 :         if (inpdu == NULL) {
     631           0 :                 return NT_STATUS_NO_MEMORY;
     632             :         }
     633             : 
     634        5052 :         req->request_time = timeval_current();
     635        5052 :         now = timeval_to_nttime(&req->request_time);
     636             : 
     637        5052 :         status = smbd_smb2_inbuf_parse_compound(xconn,
     638             :                                                 now,
     639             :                                                 inpdu,
     640             :                                                 size,
     641             :                                                 req, &req->in.vector,
     642             :                                                 &req->in.vector_count);
     643        5052 :         if (!NT_STATUS_IS_OK(status)) {
     644           0 :                 TALLOC_FREE(req);
     645           0 :                 return status;
     646             :         }
     647             : 
     648        5052 :         req->current_idx = 1;
     649             : 
     650        5052 :         *_req = req;
     651        5052 :         return NT_STATUS_OK;
     652             : }
     653             : 
     654      703910 : static bool smb2_validate_sequence_number(struct smbXsrv_connection *xconn,
     655             :                                           uint64_t message_id, uint64_t seq_id)
     656             : {
     657      703910 :         struct bitmap *credits_bm = xconn->smb2.credits.bitmap;
     658             :         unsigned int offset;
     659             :         uint64_t seq_tmp;
     660             : 
     661      703910 :         seq_tmp = xconn->smb2.credits.seq_low;
     662      703910 :         if (seq_id < seq_tmp) {
     663           0 :                 DBGC_ERR(DBGC_SMB2_CREDITS,
     664             :                         "smb2_validate_sequence_number: bad message_id "
     665             :                         "%llu (sequence id %llu) "
     666             :                         "(granted = %u, low = %llu, range = %u)\n",
     667             :                         (unsigned long long)message_id,
     668             :                         (unsigned long long)seq_id,
     669             :                         (unsigned int)xconn->smb2.credits.granted,
     670             :                         (unsigned long long)xconn->smb2.credits.seq_low,
     671             :                         (unsigned int)xconn->smb2.credits.seq_range);
     672           0 :                 return false;
     673             :         }
     674             : 
     675      703910 :         seq_tmp += xconn->smb2.credits.seq_range;
     676      703910 :         if (seq_id >= seq_tmp) {
     677           0 :                 DBGC_ERR(DBGC_SMB2_CREDITS,
     678             :                         "smb2_validate_sequence_number: bad message_id "
     679             :                         "%llu (sequence id %llu) "
     680             :                         "(granted = %u, low = %llu, range = %u)\n",
     681             :                         (unsigned long long)message_id,
     682             :                         (unsigned long long)seq_id,
     683             :                         (unsigned int)xconn->smb2.credits.granted,
     684             :                         (unsigned long long)xconn->smb2.credits.seq_low,
     685             :                         (unsigned int)xconn->smb2.credits.seq_range);
     686           0 :                 return false;
     687             :         }
     688             : 
     689      703910 :         offset = seq_id % xconn->smb2.credits.max;
     690             : 
     691      703910 :         if (bitmap_query(credits_bm, offset)) {
     692           0 :                 DBGC_ERR(DBGC_SMB2_CREDITS,
     693             :                         "smb2_validate_sequence_number: duplicate message_id "
     694             :                         "%llu (sequence id %llu) "
     695             :                         "(granted = %u, low = %llu, range = %u) "
     696             :                         "(bm offset %u)\n",
     697             :                         (unsigned long long)message_id,
     698             :                         (unsigned long long)seq_id,
     699             :                         (unsigned int)xconn->smb2.credits.granted,
     700             :                         (unsigned long long)xconn->smb2.credits.seq_low,
     701             :                         (unsigned int)xconn->smb2.credits.seq_range,
     702             :                         offset);
     703           0 :                 return false;
     704             :         }
     705             : 
     706             :         /* Mark the message_ids as seen in the bitmap. */
     707      703910 :         bitmap_set(credits_bm, offset);
     708             : 
     709      703910 :         if (seq_id != xconn->smb2.credits.seq_low) {
     710           0 :                 return true;
     711             :         }
     712             : 
     713             :         /*
     714             :          * Move the window forward by all the message_id's
     715             :          * already seen.
     716             :          */
     717     1960200 :         while (bitmap_query(credits_bm, offset)) {
     718      703910 :                 DBGC_DEBUG(DBGC_SMB2_CREDITS,
     719             :                           "smb2_validate_sequence_number: clearing "
     720             :                           "id %llu (position %u) from bitmap\n",
     721             :                           (unsigned long long)(xconn->smb2.credits.seq_low),
     722             :                           offset);
     723      703910 :                 bitmap_clear(credits_bm, offset);
     724             : 
     725      703910 :                 xconn->smb2.credits.seq_low += 1;
     726      703910 :                 xconn->smb2.credits.seq_range -= 1;
     727      703910 :                 offset = xconn->smb2.credits.seq_low % xconn->smb2.credits.max;
     728             :         }
     729             : 
     730      703910 :         return true;
     731             : }
     732             : 
     733      157044 : static bool smb2_validate_message_id(struct smbXsrv_connection *xconn,
     734             :                                      const uint8_t *inhdr)
     735             : {
     736      157044 :         uint64_t message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
     737      157044 :         uint16_t opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
     738      157044 :         uint16_t credit_charge = 1;
     739             :         uint64_t i;
     740             : 
     741      157044 :         if (opcode == SMB2_OP_CANCEL) {
     742             :                 /* SMB2_CANCEL requests by definition resend messageids. */
     743          18 :                 return true;
     744             :         }
     745             : 
     746      157026 :         if (xconn->smb2.credits.multicredit) {
     747      149602 :                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
     748      149602 :                 credit_charge = MAX(credit_charge, 1);
     749             :         }
     750             : 
     751      157026 :         DEBUGC(11,
     752             :                    DBGC_SMB2_CREDITS,
     753             :                    ("smb2_validate_message_id: mid %llu (charge %llu), "
     754             :                    "credits_granted %llu, "
     755             :                    "seqnum low/range: %llu/%llu\n",
     756             :                    (unsigned long long) message_id,
     757             :                    (unsigned long long) credit_charge,
     758             :                    (unsigned long long) xconn->smb2.credits.granted,
     759             :                    (unsigned long long) xconn->smb2.credits.seq_low,
     760             :                    (unsigned long long) xconn->smb2.credits.seq_range));
     761             : 
     762      157026 :         if (xconn->smb2.credits.granted < credit_charge) {
     763           0 :                 DBGC_ERR(DBGC_SMB2_CREDITS,
     764             :                           "smb2_validate_message_id: client used more "
     765             :                           "credits than granted, mid %llu, charge %llu, "
     766             :                           "credits_granted %llu, "
     767             :                           "seqnum low/range: %llu/%llu\n",
     768             :                           (unsigned long long) message_id,
     769             :                           (unsigned long long) credit_charge,
     770             :                           (unsigned long long) xconn->smb2.credits.granted,
     771             :                           (unsigned long long) xconn->smb2.credits.seq_low,
     772             :                           (unsigned long long) xconn->smb2.credits.seq_range);
     773           0 :                 return false;
     774             :         }
     775             : 
     776             :         /*
     777             :          * now check the message ids
     778             :          *
     779             :          * for multi-credit requests we need to check all current mid plus
     780             :          * the implicit mids caused by the credit charge
     781             :          * e.g. current mid = 15, charge 5 => mark 15-19 as used
     782             :          */
     783             : 
     784      860936 :         for (i = 0; i <= (credit_charge-1); i++) {
     785      703910 :                 uint64_t id = message_id + i;
     786             :                 bool ok;
     787             : 
     788      703910 :                 DEBUGC(11,
     789             :                            DBGC_SMB2_CREDITS,
     790             :                            ("Iterating mid %llu charge %u (sequence %llu)\n",
     791             :                            (unsigned long long)message_id,
     792             :                            credit_charge,
     793             :                            (unsigned long long)id));
     794             : 
     795      703910 :                 ok = smb2_validate_sequence_number(xconn, message_id, id);
     796      703910 :                 if (!ok) {
     797           0 :                         return false;
     798             :                 }
     799             :         }
     800             : 
     801             :         /* substract used credits */
     802      157026 :         xconn->smb2.credits.granted -= credit_charge;
     803             : 
     804      157026 :         return true;
     805             : }
     806             : 
     807      157044 : static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
     808             : {
     809             :         int count;
     810             :         int idx;
     811             : 
     812      157044 :         count = req->in.vector_count;
     813             : 
     814      157044 :         if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
     815             :                 /* It's not a SMB2 request */
     816           0 :                 return NT_STATUS_INVALID_PARAMETER;
     817             :         }
     818             : 
     819      314088 :         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
     820      157044 :                 struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
     821      157044 :                 struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
     822      157044 :                 const uint8_t *inhdr = NULL;
     823             : 
     824      157044 :                 if (hdr->iov_len != SMB2_HDR_BODY) {
     825           0 :                         return NT_STATUS_INVALID_PARAMETER;
     826             :                 }
     827             : 
     828      157044 :                 if (body->iov_len < 2) {
     829           0 :                         return NT_STATUS_INVALID_PARAMETER;
     830             :                 }
     831             : 
     832      157044 :                 inhdr = (const uint8_t *)hdr->iov_base;
     833             : 
     834             :                 /* Check the SMB2 header */
     835      157044 :                 if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
     836           0 :                         return NT_STATUS_INVALID_PARAMETER;
     837             :                 }
     838             : 
     839      157044 :                 if (!smb2_validate_message_id(req->xconn, inhdr)) {
     840           0 :                         return NT_STATUS_INVALID_PARAMETER;
     841             :                 }
     842             :         }
     843             : 
     844      157044 :         return NT_STATUS_OK;
     845             : }
     846             : 
     847      178622 : static void smb2_set_operation_credit(struct smbXsrv_connection *xconn,
     848             :                                       const struct iovec *in_vector,
     849             :                                       struct iovec *out_vector)
     850             : {
     851      178622 :         const uint8_t *inhdr = (const uint8_t *)in_vector->iov_base;
     852      178622 :         uint8_t *outhdr = (uint8_t *)out_vector->iov_base;
     853      178622 :         uint16_t credit_charge = 1;
     854             :         uint16_t credits_requested;
     855             :         uint32_t out_flags;
     856             :         uint16_t cmd;
     857             :         NTSTATUS out_status;
     858      178622 :         uint16_t credits_granted = 0;
     859             :         uint64_t credits_possible;
     860             :         uint16_t current_max_credits;
     861             : 
     862             :         /*
     863             :          * first we grant only 1/16th of the max range.
     864             :          *
     865             :          * Windows also starts with the 1/16th and then grants
     866             :          * more later. I was only able to trigger higher
     867             :          * values, when using a very high credit charge.
     868             :          *
     869             :          * TODO: scale up depending on load, free memory
     870             :          *       or other stuff.
     871             :          *       Maybe also on the relationship between number
     872             :          *       of requests and the used sequence number.
     873             :          *       Which means we would grant more credits
     874             :          *       for client which use multi credit requests.
     875             :          *
     876             :          * The above is what Windows Server < 2016 is doing,
     877             :          * but new servers use all credits (8192 by default).
     878             :          */
     879      178622 :         current_max_credits = xconn->smb2.credits.max;
     880      178622 :         current_max_credits = MAX(current_max_credits, 1);
     881             : 
     882      178622 :         if (xconn->smb2.credits.multicredit) {
     883      175859 :                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
     884      175859 :                 credit_charge = MAX(credit_charge, 1);
     885             :         }
     886             : 
     887      178622 :         cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
     888      178622 :         credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
     889      178622 :         credits_requested = MAX(credits_requested, 1);
     890      178622 :         out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
     891      178622 :         out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
     892             : 
     893      178622 :         SMB_ASSERT(xconn->smb2.credits.max >= xconn->smb2.credits.granted);
     894             : 
     895      178622 :         if (xconn->smb2.credits.max < credit_charge) {
     896           0 :                 smbd_server_connection_terminate(xconn,
     897             :                         "client error: credit charge > max credits\n");
     898           0 :                 return;
     899             :         }
     900             : 
     901      178622 :         if (out_flags & SMB2_HDR_FLAG_ASYNC) {
     902             :                 /*
     903             :                  * In case we already send an async interim
     904             :                  * response, we should not grant
     905             :                  * credits on the final response.
     906             :                  */
     907       21646 :                 credits_granted = 0;
     908             :         } else {
     909      156976 :                 uint16_t additional_possible =
     910      156976 :                         xconn->smb2.credits.max - credit_charge;
     911      156976 :                 uint16_t additional_max = 0;
     912      156976 :                 uint16_t additional_credits = credits_requested - 1;
     913             : 
     914      156976 :                 switch (cmd) {
     915        8323 :                 case SMB2_OP_NEGPROT:
     916        8323 :                         break;
     917        6774 :                 case SMB2_OP_SESSSETUP:
     918             :                         /*
     919             :                          * Windows 2012 RC1 starts to grant
     920             :                          * additional credits
     921             :                          * with a successful session setup
     922             :                          */
     923        6774 :                         if (NT_STATUS_IS_OK(out_status)) {
     924        4832 :                                 additional_max = xconn->smb2.credits.max;
     925             :                         }
     926        6774 :                         break;
     927      141879 :                 default:
     928             :                         /*
     929             :                          * Windows Server < 2016 and older Samba versions
     930             :                          * used to only grant additional credits in
     931             :                          * chunks of 32 credits.
     932             :                          *
     933             :                          * But we match Windows Server 2016 and grant
     934             :                          * all credits as requested.
     935             :                          */
     936      141879 :                         additional_max = xconn->smb2.credits.max;
     937      141879 :                         break;
     938             :                 }
     939             : 
     940      156976 :                 additional_max = MIN(additional_max, additional_possible);
     941      156976 :                 additional_credits = MIN(additional_credits, additional_max);
     942             : 
     943      156976 :                 credits_granted = credit_charge + additional_credits;
     944             :         }
     945             : 
     946             :         /*
     947             :          * sequence numbers should not wrap
     948             :          *
     949             :          * 1. calculate the possible credits until
     950             :          *    the sequence numbers start to wrap on 64-bit.
     951             :          *
     952             :          * 2. UINT64_MAX is used for Break Notifications.
     953             :          *
     954             :          * 2. truncate the possible credits to the maximum
     955             :          *    credits we want to grant to the client in total.
     956             :          *
     957             :          * 3. remove the range we'll already granted to the client
     958             :          *    this makes sure the client consumes the lowest sequence
     959             :          *    number, before we can grant additional credits.
     960             :          */
     961      178622 :         credits_possible = UINT64_MAX - xconn->smb2.credits.seq_low;
     962      178622 :         if (credits_possible > 0) {
     963             :                 /* remove UINT64_MAX */
     964      178622 :                 credits_possible -= 1;
     965             :         }
     966      178622 :         credits_possible = MIN(credits_possible, current_max_credits);
     967      178622 :         credits_possible -= xconn->smb2.credits.seq_range;
     968             : 
     969      178622 :         credits_granted = MIN(credits_granted, credits_possible);
     970             : 
     971      178622 :         SSVAL(outhdr, SMB2_HDR_CREDIT, credits_granted);
     972      178622 :         xconn->smb2.credits.granted += credits_granted;
     973      178622 :         xconn->smb2.credits.seq_range += credits_granted;
     974             : 
     975      178622 :         DBGC_DEBUG(DBGC_SMB2_CREDITS,
     976             :                 "smb2_set_operation_credit: requested %u, charge %u, "
     977             :                 "granted %u, current possible/max %u/%u, "
     978             :                 "total granted/max/low/range %u/%u/%llu/%u\n",
     979             :                 (unsigned int)credits_requested,
     980             :                 (unsigned int)credit_charge,
     981             :                 (unsigned int)credits_granted,
     982             :                 (unsigned int)credits_possible,
     983             :                 (unsigned int)current_max_credits,
     984             :                 (unsigned int)xconn->smb2.credits.granted,
     985             :                 (unsigned int)xconn->smb2.credits.max,
     986             :                 (unsigned long long)xconn->smb2.credits.seq_low,
     987             :                 (unsigned int)xconn->smb2.credits.seq_range);
     988             : }
     989             : 
     990      156976 : static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
     991             :                                 struct smbd_smb2_request *outreq)
     992             : {
     993             :         int count, idx;
     994      156976 :         uint16_t total_credits = 0;
     995             : 
     996      156976 :         count = outreq->out.vector_count;
     997             : 
     998      313952 :         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
     999      156976 :                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
    1000      156976 :                 struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
    1001      156976 :                 uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
    1002             : 
    1003      156976 :                 smb2_set_operation_credit(outreq->xconn, inhdr_v, outhdr_v);
    1004             : 
    1005             :                 /* To match Windows, count up what we
    1006             :                    just granted. */
    1007      156976 :                 total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
    1008             :                 /* Set to zero in all but the last reply. */
    1009      156976 :                 if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
    1010           0 :                         SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
    1011             :                 } else {
    1012      156976 :                         SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
    1013             :                 }
    1014             :         }
    1015      156976 : }
    1016             : 
    1017      151594 : DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size)
    1018             : {
    1019      151594 :         if (req->current_idx <= 1) {
    1020      151594 :                 if (size <= sizeof(req->out._body)) {
    1021      151594 :                         return data_blob_const(req->out._body, size);
    1022             :                 }
    1023             :         }
    1024             : 
    1025           0 :         return data_blob_talloc(req, NULL, size);
    1026             : }
    1027             : 
    1028      157044 : static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
    1029             : {
    1030      157044 :         struct smbXsrv_connection *xconn = req->xconn;
    1031             :         TALLOC_CTX *mem_ctx;
    1032             :         struct iovec *vector;
    1033             :         int count;
    1034             :         int idx;
    1035             :         bool ok;
    1036             : 
    1037      157044 :         count = req->in.vector_count;
    1038      157044 :         if (count <= ARRAY_SIZE(req->out._vector)) {
    1039      157044 :                 mem_ctx = req;
    1040      157044 :                 vector = req->out._vector;
    1041             :         } else {
    1042           0 :                 vector = talloc_zero_array(req, struct iovec, count);
    1043           0 :                 if (vector == NULL) {
    1044           0 :                         return NT_STATUS_NO_MEMORY;
    1045             :                 }
    1046           0 :                 mem_ctx = vector;
    1047             :         }
    1048             : 
    1049      157044 :         vector[0].iov_base      = req->out.nbt_hdr;
    1050      157044 :         vector[0].iov_len       = 4;
    1051      157044 :         SIVAL(req->out.nbt_hdr, 0, 0);
    1052             : 
    1053      314088 :         for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
    1054      157044 :                 struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
    1055      157044 :                 const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
    1056      157044 :                 uint8_t *outhdr = NULL;
    1057      157044 :                 uint8_t *outbody = NULL;
    1058      157044 :                 uint32_t next_command_ofs = 0;
    1059      157044 :                 struct iovec *current = &vector[idx];
    1060             : 
    1061      157044 :                 if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
    1062             :                         /* we have a next command -
    1063             :                          * setup for the error case. */
    1064           0 :                         next_command_ofs = SMB2_HDR_BODY + 9;
    1065             :                 }
    1066             : 
    1067      157044 :                 if (idx == 1) {
    1068      157044 :                         outhdr = req->out._hdr;
    1069             :                 } else {
    1070           0 :                         outhdr = talloc_zero_array(mem_ctx, uint8_t,
    1071             :                                                    OUTVEC_ALLOC_SIZE);
    1072           0 :                         if (outhdr == NULL) {
    1073           0 :                                 return NT_STATUS_NO_MEMORY;
    1074             :                         }
    1075             :                 }
    1076             : 
    1077      157044 :                 outbody = outhdr + SMB2_HDR_BODY;
    1078             : 
    1079             :                 /*
    1080             :                  * SMBD_SMB2_TF_IOV_OFS might be used later
    1081             :                  */
    1082      157044 :                 current[SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
    1083      157044 :                 current[SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
    1084             : 
    1085      157044 :                 current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
    1086      157044 :                 current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
    1087             : 
    1088      157044 :                 current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
    1089      157044 :                 current[SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
    1090             : 
    1091      157044 :                 current[SMBD_SMB2_DYN_IOV_OFS].iov_base  = NULL;
    1092      157044 :                 current[SMBD_SMB2_DYN_IOV_OFS].iov_len   = 0;
    1093             : 
    1094             :                 /* setup the SMB2 header */
    1095      157044 :                 SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
    1096      157044 :                 SSVAL(outhdr, SMB2_HDR_LENGTH,          SMB2_HDR_BODY);
    1097      157044 :                 SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
    1098             :                       SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
    1099      157044 :                 SIVAL(outhdr, SMB2_HDR_STATUS,
    1100             :                       NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
    1101      157044 :                 SSVAL(outhdr, SMB2_HDR_OPCODE,
    1102             :                       SVAL(inhdr, SMB2_HDR_OPCODE));
    1103      157044 :                 SIVAL(outhdr, SMB2_HDR_FLAGS,
    1104             :                       IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
    1105      157044 :                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,    next_command_ofs);
    1106      157044 :                 SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
    1107             :                       BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
    1108      157044 :                 SIVAL(outhdr, SMB2_HDR_PID,
    1109             :                       IVAL(inhdr, SMB2_HDR_PID));
    1110      157044 :                 SIVAL(outhdr, SMB2_HDR_TID,
    1111             :                       IVAL(inhdr, SMB2_HDR_TID));
    1112      157044 :                 SBVAL(outhdr, SMB2_HDR_SESSION_ID,
    1113             :                       BVAL(inhdr, SMB2_HDR_SESSION_ID));
    1114      157044 :                 memcpy(outhdr + SMB2_HDR_SIGNATURE,
    1115      157044 :                        inhdr + SMB2_HDR_SIGNATURE, 16);
    1116             : 
    1117             :                 /* setup error body header */
    1118      157044 :                 SSVAL(outbody, 0x00, 0x08 + 1);
    1119      157044 :                 SSVAL(outbody, 0x02, 0);
    1120      157044 :                 SIVAL(outbody, 0x04, 0);
    1121             :         }
    1122             : 
    1123      157044 :         req->out.vector = vector;
    1124      157044 :         req->out.vector_count = count;
    1125             : 
    1126             :         /* setup the length of the NBT packet */
    1127      157044 :         ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
    1128      157044 :         if (!ok) {
    1129           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1130             :         }
    1131             : 
    1132      157044 :         DLIST_ADD_END(xconn->smb2.requests, req);
    1133             : 
    1134      157044 :         return NT_STATUS_OK;
    1135             : }
    1136             : 
    1137        5270 : bool smbXsrv_server_multi_channel_enabled(void)
    1138             : {
    1139        5270 :         bool enabled = lp_server_multi_channel_support();
    1140             : #ifndef __ALLOW_MULTI_CHANNEL_SUPPORT
    1141             :         bool forced = false;
    1142             :         struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
    1143             :         bool unspecified = lpcfg_parm_is_unspecified(lp_ctx, "server multi channel support");
    1144             :         if (unspecified) {
    1145             :                 enabled = false;
    1146             :         }
    1147             :         /*
    1148             :          * If we don't have support from the kernel
    1149             :          * to ask for the un-acked number of bytes
    1150             :          * in the socket send queue, we better
    1151             :          * don't support multi-channel.
    1152             :          */
    1153             :         forced = lp_parm_bool(-1, "force", "server multi channel support", false);
    1154             :         if (enabled && !forced) {
    1155             :                 D_NOTICE("'server multi channel support' enabled "
    1156             :                          "but not supported on %s (%s)\n",
    1157             :                          SYSTEM_UNAME_SYSNAME, SYSTEM_UNAME_RELEASE);
    1158             :                 DEBUGADD(DBGLVL_NOTICE, ("Please report this on "
    1159             :                         "https://bugzilla.samba.org/show_bug.cgi?id=11897\n"));
    1160             :                 enabled = false;
    1161             :         }
    1162             :         TALLOC_FREE(lp_ctx);
    1163             : #endif /* ! __ALLOW_MULTI_CHANNEL_SUPPORT */
    1164        5270 :         return enabled;
    1165             : }
    1166             : 
    1167           0 : static NTSTATUS smbXsrv_connection_get_rto_usecs(struct smbXsrv_connection *xconn,
    1168             :                                                  uint32_t *_rto_usecs)
    1169             : {
    1170             :         /*
    1171             :          * Define an Retransmission Timeout
    1172             :          * of 1 second, if there's no way for the
    1173             :          * kernel to tell us the current value.
    1174             :          */
    1175           0 :         uint32_t rto_usecs = 1000000;
    1176             : 
    1177             : #ifdef __HAVE_TCP_INFO_RTO
    1178             :         {
    1179             :                 struct tcp_info info;
    1180           0 :                 socklen_t ilen = sizeof(info);
    1181             :                 int ret;
    1182             : 
    1183           0 :                 ZERO_STRUCT(info);
    1184           0 :                 ret = getsockopt(xconn->transport.sock,
    1185             :                                  IPPROTO_TCP, TCP_INFO,
    1186             :                                  (void *)&info, &ilen);
    1187           0 :                 if (ret != 0) {
    1188           0 :                         int saved_errno = errno;
    1189           0 :                         NTSTATUS status = map_nt_error_from_unix(errno);
    1190           0 :                         DBG_ERR("getsockopt(TCP_INFO) errno[%d/%s] -s %s\n",
    1191             :                                 saved_errno, strerror(saved_errno),
    1192             :                                 nt_errstr(status));
    1193           0 :                         return status;
    1194             :                 }
    1195             : 
    1196           0 :                 DBG_DEBUG("tcpi_rto[%u] tcpi_rtt[%u] tcpi_rttvar[%u]\n",
    1197             :                           (unsigned)info.tcpi_rto,
    1198             :                           (unsigned)info.tcpi_rtt,
    1199             :                           (unsigned)info.tcpi_rttvar);
    1200           0 :                 rto_usecs = info.tcpi_rto;
    1201             :         }
    1202             : #endif /* __HAVE_TCP_INFO_RTO */
    1203             : 
    1204           0 :         rto_usecs = MAX(rto_usecs,  200000); /* at least 0.2s */
    1205           0 :         rto_usecs = MIN(rto_usecs, 1000000); /* at max   1.0s */
    1206           0 :         *_rto_usecs = rto_usecs;
    1207           0 :         return NT_STATUS_OK;
    1208             : }
    1209             : 
    1210           0 : static NTSTATUS smbXsrv_connection_get_acked_bytes(struct smbXsrv_connection *xconn,
    1211             :                                                    uint64_t *_acked_bytes)
    1212             : {
    1213             :         /*
    1214             :          * Unless the kernel has an interface
    1215             :          * to reveal the number of un-acked bytes
    1216             :          * in the socket send queue, we'll assume
    1217             :          * everything is already acked.
    1218             :          *
    1219             :          * But that would mean that we better don't
    1220             :          * pretent to support multi-channel.
    1221             :          */
    1222           0 :         uint64_t unacked_bytes = 0;
    1223             : 
    1224           0 :         *_acked_bytes = 0;
    1225             : 
    1226           0 :         if (xconn->ack.force_unacked_timeout) {
    1227             :                 /*
    1228             :                  * Smbtorture tries to test channel failures...
    1229             :                  * Just pretend nothing was acked...
    1230             :                  */
    1231           0 :                 DBG_INFO("Simulating channel failure: "
    1232             :                          "xconn->ack.unacked_bytes[%llu]\n",
    1233             :                          (unsigned long long)xconn->ack.unacked_bytes);
    1234           0 :                 return NT_STATUS_OK;
    1235             :         }
    1236             : 
    1237             : #ifdef __IOCTL_SEND_QUEUE_SIZE_OPCODE
    1238             :         {
    1239           0 :                 int value = 0;
    1240             :                 int ret;
    1241             : 
    1242             :                 /*
    1243             :                  * If we have kernel support to get
    1244             :                  * the number of bytes waiting in
    1245             :                  * the socket's send queue, we
    1246             :                  * use that in order to find out
    1247             :                  * the number of unacked bytes.
    1248             :                  */
    1249           0 :                 ret = ioctl(xconn->transport.sock,
    1250             :                             __IOCTL_SEND_QUEUE_SIZE_OPCODE,
    1251             :                             &value);
    1252           0 :                 if (ret != 0) {
    1253           0 :                         int saved_errno = errno;
    1254           0 :                         NTSTATUS status = map_nt_error_from_unix(saved_errno);
    1255           0 :                         DBG_ERR("Failed to get the SEND_QUEUE_SIZE - "
    1256             :                                 "errno %d (%s) - %s\n",
    1257             :                                 saved_errno, strerror(saved_errno),
    1258             :                                 nt_errstr(status));
    1259           0 :                         return status;
    1260             :                 }
    1261             : 
    1262           0 :                 if (value < 0) {
    1263           0 :                         DBG_ERR("xconn->ack.unacked_bytes[%llu] value[%d]\n",
    1264             :                                 (unsigned long long)xconn->ack.unacked_bytes,
    1265             :                                 value);
    1266           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1267             :                 }
    1268           0 :                 unacked_bytes = value;
    1269             :         }
    1270             : #endif
    1271           0 :         if (xconn->ack.unacked_bytes == 0) {
    1272           0 :                 xconn->ack.unacked_bytes = unacked_bytes;
    1273           0 :                 return NT_STATUS_OK;
    1274             :         }
    1275             : 
    1276           0 :         if (xconn->ack.unacked_bytes < unacked_bytes) {
    1277           0 :                 DBG_ERR("xconn->ack.unacked_bytes[%llu] unacked_bytes[%llu]\n",
    1278             :                         (unsigned long long)xconn->ack.unacked_bytes,
    1279             :                         (unsigned long long)unacked_bytes);
    1280           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1281             :         }
    1282             : 
    1283           0 :         *_acked_bytes = xconn->ack.unacked_bytes - unacked_bytes;
    1284           0 :         xconn->ack.unacked_bytes = unacked_bytes;
    1285           0 :         return NT_STATUS_OK;
    1286             : }
    1287             : 
    1288       10640 : static void smbd_smb2_send_queue_ack_fail(struct smbd_smb2_send_queue **queue,
    1289             :                                           NTSTATUS status)
    1290             : {
    1291       10640 :         struct smbd_smb2_send_queue *e = NULL;
    1292       10640 :         struct smbd_smb2_send_queue *n = NULL;
    1293             : 
    1294       13132 :         for (e = *queue; e != NULL; e = n) {
    1295        2492 :                 n = e->next;
    1296             : 
    1297        2492 :                 DLIST_REMOVE(*queue, e);
    1298        2492 :                 if (e->ack.req != NULL) {
    1299           0 :                         tevent_req_nterror(e->ack.req, status);
    1300             :                 }
    1301             :         }
    1302       10640 : }
    1303             : 
    1304           0 : static NTSTATUS smbd_smb2_send_queue_ack_bytes(struct smbd_smb2_send_queue **queue,
    1305             :                                                uint64_t acked_bytes)
    1306             : {
    1307           0 :         struct smbd_smb2_send_queue *e = NULL;
    1308           0 :         struct smbd_smb2_send_queue *n = NULL;
    1309             : 
    1310           0 :         for (e = *queue; e != NULL; e = n) {
    1311             :                 bool expired;
    1312             : 
    1313           0 :                 n = e->next;
    1314             : 
    1315           0 :                 if (e->ack.req == NULL) {
    1316           0 :                         continue;
    1317             :                 }
    1318             : 
    1319           0 :                 if (e->ack.required_acked_bytes <= acked_bytes) {
    1320           0 :                         e->ack.required_acked_bytes = 0;
    1321           0 :                         DLIST_REMOVE(*queue, e);
    1322           0 :                         tevent_req_done(e->ack.req);
    1323           0 :                         continue;
    1324             :                 }
    1325           0 :                 e->ack.required_acked_bytes -= acked_bytes;
    1326             : 
    1327           0 :                 expired = timeval_expired(&e->ack.timeout);
    1328           0 :                 if (expired) {
    1329           0 :                         return NT_STATUS_IO_TIMEOUT;
    1330             :                 }
    1331             :         }
    1332             : 
    1333           0 :         return NT_STATUS_OK;
    1334             : }
    1335             : 
    1336           0 : static NTSTATUS smbd_smb2_check_ack_queue(struct smbXsrv_connection *xconn)
    1337             : {
    1338           0 :         uint64_t acked_bytes = 0;
    1339             :         NTSTATUS status;
    1340             : 
    1341           0 :         status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
    1342           0 :         if (!NT_STATUS_IS_OK(status)) {
    1343           0 :                 return status;
    1344             :         }
    1345             : 
    1346           0 :         status = smbd_smb2_send_queue_ack_bytes(&xconn->ack.queue, acked_bytes);
    1347           0 :         if (!NT_STATUS_IS_OK(status)) {
    1348           0 :                 return status;
    1349             :         }
    1350             : 
    1351           0 :         status = smbd_smb2_send_queue_ack_bytes(&xconn->smb2.send_queue, 0);
    1352           0 :         if (!NT_STATUS_IS_OK(status)) {
    1353           0 :                 return status;
    1354             :         }
    1355             : 
    1356           0 :         return NT_STATUS_OK;
    1357             : }
    1358             : 
    1359           0 : static void smbXsrv_connection_ack_checker(struct tevent_req *subreq)
    1360             : {
    1361           0 :         struct smbXsrv_connection *xconn =
    1362           0 :                 tevent_req_callback_data(subreq,
    1363             :                 struct smbXsrv_connection);
    1364           0 :         struct smbXsrv_client *client = xconn->client;
    1365             :         struct timeval next_check;
    1366             :         NTSTATUS status;
    1367             :         bool ok;
    1368             : 
    1369           0 :         xconn->ack.checker_subreq = NULL;
    1370             : 
    1371           0 :         ok = tevent_wakeup_recv(subreq);
    1372           0 :         TALLOC_FREE(subreq);
    1373           0 :         if (!ok) {
    1374           0 :                 smbd_server_connection_terminate(xconn,
    1375             :                                                  "tevent_wakeup_recv() failed");
    1376           0 :                 return;
    1377             :         }
    1378             : 
    1379           0 :         status = smbd_smb2_check_ack_queue(xconn);
    1380           0 :         if (!NT_STATUS_IS_OK(status)) {
    1381           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    1382           0 :                 return;
    1383             :         }
    1384             : 
    1385           0 :         next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
    1386           0 :         xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
    1387             :                                                        client->raw_ev_ctx,
    1388             :                                                        next_check);
    1389           0 :         if (xconn->ack.checker_subreq == NULL) {
    1390           0 :                 smbd_server_connection_terminate(xconn,
    1391             :                                                  "tevent_wakeup_send() failed");
    1392           0 :                 return;
    1393             :         }
    1394           0 :         tevent_req_set_callback(xconn->ack.checker_subreq,
    1395             :                                 smbXsrv_connection_ack_checker,
    1396             :                                 xconn);
    1397             : }
    1398             : 
    1399        5052 : static NTSTATUS smbXsrv_client_pending_breaks_updated(struct smbXsrv_client *client)
    1400             : {
    1401        5052 :         struct smbXsrv_connection *xconn = NULL;
    1402             : 
    1403       10156 :         for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
    1404             :                 struct timeval next_check;
    1405        5104 :                 uint64_t acked_bytes = 0;
    1406             :                 NTSTATUS status;
    1407             : 
    1408             :                 /*
    1409             :                  * A new 'pending break cycle' starts
    1410             :                  * with a first pending break and lasts until
    1411             :                  * all pending breaks are finished.
    1412             :                  *
    1413             :                  * This is typically a very short time,
    1414             :                  * the value of one retransmission timeout.
    1415             :                  */
    1416             : 
    1417        5104 :                 if (client->pending_breaks == NULL) {
    1418             :                         /*
    1419             :                          * No more pending breaks, remove a pending
    1420             :                          * checker timer
    1421             :                          */
    1422        5104 :                         TALLOC_FREE(xconn->ack.checker_subreq);
    1423        8633 :                         continue;
    1424             :                 }
    1425             : 
    1426           0 :                 if (xconn->ack.checker_subreq != NULL) {
    1427             :                         /*
    1428             :                          * The cycle already started =>
    1429             :                          * nothing todo
    1430             :                          */
    1431           0 :                         continue;
    1432             :                 }
    1433             : 
    1434             :                 /*
    1435             :                  * Get the current retransmission timeout value.
    1436             :                  *
    1437             :                  * It may change over time, but fetching it once
    1438             :                  * per 'pending break' cycled should be enough.
    1439             :                  */
    1440           0 :                 status = smbXsrv_connection_get_rto_usecs(xconn,
    1441             :                                                           &xconn->ack.rto_usecs);
    1442           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1443           0 :                         return status;
    1444             :                 }
    1445             : 
    1446             :                 /*
    1447             :                  * At the start of the cycle we reset the
    1448             :                  * unacked_bytes counter (first to 0 and
    1449             :                  * within smbXsrv_connection_get_acked_bytes()
    1450             :                  * to the current value in the kernel
    1451             :                  * send queue.
    1452             :                  */
    1453           0 :                 xconn->ack.unacked_bytes = 0;
    1454           0 :                 status = smbXsrv_connection_get_acked_bytes(xconn, &acked_bytes);
    1455           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1456           0 :                         return status;
    1457             :                 }
    1458             : 
    1459             :                 /*
    1460             :                  * We setup a timer in order to check for
    1461             :                  * acked bytes after one retransmission timeout.
    1462             :                  *
    1463             :                  * The code that sets up the send_queue.ack.timeout
    1464             :                  * uses a multiple of the retransmission timeout.
    1465             :                  */
    1466           0 :                 next_check = timeval_current_ofs_usec(xconn->ack.rto_usecs);
    1467           0 :                 xconn->ack.checker_subreq = tevent_wakeup_send(xconn,
    1468             :                                                         client->raw_ev_ctx,
    1469             :                                                         next_check);
    1470           0 :                 if (xconn->ack.checker_subreq == NULL) {
    1471           0 :                         return NT_STATUS_NO_MEMORY;
    1472             :                 }
    1473           0 :                 tevent_req_set_callback(xconn->ack.checker_subreq,
    1474             :                                         smbXsrv_connection_ack_checker,
    1475             :                                         xconn);
    1476             :         }
    1477             : 
    1478        5052 :         return NT_STATUS_OK;
    1479             : }
    1480             : 
    1481       15304 : void smbXsrv_connection_disconnect_transport(struct smbXsrv_connection *xconn,
    1482             :                                              NTSTATUS status)
    1483             : {
    1484       15304 :         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    1485        9984 :                 return;
    1486             :         }
    1487             : 
    1488        5320 :         xconn->transport.status = status;
    1489        5320 :         TALLOC_FREE(xconn->transport.fde);
    1490        5320 :         if (xconn->transport.sock != -1) {
    1491        5320 :                 xconn->transport.sock = -1;
    1492             :         }
    1493        5320 :         smbd_smb2_send_queue_ack_fail(&xconn->ack.queue, status);
    1494        5320 :         smbd_smb2_send_queue_ack_fail(&xconn->smb2.send_queue, status);
    1495        5320 :         xconn->smb2.send_queue_len = 0;
    1496        5320 :         DO_PROFILE_INC(disconnect);
    1497             : }
    1498             : 
    1499        5042 : size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
    1500             : {
    1501        5042 :         struct smbXsrv_connection *xconn = NULL;
    1502        5042 :         size_t num_ok = 0;
    1503             : 
    1504       10136 :         for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
    1505        5094 :                 if (NT_STATUS_IS_OK(xconn->transport.status)) {
    1506          52 :                         num_ok++;
    1507             :                 }
    1508             :         }
    1509             : 
    1510        5042 :         return num_ok;
    1511             : }
    1512             : 
    1513             : struct smbXsrv_connection_shutdown_state {
    1514             :         struct smbXsrv_connection *xconn;
    1515             : };
    1516             : 
    1517             : static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
    1518             : 
    1519          50 : static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
    1520             :                                         struct tevent_context *ev,
    1521             :                                         struct smbXsrv_connection *xconn)
    1522             : {
    1523          50 :         struct tevent_req *req = NULL;
    1524          50 :         struct smbXsrv_connection_shutdown_state *state = NULL;
    1525          50 :         struct tevent_req *subreq = NULL;
    1526          50 :         size_t len = 0;
    1527          50 :         struct smbd_smb2_request *preq = NULL;
    1528             :         NTSTATUS status;
    1529             : 
    1530             :         /*
    1531             :          * The caller should have called
    1532             :          * smbXsrv_connection_disconnect_transport() before.
    1533             :          */
    1534          50 :         SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
    1535          50 :         SMB_ASSERT(xconn->transport.terminating);
    1536          50 :         SMB_ASSERT(xconn->transport.shutdown_wait_queue == NULL);
    1537             : 
    1538          50 :         req = tevent_req_create(mem_ctx, &state,
    1539             :                                 struct smbXsrv_connection_shutdown_state);
    1540          50 :         if (req == NULL) {
    1541           0 :                 return NULL;
    1542             :         }
    1543             : 
    1544          50 :         state->xconn = xconn;
    1545          50 :         tevent_req_defer_callback(req, ev);
    1546             : 
    1547          50 :         xconn->transport.shutdown_wait_queue =
    1548          50 :                 tevent_queue_create(state, "smbXsrv_connection_shutdown_queue");
    1549          50 :         if (tevent_req_nomem(xconn->transport.shutdown_wait_queue, req)) {
    1550           0 :                 return tevent_req_post(req, ev);
    1551             :         }
    1552             : 
    1553          50 :         for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
    1554             :                 /*
    1555             :                  * Now wait until the request is finished.
    1556             :                  *
    1557             :                  * We don't set a callback, as we just want to block the
    1558             :                  * wait queue and the talloc_free() of the request will
    1559             :                  * remove the item from the wait queue.
    1560             :                  *
    1561             :                  * Note that we don't cancel the requests here
    1562             :                  * in order to keep the replay detection logic correct.
    1563             :                  *
    1564             :                  * However if we teardown the last channel of
    1565             :                  * a connection, we'll call some logic via
    1566             :                  * smbXsrv_session_disconnect_xconn()
    1567             :                  * -> smbXsrv_session_disconnect_xconn_callback()
    1568             :                  *   -> smbXsrv_session_remove_channel()
    1569             :                  *     -> smb2srv_session_shutdown_send()
    1570             :                  * will indeed cancel the request.
    1571             :                  */
    1572           0 :                 subreq = tevent_queue_wait_send(preq, ev,
    1573             :                                         xconn->transport.shutdown_wait_queue);
    1574           0 :                 if (tevent_req_nomem(subreq, req)) {
    1575           0 :                         return tevent_req_post(req, ev);
    1576             :                 }
    1577             :         }
    1578             : 
    1579             :         /*
    1580             :          * This may attach sessions with num_channels == 0
    1581             :          * to xconn->transport.shutdown_wait_queue.
    1582             :          */
    1583          50 :         status = smbXsrv_session_disconnect_xconn(xconn);
    1584          50 :         if (tevent_req_nterror(req, status)) {
    1585           0 :                 return tevent_req_post(req, ev);
    1586             :         }
    1587             : 
    1588          50 :         len = tevent_queue_length(xconn->transport.shutdown_wait_queue);
    1589          50 :         if (len == 0) {
    1590          48 :                 tevent_req_done(req);
    1591          48 :                 return tevent_req_post(req, ev);
    1592             :         }
    1593             : 
    1594             :         /*
    1595             :          * Now we add our own waiter to the end of the queue,
    1596             :          * this way we get notified when all pending requests are finished
    1597             :          * and send to the socket.
    1598             :          */
    1599           2 :         subreq = tevent_queue_wait_send(state, ev, xconn->transport.shutdown_wait_queue);
    1600           2 :         if (tevent_req_nomem(subreq, req)) {
    1601           0 :                 return tevent_req_post(req, ev);
    1602             :         }
    1603           2 :         tevent_req_set_callback(subreq, smbXsrv_connection_shutdown_wait_done, req);
    1604             : 
    1605           2 :         return req;
    1606             : }
    1607             : 
    1608           2 : static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
    1609             : {
    1610           1 :         struct tevent_req *req =
    1611           2 :                 tevent_req_callback_data(subreq,
    1612             :                 struct tevent_req);
    1613           1 :         struct smbXsrv_connection_shutdown_state *state =
    1614           2 :                 tevent_req_data(req,
    1615             :                 struct smbXsrv_connection_shutdown_state);
    1616           2 :         struct smbXsrv_connection *xconn = state->xconn;
    1617             : 
    1618           2 :         tevent_queue_wait_recv(subreq);
    1619           2 :         TALLOC_FREE(subreq);
    1620             : 
    1621           2 :         tevent_req_done(req);
    1622             :         /*
    1623             :          * make sure the xconn pointer is still valid,
    1624             :          * it should as we used tevent_req_defer_callback()
    1625             :          */
    1626           2 :         SMB_ASSERT(xconn->transport.terminating);
    1627           2 : }
    1628             : 
    1629          50 : static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
    1630             : {
    1631          25 :         struct smbXsrv_connection_shutdown_state *state =
    1632          50 :                 tevent_req_data(req,
    1633             :                 struct smbXsrv_connection_shutdown_state);
    1634          50 :         struct smbXsrv_connection *xconn = state->xconn;
    1635             :         /*
    1636             :          * make sure the xconn pointer is still valid,
    1637             :          * it should as we used tevent_req_defer_callback()
    1638             :          */
    1639          50 :         SMB_ASSERT(xconn->transport.terminating);
    1640          50 :         return tevent_req_simple_recv_ntstatus(req);
    1641             : }
    1642             : 
    1643          50 : static void smbd_server_connection_terminate_done(struct tevent_req *subreq)
    1644             : {
    1645          25 :         struct smbXsrv_connection *xconn =
    1646          50 :                 tevent_req_callback_data(subreq,
    1647             :                 struct smbXsrv_connection);
    1648          50 :         struct smbXsrv_client *client = xconn->client;
    1649             :         NTSTATUS status;
    1650             : 
    1651          50 :         status = smbXsrv_connection_shutdown_recv(subreq);
    1652          50 :         TALLOC_FREE(subreq);
    1653          50 :         if (!NT_STATUS_IS_OK(status)) {
    1654           0 :                 exit_server("smbXsrv_connection_shutdown_recv failed");
    1655             :         }
    1656             : 
    1657          50 :         DLIST_REMOVE(client->connections, xconn);
    1658          50 :         TALLOC_FREE(xconn);
    1659          50 : }
    1660             : 
    1661        5042 : void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
    1662             :                                          const char *reason,
    1663             :                                          const char *location)
    1664             : {
    1665        5042 :         struct smbXsrv_client *client = xconn->client;
    1666        5042 :         size_t num_ok = 0;
    1667             : 
    1668             :         /*
    1669             :          * Make sure that no new request will be able to use this session.
    1670             :          *
    1671             :          * smbXsrv_connection_disconnect_transport() might be called already,
    1672             :          * but calling it again is a no-op.
    1673             :          */
    1674        5042 :         smbXsrv_connection_disconnect_transport(xconn,
    1675        5042 :                                         NT_STATUS_CONNECTION_DISCONNECTED);
    1676             : 
    1677        5042 :         num_ok = smbXsrv_client_valid_connections(client);
    1678             : 
    1679        5042 :         if (xconn->transport.terminating) {
    1680           0 :                 DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
    1681             :                           smbXsrv_connection_dbg(xconn), num_ok,
    1682             :                           reason, location);
    1683           0 :                 return;
    1684             :         }
    1685        5042 :         xconn->transport.terminating = true;
    1686             : 
    1687        5042 :         DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
    1688             :                   smbXsrv_connection_dbg(xconn), num_ok,
    1689             :                   reason, location);
    1690             : 
    1691        5042 :         if (xconn->has_cluster_movable_ip) {
    1692             :                 /*
    1693             :                  * If the connection has a movable cluster public address
    1694             :                  * we disconnect all client connections,
    1695             :                  * as the public address might be moved to
    1696             :                  * a different node.
    1697             :                  *
    1698             :                  * In future we may recheck which node currently
    1699             :                  * holds this address, but for now we keep it simple.
    1700             :                  */
    1701           0 :                 smbd_server_disconnect_client_ex(xconn->client,
    1702             :                                                  reason,
    1703             :                                                  location);
    1704           0 :                 return;
    1705             :         }
    1706             : 
    1707        5042 :         if (num_ok != 0) {
    1708          50 :                 struct tevent_req *subreq = NULL;
    1709             : 
    1710          50 :                 subreq = smbXsrv_connection_shutdown_send(client,
    1711             :                                                           client->raw_ev_ctx,
    1712             :                                                           xconn);
    1713          50 :                 if (subreq == NULL) {
    1714           0 :                         exit_server("smbXsrv_connection_shutdown_send failed");
    1715             :                 }
    1716          50 :                 tevent_req_set_callback(subreq,
    1717             :                                         smbd_server_connection_terminate_done,
    1718             :                                         xconn);
    1719          50 :                 return;
    1720             :         }
    1721             : 
    1722             :         /*
    1723             :          * The last connection was disconnected
    1724             :          */
    1725        4992 :         exit_server_cleanly(reason);
    1726             : }
    1727             : 
    1728           0 : void smbd_server_disconnect_client_ex(struct smbXsrv_client *client,
    1729             :                                       const char *reason,
    1730             :                                       const char *location)
    1731             : {
    1732           0 :         size_t num_ok = 0;
    1733             : 
    1734           0 :         num_ok = smbXsrv_client_valid_connections(client);
    1735             : 
    1736           0 :         DBG_WARNING("client[%s] num_ok[%zu] reason[%s] at %s\n",
    1737             :                     client->global->remote_address, num_ok,
    1738             :                     reason, location);
    1739             : 
    1740             :         /*
    1741             :          * Something bad happened we need to disconnect all connections.
    1742             :          */
    1743           0 :         exit_server_cleanly(reason);
    1744             : }
    1745             : 
    1746           0 : static bool dup_smb2_vec4(TALLOC_CTX *ctx,
    1747             :                         struct iovec *outvec,
    1748             :                         const struct iovec *srcvec)
    1749             : {
    1750             :         const uint8_t *srctf;
    1751             :         size_t srctf_len;
    1752             :         const uint8_t *srchdr;
    1753             :         size_t srchdr_len;
    1754             :         const uint8_t *srcbody;
    1755             :         size_t srcbody_len;
    1756             :         const uint8_t *expected_srcbody;
    1757             :         const uint8_t *srcdyn;
    1758             :         size_t srcdyn_len;
    1759             :         const uint8_t *expected_srcdyn;
    1760             :         uint8_t *dsttf;
    1761             :         uint8_t *dsthdr;
    1762             :         uint8_t *dstbody;
    1763             :         uint8_t *dstdyn;
    1764             : 
    1765           0 :         srctf  = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
    1766           0 :         srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
    1767           0 :         srchdr  = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
    1768           0 :         srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
    1769           0 :         srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
    1770           0 :         srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len;
    1771           0 :         expected_srcbody = srchdr + SMB2_HDR_BODY;
    1772           0 :         srcdyn  = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base;
    1773           0 :         srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
    1774           0 :         expected_srcdyn = srcbody + 8;
    1775             : 
    1776           0 :         if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
    1777           0 :                 return false;
    1778             :         }
    1779             : 
    1780           0 :         if (srchdr_len != SMB2_HDR_BODY) {
    1781           0 :                 return false;
    1782             :         }
    1783             : 
    1784           0 :         if (srctf_len == SMB2_TF_HDR_SIZE) {
    1785           0 :                 dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
    1786           0 :                 if (dsttf == NULL) {
    1787           0 :                         return false;
    1788             :                 }
    1789             :         } else {
    1790           0 :                 dsttf = NULL;
    1791             :         }
    1792           0 :         outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
    1793           0 :         outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
    1794             : 
    1795             :         /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
    1796             :          * be allocated with size OUTVEC_ALLOC_SIZE. */
    1797             : 
    1798           0 :         dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE);
    1799           0 :         if (dsthdr == NULL) {
    1800           0 :                 return false;
    1801             :         }
    1802           0 :         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr;
    1803           0 :         outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY;
    1804             : 
    1805             :         /*
    1806             :          * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8,
    1807             :          * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY,
    1808             :          * then duplicate this. Else use talloc_memdup().
    1809             :          */
    1810             : 
    1811           0 :         if ((srcbody == expected_srcbody) && (srcbody_len == 8)) {
    1812           0 :                 dstbody = dsthdr + SMB2_HDR_BODY;
    1813             :         } else {
    1814           0 :                 dstbody = talloc_memdup(ctx, srcbody, srcbody_len);
    1815           0 :                 if (dstbody == NULL) {
    1816           0 :                         return false;
    1817             :                 }
    1818             :         }
    1819           0 :         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody;
    1820           0 :         outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len;
    1821             : 
    1822             :         /*
    1823             :          * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1,
    1824             :          * pointing to
    1825             :          * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8
    1826             :          * then duplicate this. Else use talloc_memdup().
    1827             :          */
    1828             : 
    1829           0 :         if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) {
    1830           0 :                 dstdyn = dsthdr + SMB2_HDR_BODY + 8;
    1831           0 :         } else if (srcdyn == NULL) {
    1832           0 :                 dstdyn = NULL;
    1833             :         } else {
    1834           0 :                 dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len);
    1835           0 :                 if (dstdyn == NULL) {
    1836           0 :                         return false;
    1837             :                 }
    1838             :         }
    1839           0 :         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn;
    1840           0 :         outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len;
    1841             : 
    1842           0 :         return true;
    1843             : }
    1844             : 
    1845           0 : static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *req)
    1846             : {
    1847           0 :         struct smbd_smb2_request *newreq = NULL;
    1848           0 :         struct iovec *outvec = NULL;
    1849           0 :         int count = req->out.vector_count;
    1850             :         int i;
    1851             :         bool ok;
    1852             : 
    1853           0 :         newreq = smbd_smb2_request_allocate(req->xconn);
    1854           0 :         if (!newreq) {
    1855           0 :                 return NULL;
    1856             :         }
    1857             : 
    1858           0 :         newreq->sconn = req->sconn;
    1859           0 :         newreq->xconn = req->xconn;
    1860           0 :         newreq->session = req->session;
    1861           0 :         newreq->do_encryption = req->do_encryption;
    1862           0 :         newreq->do_signing = req->do_signing;
    1863           0 :         newreq->current_idx = req->current_idx;
    1864             : 
    1865           0 :         outvec = talloc_zero_array(newreq, struct iovec, count);
    1866           0 :         if (!outvec) {
    1867           0 :                 TALLOC_FREE(newreq);
    1868           0 :                 return NULL;
    1869             :         }
    1870           0 :         newreq->out.vector = outvec;
    1871           0 :         newreq->out.vector_count = count;
    1872             : 
    1873             :         /* Setup the outvec's identically to req. */
    1874           0 :         outvec[0].iov_base = newreq->out.nbt_hdr;
    1875           0 :         outvec[0].iov_len = 4;
    1876           0 :         memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
    1877             : 
    1878             :         /* Setup the vectors identically to the ones in req. */
    1879           0 :         for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
    1880           0 :                 if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
    1881           0 :                         break;
    1882             :                 }
    1883             :         }
    1884             : 
    1885           0 :         if (i < count) {
    1886             :                 /* Alloc failed. */
    1887           0 :                 TALLOC_FREE(newreq);
    1888           0 :                 return NULL;
    1889             :         }
    1890             : 
    1891           0 :         ok = smb2_setup_nbt_length(newreq->out.vector,
    1892             :                                    newreq->out.vector_count);
    1893           0 :         if (!ok) {
    1894           0 :                 TALLOC_FREE(newreq);
    1895           0 :                 return NULL;
    1896             :         }
    1897             : 
    1898           0 :         return newreq;
    1899             : }
    1900             : 
    1901           0 : static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
    1902             : {
    1903           0 :         struct smbXsrv_connection *xconn = req->xconn;
    1904           0 :         int first_idx = 1;
    1905           0 :         struct iovec *firsttf = NULL;
    1906           0 :         struct iovec *outhdr_v = NULL;
    1907           0 :         uint8_t *outhdr = NULL;
    1908           0 :         struct smbd_smb2_request *nreq = NULL;
    1909             :         NTSTATUS status;
    1910             :         bool ok;
    1911             : 
    1912             :         /* Create a new smb2 request we'll use
    1913             :            for the interim return. */
    1914           0 :         nreq = dup_smb2_req(req);
    1915           0 :         if (!nreq) {
    1916           0 :                 return NT_STATUS_NO_MEMORY;
    1917             :         }
    1918             : 
    1919             :         /* Lose the last X out vectors. They're the
    1920             :            ones we'll be using for the async reply. */
    1921           0 :         nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
    1922             : 
    1923           0 :         ok = smb2_setup_nbt_length(nreq->out.vector,
    1924             :                                    nreq->out.vector_count);
    1925           0 :         if (!ok) {
    1926           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1927             :         }
    1928             : 
    1929             :         /* Step back to the previous reply. */
    1930           0 :         nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
    1931           0 :         firsttf = SMBD_SMB2_IDX_TF_IOV(nreq,out,first_idx);
    1932           0 :         outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
    1933           0 :         outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
    1934             :         /* And end the chain. */
    1935           0 :         SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
    1936             : 
    1937             :         /* Calculate outgoing credits */
    1938           0 :         smb2_calculate_credits(req, nreq);
    1939             : 
    1940           0 :         if (DEBUGLEVEL >= 10) {
    1941           0 :                 dbgtext("smb2_send_async_interim_response: nreq->current_idx = %u\n",
    1942           0 :                         (unsigned int)nreq->current_idx );
    1943           0 :                 dbgtext("smb2_send_async_interim_response: returning %u vectors\n",
    1944           0 :                         (unsigned int)nreq->out.vector_count );
    1945           0 :                 print_req_vectors(nreq);
    1946             :         }
    1947             : 
    1948             :         /*
    1949             :          * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
    1950             :          * we need to sign/encrypt here with the last/first key we remembered
    1951             :          */
    1952           0 :         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
    1953           0 :                 status = smb2_signing_encrypt_pdu(req->first_enc_key,
    1954             :                                         firsttf,
    1955           0 :                                         nreq->out.vector_count - first_idx);
    1956           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1957           0 :                         return status;
    1958             :                 }
    1959           0 :         } else if (smb2_signing_key_valid(req->last_sign_key)) {
    1960           0 :                 status = smb2_signing_sign_pdu(req->last_sign_key,
    1961             :                                                outhdr_v,
    1962             :                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
    1963           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1964           0 :                         return status;
    1965             :                 }
    1966             :         }
    1967             : 
    1968           0 :         nreq->queue_entry.mem_ctx = nreq;
    1969           0 :         nreq->queue_entry.vector = nreq->out.vector;
    1970           0 :         nreq->queue_entry.count = nreq->out.vector_count;
    1971           0 :         DLIST_ADD_END(xconn->smb2.send_queue, &nreq->queue_entry);
    1972           0 :         xconn->smb2.send_queue_len++;
    1973             : 
    1974           0 :         status = smbd_smb2_flush_send_queue(xconn);
    1975           0 :         if (!NT_STATUS_IS_OK(status)) {
    1976           0 :                 return status;
    1977             :         }
    1978             : 
    1979           0 :         return NT_STATUS_OK;
    1980             : }
    1981             : 
    1982             : struct smbd_smb2_request_pending_state {
    1983             :         struct smbd_smb2_send_queue queue_entry;
    1984             :         uint8_t buf[NBT_HDR_SIZE + SMB2_TF_HDR_SIZE + SMB2_HDR_BODY + 0x08 + 1];
    1985             :         struct iovec vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
    1986             : };
    1987             : 
    1988             : static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
    1989             :                                             struct tevent_timer *te,
    1990             :                                             struct timeval current_time,
    1991             :                                             void *private_data);
    1992             : 
    1993      148445 : NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
    1994             :                                          struct tevent_req *subreq,
    1995             :                                          uint32_t defer_time)
    1996             : {
    1997             :         NTSTATUS status;
    1998             :         struct timeval defer_endtime;
    1999      148445 :         uint8_t *outhdr = NULL;
    2000             :         uint32_t flags;
    2001             : 
    2002      148445 :         if (!tevent_req_is_in_progress(subreq)) {
    2003             :                 /*
    2004             :                  * This is a performance optimization,
    2005             :                  * it avoids one tevent_loop iteration,
    2006             :                  * which means we avoid one
    2007             :                  * talloc_stackframe_pool/talloc_free pair.
    2008             :                  */
    2009       48960 :                 tevent_req_notify_callback(subreq);
    2010       46468 :                 return NT_STATUS_OK;
    2011             :         }
    2012             : 
    2013       99485 :         req->subreq = subreq;
    2014       99485 :         subreq = NULL;
    2015             : 
    2016       99485 :         if (req->async_te) {
    2017             :                 /* We're already async. */
    2018           0 :                 return NT_STATUS_OK;
    2019             :         }
    2020             : 
    2021       99485 :         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
    2022       99485 :         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
    2023       99485 :         if (flags & SMB2_HDR_FLAG_ASYNC) {
    2024             :                 /* We're already async. */
    2025           0 :                 return NT_STATUS_OK;
    2026             :         }
    2027             : 
    2028       99485 :         if (req->async_internal || defer_time == 0) {
    2029             :                 /*
    2030             :                  * An SMB2 request implementation wants to handle the request
    2031             :                  * asynchronously "internally" while keeping synchronous
    2032             :                  * behaviour for the SMB2 request. This means we don't send an
    2033             :                  * interim response and we can allow processing of compound SMB2
    2034             :                  * requests (cf the subsequent check) for all cases.
    2035             :                  */
    2036        9172 :                 return NT_STATUS_OK;
    2037             :         }
    2038             : 
    2039       90313 :         if (req->in.vector_count > req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) {
    2040             :                 /*
    2041             :                  * We're trying to go async in a compound request
    2042             :                  * chain. This is only allowed for opens that cause an
    2043             :                  * oplock break or for the last operation in the
    2044             :                  * chain, otherwise it is not allowed. See
    2045             :                  * [MS-SMB2].pdf note <206> on Section 3.3.5.2.7.
    2046             :                  */
    2047           0 :                 const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2048             : 
    2049           0 :                 if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) {
    2050             :                         /*
    2051             :                          * Cancel the outstanding request.
    2052             :                          */
    2053           0 :                         bool ok = tevent_req_cancel(req->subreq);
    2054           0 :                         if (ok) {
    2055           0 :                                 return NT_STATUS_OK;
    2056             :                         }
    2057           0 :                         TALLOC_FREE(req->subreq);
    2058           0 :                         return smbd_smb2_request_error(req,
    2059             :                                 NT_STATUS_INTERNAL_ERROR);
    2060             :                 }
    2061             :         }
    2062             : 
    2063       90313 :         if (DEBUGLEVEL >= 10) {
    2064           0 :                 dbgtext("smbd_smb2_request_pending_queue: req->current_idx = %u\n",
    2065           0 :                         (unsigned int)req->current_idx );
    2066           0 :                 print_req_vectors(req);
    2067             :         }
    2068             : 
    2069       90313 :         if (req->current_idx > 1) {
    2070             :                 /*
    2071             :                  * We're going async in a compound
    2072             :                  * chain after the first request has
    2073             :                  * already been processed. Send an
    2074             :                  * interim response containing the
    2075             :                  * set of replies already generated.
    2076             :                  */
    2077           0 :                 int idx = req->current_idx;
    2078             : 
    2079           0 :                 status = smb2_send_async_interim_response(req);
    2080           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2081           0 :                         return status;
    2082             :                 }
    2083           0 :                 TALLOC_FREE(req->first_enc_key);
    2084             : 
    2085           0 :                 req->current_idx = 1;
    2086             : 
    2087             :                 /*
    2088             :                  * Re-arrange the in.vectors to remove what
    2089             :                  * we just sent.
    2090             :                  */
    2091           0 :                 memmove(&req->in.vector[1],
    2092           0 :                         &req->in.vector[idx],
    2093           0 :                         sizeof(req->in.vector[0])*(req->in.vector_count - idx));
    2094           0 :                 req->in.vector_count = 1 + (req->in.vector_count - idx);
    2095             : 
    2096             :                 /* Re-arrange the out.vectors to match. */
    2097           0 :                 memmove(&req->out.vector[1],
    2098           0 :                         &req->out.vector[idx],
    2099           0 :                         sizeof(req->out.vector[0])*(req->out.vector_count - idx));
    2100           0 :                 req->out.vector_count = 1 + (req->out.vector_count - idx);
    2101             : 
    2102           0 :                 if (req->in.vector_count == 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
    2103             :                         /*
    2104             :                          * We only have one remaining request as
    2105             :                          * we've processed everything else.
    2106             :                          * This is no longer a compound request.
    2107             :                          */
    2108           0 :                         req->compound_related = false;
    2109           0 :                         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
    2110           0 :                         flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
    2111           0 :                         SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
    2112             :                 }
    2113             :         }
    2114       90313 :         TALLOC_FREE(req->last_sign_key);
    2115             : 
    2116             :         /*
    2117             :          * smbd_smb2_request_pending_timer() just send a packet
    2118             :          * to the client and doesn't need any impersonation.
    2119             :          * So we use req->xconn->client->raw_ev_ctx instead
    2120             :          * of req->ev_ctx here.
    2121             :          */
    2122       90313 :         defer_endtime = timeval_current_ofs_usec(defer_time);
    2123       90313 :         req->async_te = tevent_add_timer(req->xconn->client->raw_ev_ctx,
    2124             :                                          req, defer_endtime,
    2125             :                                          smbd_smb2_request_pending_timer,
    2126             :                                          req);
    2127       90313 :         if (req->async_te == NULL) {
    2128           0 :                 return NT_STATUS_NO_MEMORY;
    2129             :         }
    2130             : 
    2131       90313 :         return NT_STATUS_OK;
    2132             : }
    2133             : 
    2134             : static
    2135      254739 : struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
    2136             :                                                struct smbXsrv_connection *xconn,
    2137             :                                                bool *_has_channel)
    2138             : {
    2139      254739 :         struct smbXsrv_channel_global0 *c = NULL;
    2140             :         NTSTATUS status;
    2141      254739 :         struct smb2_signing_key *key = NULL;
    2142      254739 :         bool has_channel = false;
    2143             : 
    2144      254739 :         status = smbXsrv_session_find_channel(session, xconn, &c);
    2145      254739 :         if (NT_STATUS_IS_OK(status)) {
    2146      254223 :                 key = c->signing_key;
    2147      254223 :                 has_channel = true;
    2148             :         }
    2149             : 
    2150      254739 :         if (!smb2_signing_key_valid(key)) {
    2151         520 :                 key = session->global->signing_key;
    2152         520 :                 has_channel = false;
    2153             :         }
    2154             : 
    2155      254739 :         if (_has_channel != NULL) {
    2156      125173 :                 *_has_channel = has_channel;
    2157             :         }
    2158             : 
    2159      254739 :         return key;
    2160             : }
    2161             : 
    2162         635 : static NTSTATUS smb2_get_new_nonce(struct smbXsrv_session *session,
    2163             :                                    uint64_t *new_nonce_high,
    2164             :                                    uint64_t *new_nonce_low)
    2165             : {
    2166             :         uint64_t nonce_high;
    2167             :         uint64_t nonce_low;
    2168             : 
    2169         635 :         session->nonce_low += 1;
    2170         635 :         if (session->nonce_low == 0) {
    2171           0 :                 session->nonce_low += 1;
    2172           0 :                 session->nonce_high += 1;
    2173             :         }
    2174             : 
    2175             :         /*
    2176             :          * CCM and GCM algorithms must never have their
    2177             :          * nonce wrap, or the security of the whole
    2178             :          * communication and the keys is destroyed.
    2179             :          * We must drop the connection once we have
    2180             :          * transfered too much data.
    2181             :          *
    2182             :          * NOTE: We assume nonces greater than 8 bytes.
    2183             :          */
    2184         635 :         if (session->nonce_high >= session->nonce_high_max) {
    2185           0 :                 return NT_STATUS_ENCRYPTION_FAILED;
    2186             :         }
    2187             : 
    2188         635 :         nonce_high = session->nonce_high_random;
    2189         635 :         nonce_high += session->nonce_high;
    2190         635 :         nonce_low = session->nonce_low;
    2191             : 
    2192         635 :         *new_nonce_high = nonce_high;
    2193         635 :         *new_nonce_low = nonce_low;
    2194         635 :         return NT_STATUS_OK;
    2195             : }
    2196             : 
    2197       21646 : static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
    2198             :                                             struct tevent_timer *te,
    2199             :                                             struct timeval current_time,
    2200             :                                             void *private_data)
    2201             : {
    2202       19645 :         struct smbd_smb2_request *req =
    2203        2001 :                 talloc_get_type_abort(private_data,
    2204             :                 struct smbd_smb2_request);
    2205       21646 :         struct smbXsrv_connection *xconn = req->xconn;
    2206       21646 :         struct smbd_smb2_request_pending_state *state = NULL;
    2207       21646 :         uint8_t *outhdr = NULL;
    2208       21646 :         const uint8_t *inhdr = NULL;
    2209       21646 :         uint8_t *tf = NULL;
    2210       21646 :         uint8_t *hdr = NULL;
    2211       21646 :         uint8_t *body = NULL;
    2212       21646 :         uint8_t *dyn = NULL;
    2213       21646 :         uint32_t flags = 0;
    2214       21646 :         uint64_t message_id = 0;
    2215       21646 :         uint64_t async_id = 0;
    2216             :         NTSTATUS status;
    2217             :         bool ok;
    2218             : 
    2219       21646 :         TALLOC_FREE(req->async_te);
    2220             : 
    2221             :         /* Ensure our final reply matches the interim one. */
    2222       21646 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2223       21646 :         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
    2224       21646 :         flags = IVAL(outhdr, SMB2_HDR_FLAGS);
    2225       21646 :         message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
    2226             : 
    2227       21646 :         async_id = message_id; /* keep it simple for now... */
    2228             : 
    2229       21646 :         SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
    2230       21646 :         SBVAL(outhdr, SMB2_HDR_ASYNC_ID, async_id);
    2231             : 
    2232       21646 :         DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu "
    2233             :                 "going async\n",
    2234             :                 smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
    2235             :                 (unsigned long long)async_id ));
    2236             : 
    2237             :         /*
    2238             :          * What we send is identical to a smbd_smb2_request_error
    2239             :          * packet with an error status of STATUS_PENDING. Make use
    2240             :          * of this fact sometime when refactoring. JRA.
    2241             :          */
    2242             : 
    2243       21646 :         state = talloc_zero(req->xconn, struct smbd_smb2_request_pending_state);
    2244       21646 :         if (state == NULL) {
    2245           0 :                 smbd_server_connection_terminate(xconn,
    2246             :                                                  nt_errstr(NT_STATUS_NO_MEMORY));
    2247           0 :                 return;
    2248             :         }
    2249             : 
    2250       21646 :         tf = state->buf + NBT_HDR_SIZE;
    2251             : 
    2252       21646 :         hdr = tf + SMB2_TF_HDR_SIZE;
    2253       21646 :         body = hdr + SMB2_HDR_BODY;
    2254       21646 :         dyn = body + 8;
    2255             : 
    2256       21646 :         if (req->do_encryption) {
    2257          21 :                 uint64_t nonce_high = 0;
    2258          21 :                 uint64_t nonce_low = 0;
    2259          21 :                 uint64_t session_id = req->session->global->session_wire_id;
    2260             : 
    2261          21 :                 status = smb2_get_new_nonce(req->session,
    2262             :                                             &nonce_high,
    2263             :                                             &nonce_low);
    2264          21 :                 if (!NT_STATUS_IS_OK(status)) {
    2265           0 :                         smbd_server_connection_terminate(xconn,
    2266             :                                                          nt_errstr(status));
    2267           0 :                         return;
    2268             :                 }
    2269             : 
    2270          21 :                 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
    2271          21 :                 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
    2272          21 :                 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
    2273          21 :                 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
    2274             :         }
    2275             : 
    2276       21646 :         SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
    2277       21646 :         SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
    2278       21646 :         SSVAL(hdr, SMB2_HDR_EPOCH, 0);
    2279       21646 :         SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(NT_STATUS_PENDING));
    2280       21646 :         SSVAL(hdr, SMB2_HDR_OPCODE, SVAL(outhdr, SMB2_HDR_OPCODE));
    2281             : 
    2282             :         /*
    2283             :          * The STATUS_PENDING response has SMB2_HDR_FLAG_SIGNED
    2284             :          * clearedm, but echoes the signature field.
    2285             :          */
    2286       21646 :         flags &= ~SMB2_HDR_FLAG_SIGNED;
    2287       21646 :         SIVAL(hdr, SMB2_HDR_FLAGS, flags);
    2288       21646 :         SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
    2289       21646 :         SBVAL(hdr, SMB2_HDR_MESSAGE_ID, message_id);
    2290       21646 :         SBVAL(hdr, SMB2_HDR_PID, async_id);
    2291       21646 :         SBVAL(hdr, SMB2_HDR_SESSION_ID,
    2292             :                 BVAL(outhdr, SMB2_HDR_SESSION_ID));
    2293       21646 :         memcpy(hdr+SMB2_HDR_SIGNATURE,
    2294       21646 :                outhdr+SMB2_HDR_SIGNATURE, 16);
    2295             : 
    2296       21646 :         SSVAL(body, 0x00, 0x08 + 1);
    2297             : 
    2298       21646 :         SCVAL(body, 0x02, 0);
    2299       21646 :         SCVAL(body, 0x03, 0);
    2300       21646 :         SIVAL(body, 0x04, 0);
    2301             :         /* Match W2K8R2... */
    2302       21646 :         SCVAL(dyn,  0x00, 0x21);
    2303             : 
    2304       21646 :         state->vector[0].iov_base = (void *)state->buf;
    2305       21646 :         state->vector[0].iov_len = NBT_HDR_SIZE;
    2306             : 
    2307       21646 :         if (req->do_encryption) {
    2308          21 :                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
    2309          21 :                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    =
    2310             :                                                         SMB2_TF_HDR_SIZE;
    2311             :         } else {
    2312       21625 :                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
    2313       21625 :                 state->vector[1+SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
    2314             :         }
    2315             : 
    2316       21646 :         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
    2317       21646 :         state->vector[1+SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
    2318             : 
    2319       21646 :         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
    2320       21646 :         state->vector[1+SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
    2321             : 
    2322       21646 :         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
    2323       21646 :         state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = 1;
    2324             : 
    2325       21646 :         ok = smb2_setup_nbt_length(state->vector,
    2326             :                                    1 + SMBD_SMB2_NUM_IOV_PER_REQ);
    2327       21646 :         if (!ok) {
    2328           0 :                 smbd_server_connection_terminate(
    2329             :                         xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
    2330           0 :                 return;
    2331             :         }
    2332             : 
    2333             :         /* Ensure we correctly go through crediting. Grant
    2334             :            the credits now, and zero credits on the final
    2335             :            response. */
    2336       60936 :         smb2_set_operation_credit(req->xconn,
    2337       41291 :                         SMBD_SMB2_IN_HDR_IOV(req),
    2338             :                         &state->vector[1+SMBD_SMB2_HDR_IOV_OFS]);
    2339             : 
    2340             :         /*
    2341             :          * We add SMB2_HDR_FLAG_ASYNC after smb2_set_operation_credit()
    2342             :          * as it reacts on it
    2343             :          */
    2344       21646 :         SIVAL(hdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
    2345             : 
    2346       21646 :         if (DEBUGLVL(10)) {
    2347             :                 int i;
    2348             : 
    2349           0 :                 for (i = 0; i < ARRAY_SIZE(state->vector); i++) {
    2350           0 :                         dbgtext("\tstate->vector[%u/%u].iov_len = %u\n",
    2351             :                                 (unsigned int)i,
    2352             :                                 (unsigned int)ARRAY_SIZE(state->vector),
    2353           0 :                                 (unsigned int)state->vector[i].iov_len);
    2354             :                 }
    2355             :         }
    2356             : 
    2357       21646 :         if (req->do_encryption) {
    2358          21 :                 struct smbXsrv_session *x = req->session;
    2359          21 :                 struct smb2_signing_key *encryption_key = x->global->encryption_key;
    2360             : 
    2361          21 :                 status = smb2_signing_encrypt_pdu(encryption_key,
    2362             :                                         &state->vector[1+SMBD_SMB2_TF_IOV_OFS],
    2363             :                                         SMBD_SMB2_NUM_IOV_PER_REQ);
    2364          21 :                 if (!NT_STATUS_IS_OK(status)) {
    2365           0 :                         smbd_server_connection_terminate(xconn,
    2366             :                                                 nt_errstr(status));
    2367           0 :                         return;
    2368             :                 }
    2369             :         }
    2370             : 
    2371       21646 :         state->queue_entry.mem_ctx = state;
    2372       21646 :         state->queue_entry.vector = state->vector;
    2373       21646 :         state->queue_entry.count = ARRAY_SIZE(state->vector);
    2374       21646 :         DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
    2375       21646 :         xconn->smb2.send_queue_len++;
    2376             : 
    2377       21646 :         status = smbd_smb2_flush_send_queue(xconn);
    2378       21646 :         if (!NT_STATUS_IS_OK(status)) {
    2379           0 :                 smbd_server_connection_terminate(xconn,
    2380             :                                                  nt_errstr(status));
    2381           0 :                 return;
    2382             :         }
    2383             : }
    2384             : 
    2385          18 : static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
    2386             : {
    2387          18 :         struct smbXsrv_connection *xconn = req->xconn;
    2388             :         struct smbd_smb2_request *cur;
    2389             :         const uint8_t *inhdr;
    2390             :         uint32_t flags;
    2391             :         uint64_t search_message_id;
    2392             :         uint64_t search_async_id;
    2393             :         uint64_t found_id;
    2394             : 
    2395          18 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2396             : 
    2397          18 :         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
    2398          18 :         search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
    2399          18 :         search_async_id = BVAL(inhdr, SMB2_HDR_PID);
    2400             : 
    2401             :         /*
    2402             :          * We don't need the request anymore cancel requests never
    2403             :          * have a response.
    2404             :          *
    2405             :          * We defer the TALLOC_FREE(req) to the caller.
    2406             :          */
    2407          18 :         DLIST_REMOVE(xconn->smb2.requests, req);
    2408             : 
    2409          18 :         for (cur = xconn->smb2.requests; cur; cur = cur->next) {
    2410             :                 const uint8_t *outhdr;
    2411             :                 uint64_t message_id;
    2412             :                 uint64_t async_id;
    2413             : 
    2414          18 :                 if (cur->session != req->session) {
    2415           0 :                         continue;
    2416             :                 }
    2417             : 
    2418          18 :                 if (cur->compound_related) {
    2419             :                         /*
    2420             :                          * Never cancel anything in a compound request.
    2421             :                          * Way too hard to deal with the result.
    2422             :                          */
    2423           0 :                         continue;
    2424             :                 }
    2425             : 
    2426          18 :                 outhdr = SMBD_SMB2_OUT_HDR_PTR(cur);
    2427             : 
    2428          18 :                 message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
    2429          18 :                 async_id = BVAL(outhdr, SMB2_HDR_PID);
    2430             : 
    2431          18 :                 if (flags & SMB2_HDR_FLAG_ASYNC) {
    2432          18 :                         if (search_async_id == async_id) {
    2433          18 :                                 found_id = async_id;
    2434          18 :                                 break;
    2435             :                         }
    2436             :                 } else {
    2437           0 :                         if (search_message_id == message_id) {
    2438           0 :                                 found_id = message_id;
    2439           0 :                                 break;
    2440             :                         }
    2441             :                 }
    2442             :         }
    2443             : 
    2444          18 :         if (cur && cur->subreq) {
    2445          18 :                 inhdr = SMBD_SMB2_IN_HDR_PTR(cur);
    2446          18 :                 DEBUG(10,("smbd_smb2_request_process_cancel: attempting to "
    2447             :                         "cancel opcode[%s] mid %llu\n",
    2448             :                         smb2_opcode_name(SVAL(inhdr, SMB2_HDR_OPCODE)),
    2449             :                         (unsigned long long)found_id ));
    2450          18 :                 tevent_req_cancel(cur->subreq);
    2451             :         }
    2452             : 
    2453          18 :         return NT_STATUS_OK;
    2454             : }
    2455             : 
    2456             : /*************************************************************
    2457             :  Ensure an incoming tid is a valid one for us to access.
    2458             :  Change to the associated uid credentials and chdir to the
    2459             :  valid tid directory.
    2460             : *************************************************************/
    2461             : 
    2462      133802 : static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
    2463             : {
    2464             :         const uint8_t *inhdr;
    2465             :         uint32_t in_flags;
    2466             :         uint32_t in_tid;
    2467             :         struct smbXsrv_tcon *tcon;
    2468             :         NTSTATUS status;
    2469      133802 :         NTTIME now = timeval_to_nttime(&req->request_time);
    2470             : 
    2471      133802 :         req->tcon = NULL;
    2472             : 
    2473      133802 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2474             : 
    2475      133802 :         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
    2476      133802 :         in_tid = IVAL(inhdr, SMB2_HDR_TID);
    2477             : 
    2478      133802 :         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
    2479           0 :                 in_tid = req->last_tid;
    2480             :         }
    2481             : 
    2482      133802 :         req->last_tid = 0;
    2483             : 
    2484      133802 :         status = smb2srv_tcon_lookup(req->session,
    2485             :                                      in_tid, now, &tcon);
    2486      133802 :         if (!NT_STATUS_IS_OK(status)) {
    2487          14 :                 return status;
    2488             :         }
    2489             : 
    2490      238046 :         if (!change_to_user_and_service(
    2491      133788 :                     tcon->compat,
    2492      133788 :                     req->session->global->session_wire_id))
    2493             :         {
    2494          24 :                 return NT_STATUS_ACCESS_DENIED;
    2495             :         }
    2496             : 
    2497      133764 :         req->tcon = tcon;
    2498      133764 :         req->last_tid = in_tid;
    2499             : 
    2500      133764 :         return NT_STATUS_OK;
    2501             : }
    2502             : 
    2503             : /*************************************************************
    2504             :  Ensure an incoming session_id is a valid one for us to access.
    2505             : *************************************************************/
    2506             : 
    2507      157044 : static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
    2508             : {
    2509             :         const uint8_t *inhdr;
    2510             :         uint32_t in_flags;
    2511             :         uint16_t in_opcode;
    2512             :         uint64_t in_session_id;
    2513      157044 :         struct smbXsrv_session *session = NULL;
    2514             :         struct auth_session_info *session_info;
    2515             :         NTSTATUS status;
    2516      157044 :         NTTIME now = timeval_to_nttime(&req->request_time);
    2517             : 
    2518      157044 :         req->session = NULL;
    2519      157044 :         req->tcon = NULL;
    2520             : 
    2521      157044 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2522             : 
    2523      157044 :         in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
    2524      157044 :         in_opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
    2525      157044 :         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
    2526             : 
    2527      157044 :         if (in_flags & SMB2_HDR_FLAG_CHAINED) {
    2528           0 :                 in_session_id = req->last_session_id;
    2529             :         }
    2530             : 
    2531      157044 :         req->last_session_id = 0;
    2532             : 
    2533             :         /* look an existing session up */
    2534      157044 :         switch (in_opcode) {
    2535        6774 :         case SMB2_OP_SESSSETUP:
    2536             :                 /*
    2537             :                  * For a session bind request, we don't have the
    2538             :                  * channel set up at this point yet, so we defer
    2539             :                  * the verification that the connection belongs
    2540             :                  * to the session to the session setup code, which
    2541             :                  * can look at the session binding flags.
    2542             :                  */
    2543        6774 :                 status = smb2srv_session_lookup_client(req->xconn->client,
    2544             :                                                        in_session_id, now,
    2545             :                                                        &session);
    2546        6774 :                 break;
    2547      150270 :         default:
    2548      150270 :                 status = smb2srv_session_lookup_conn(req->xconn,
    2549             :                                                      in_session_id, now,
    2550             :                                                      &session);
    2551      150270 :                 break;
    2552             :         }
    2553      157044 :         if (session) {
    2554      143525 :                 req->session = session;
    2555      143525 :                 req->last_session_id = in_session_id;
    2556             :         }
    2557      157044 :         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
    2558       13519 :                 switch (in_opcode) {
    2559        5068 :                 case SMB2_OP_SESSSETUP:
    2560        5068 :                         status = smb2srv_session_lookup_global(req->xconn->client,
    2561             :                                                                in_session_id,
    2562             :                                                                req,
    2563             :                                                                &session);
    2564        5068 :                         if (NT_STATUS_IS_OK(status)) {
    2565             :                                 /*
    2566             :                                  * We fallback to a session of
    2567             :                                  * another process in order to
    2568             :                                  * get the signing correct.
    2569             :                                  *
    2570             :                                  * We don't set req->last_session_id here.
    2571             :                                  */
    2572         148 :                                 req->session = session;
    2573             :                         }
    2574        5068 :                         break;
    2575        8451 :                 default:
    2576        8451 :                         break;
    2577             :                 }
    2578      110724 :         }
    2579      157044 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
    2580         106 :                 switch (in_opcode) {
    2581          12 :                 case SMB2_OP_SESSSETUP:
    2582          12 :                         status = NT_STATUS_OK;
    2583          12 :                         break;
    2584          28 :                 case SMB2_OP_LOGOFF:
    2585             :                 case SMB2_OP_CLOSE:
    2586             :                 case SMB2_OP_LOCK:
    2587             :                 case SMB2_OP_CANCEL:
    2588             :                 case SMB2_OP_KEEPALIVE:
    2589             :                         /*
    2590             :                          * [MS-SMB2] 3.3.5.2.9 Verifying the Session
    2591             :                          * specifies that LOGOFF, CLOSE and (UN)LOCK
    2592             :                          * should always be processed even on expired sessions.
    2593             :                          *
    2594             :                          * Also see the logic in
    2595             :                          * smbd_smb2_request_process_lock().
    2596             :                          *
    2597             :                          * The smb2.session.expire2 test shows that
    2598             :                          * CANCEL and KEEPALIVE/ECHO should also
    2599             :                          * be processed.
    2600             :                          */
    2601          28 :                         status = NT_STATUS_OK;
    2602          28 :                         break;
    2603          66 :                 default:
    2604          66 :                         break;
    2605             :                 }
    2606      120056 :         }
    2607      157044 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    2608        1506 :                 switch (in_opcode) {
    2609           0 :                 case SMB2_OP_TCON:
    2610             :                 case SMB2_OP_CREATE:
    2611             :                 case SMB2_OP_GETINFO:
    2612             :                 case SMB2_OP_SETINFO:
    2613           0 :                         return NT_STATUS_INVALID_HANDLE;
    2614        1506 :                 default:
    2615             :                         /*
    2616             :                          * Notice the check for
    2617             :                          * (session_info == NULL)
    2618             :                          * below.
    2619             :                          */
    2620        1506 :                         status = NT_STATUS_OK;
    2621        1506 :                         break;
    2622             :                 }
    2623      119074 :         }
    2624      157044 :         if (!NT_STATUS_IS_OK(status)) {
    2625       13437 :                 return status;
    2626             :         }
    2627             : 
    2628      143607 :         session_info = session->global->auth_session_info;
    2629      143607 :         if (session_info == NULL) {
    2630        1496 :                 return NT_STATUS_INVALID_HANDLE;
    2631             :         }
    2632             : 
    2633      142111 :         return NT_STATUS_OK;
    2634             : }
    2635             : 
    2636      101278 : NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req,
    2637             :                                                 uint32_t data_length)
    2638             : {
    2639      101278 :         struct smbXsrv_connection *xconn = req->xconn;
    2640             :         uint16_t needed_charge;
    2641      101278 :         uint16_t credit_charge = 1;
    2642             :         const uint8_t *inhdr;
    2643             : 
    2644      101278 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2645             : 
    2646      101278 :         if (xconn->smb2.credits.multicredit) {
    2647      100902 :                 credit_charge = SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE);
    2648      100902 :                 credit_charge = MAX(credit_charge, 1);
    2649             :         }
    2650             : 
    2651      101278 :         needed_charge = (data_length - 1)/ 65536 + 1;
    2652             : 
    2653      101278 :         DBGC_DEBUG(DBGC_SMB2_CREDITS,
    2654             :                    "mid %llu, CreditCharge: %d, NeededCharge: %d\n",
    2655             :                    (unsigned long long) BVAL(inhdr, SMB2_HDR_MESSAGE_ID),
    2656             :                    credit_charge, needed_charge);
    2657             : 
    2658      101278 :         if (needed_charge > credit_charge) {
    2659           0 :                 DBGC_WARNING(DBGC_SMB2_CREDITS,
    2660             :                           "CreditCharge too low, given %d, needed %d\n",
    2661             :                           credit_charge, needed_charge);
    2662           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2663             :         }
    2664             : 
    2665      101278 :         return NT_STATUS_OK;
    2666             : }
    2667             : 
    2668      156886 : NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
    2669             :                                         size_t expected_body_size)
    2670             : {
    2671             :         struct iovec *inhdr_v;
    2672             :         const uint8_t *inhdr;
    2673             :         uint16_t opcode;
    2674             :         const uint8_t *inbody;
    2675             :         size_t body_size;
    2676      156886 :         size_t min_dyn_size = expected_body_size & 0x00000001;
    2677      156886 :         int max_idx = req->in.vector_count - SMBD_SMB2_NUM_IOV_PER_REQ;
    2678             : 
    2679             :         /*
    2680             :          * The following should be checked already.
    2681             :          */
    2682      156886 :         if (req->in.vector_count < SMBD_SMB2_NUM_IOV_PER_REQ) {
    2683           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2684             :         }
    2685      156886 :         if (req->current_idx > max_idx) {
    2686           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2687             :         }
    2688             : 
    2689      156886 :         inhdr_v = SMBD_SMB2_IN_HDR_IOV(req);
    2690      156886 :         if (inhdr_v->iov_len != SMB2_HDR_BODY) {
    2691           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2692             :         }
    2693      156886 :         if (SMBD_SMB2_IN_BODY_LEN(req) < 2) {
    2694           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2695             :         }
    2696             : 
    2697      156886 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2698      156886 :         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
    2699             : 
    2700      156886 :         switch (opcode) {
    2701       89553 :         case SMB2_OP_IOCTL:
    2702             :         case SMB2_OP_GETINFO:
    2703             :         case SMB2_OP_WRITE:
    2704       89553 :                 min_dyn_size = 0;
    2705       89553 :                 break;
    2706             :         }
    2707             : 
    2708             :         /*
    2709             :          * Now check the expected body size,
    2710             :          * where the last byte might be in the
    2711             :          * dynamic section..
    2712             :          */
    2713      156886 :         if (SMBD_SMB2_IN_BODY_LEN(req) != (expected_body_size & 0xFFFFFFFE)) {
    2714           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2715             :         }
    2716      156886 :         if (SMBD_SMB2_IN_DYN_LEN(req) < min_dyn_size) {
    2717           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2718             :         }
    2719             : 
    2720      156886 :         inbody = SMBD_SMB2_IN_BODY_PTR(req);
    2721             : 
    2722      156886 :         body_size = SVAL(inbody, 0x00);
    2723      156886 :         if (body_size != expected_body_size) {
    2724           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2725             :         }
    2726             : 
    2727      156886 :         return NT_STATUS_OK;
    2728             : }
    2729             : 
    2730           0 : bool smbXsrv_is_encrypted(uint8_t encryption_flags)
    2731             : {
    2732           0 :         return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
    2733           0 :                 &&
    2734           0 :                 (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
    2735             :                                      SMBXSRV_ENCRYPTION_DESIRED |
    2736             :                                      SMBXSRV_ENCRYPTION_REQUIRED)));
    2737             : }
    2738             : 
    2739           0 : bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
    2740             : {
    2741           0 :         return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
    2742           0 :                 (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
    2743             : }
    2744             : 
    2745             : /* Set a flag if not already set, return true if set */
    2746      554510 : bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
    2747             : {
    2748      554510 :         if ((flag == 0) || (*flags & flag)) {
    2749      532286 :                 return false;
    2750             :         }
    2751             : 
    2752       22224 :         *flags |= flag;
    2753       22224 :         return true;
    2754             : }
    2755             : 
    2756             : /*
    2757             :  * Update encryption state tracking flags, this can be used to
    2758             :  * determine whether whether the session or tcon is "encrypted".
    2759             :  */
    2760      143557 : static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
    2761             :                                         uint16_t opcode,
    2762             :                                         bool *update_session_globalp,
    2763             :                                         bool *update_tcon_globalp)
    2764             : {
    2765             :         /* Default: assume unecrypted and unsigned */
    2766      143557 :         struct smbXsrv_session *session = req->session;
    2767      143557 :         struct smbXsrv_tcon *tcon = req->tcon;
    2768      143557 :         uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
    2769      143557 :         uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
    2770      143557 :         bool update_session = false;
    2771      143557 :         bool update_tcon = false;
    2772             : 
    2773      143557 :         if (session->table == NULL) {
    2774             :                 /*
    2775             :                  * sessions from smb2srv_session_lookup_global()
    2776             :                  * have NT_STATUS_BAD_LOGON_SESSION_STATE
    2777             :                  * and session->table == NULL.
    2778             :                  *
    2779             :                  * They only used to give the correct error
    2780             :                  * status, we should not update any state.
    2781             :                  */
    2782         182 :                 goto out;
    2783             :         }
    2784             : 
    2785      143375 :         if (req->was_encrypted && req->do_encryption) {
    2786         594 :                 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
    2787         594 :                 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
    2788             :         } else {
    2789             :                 /* Unencrypted packet, can be signed */
    2790      142781 :                 if (req->do_signing) {
    2791      124965 :                         sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
    2792             :                 }
    2793             :         }
    2794             : 
    2795      286750 :         update_session |= smbXsrv_set_crypto_flag(
    2796      143375 :                 &session->global->encryption_flags, encrypt_flag);
    2797      286750 :         update_session |= smbXsrv_set_crypto_flag(
    2798      143375 :                 &session->global->signing_flags, sign_flag);
    2799             : 
    2800      143375 :         if (tcon) {
    2801      267528 :                 update_tcon |= smbXsrv_set_crypto_flag(
    2802      133764 :                         &tcon->global->encryption_flags, encrypt_flag);
    2803      238010 :                 update_tcon |= smbXsrv_set_crypto_flag(
    2804      133764 :                         &tcon->global->signing_flags, sign_flag);
    2805             :         }
    2806             : 
    2807      120351 : out:
    2808      143557 :         *update_session_globalp = update_session;
    2809      143557 :         *update_tcon_globalp = update_tcon;
    2810      143557 :         return;
    2811             : }
    2812             : 
    2813           0 : bool smbXsrv_is_signed(uint8_t signing_flags)
    2814             : {
    2815             :         /*
    2816             :          * Signing is always enabled, so unless we got an unsigned
    2817             :          * packet and at least one signed packet that was not
    2818             :          * encrypted, the session or tcon is "signed".
    2819             :          */
    2820           0 :         return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
    2821           0 :                 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
    2822             : }
    2823             : 
    2824           0 : bool smbXsrv_is_partially_signed(uint8_t signing_flags)
    2825             : {
    2826           0 :         return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
    2827           0 :                 (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
    2828             : }
    2829             : 
    2830      156904 : static NTSTATUS smbd_smb2_request_dispatch_update_counts(
    2831             :                                 struct smbd_smb2_request *req,
    2832             :                                 bool modify_call)
    2833             : {
    2834      156904 :         struct smbXsrv_connection *xconn = req->xconn;
    2835             :         const uint8_t *inhdr;
    2836             :         uint16_t channel_sequence;
    2837      156904 :         uint8_t generation_wrap = 0;
    2838             :         uint32_t flags;
    2839             :         int cmp;
    2840             :         struct smbXsrv_open *op;
    2841      156904 :         bool update_open = false;
    2842      156904 :         NTSTATUS status = NT_STATUS_OK;
    2843             : 
    2844      156904 :         SMB_ASSERT(!req->request_counters_updated);
    2845             : 
    2846      156904 :         if (xconn->protocol < PROTOCOL_SMB3_00) {
    2847       78454 :                 return NT_STATUS_OK;
    2848             :         }
    2849             : 
    2850       78450 :         if (req->compat_chain_fsp == NULL) {
    2851       19857 :                 return NT_STATUS_OK;
    2852             :         }
    2853             : 
    2854       58593 :         op = req->compat_chain_fsp->op;
    2855       58593 :         if (op == NULL) {
    2856           0 :                 return NT_STATUS_OK;
    2857             :         }
    2858             : 
    2859       58593 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2860       58593 :         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
    2861       58593 :         channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
    2862             : 
    2863       58593 :         cmp = channel_sequence - op->global->channel_sequence;
    2864       58593 :         if (cmp < 0) {
    2865             :                 /*
    2866             :                  * csn wrap. We need to watch out for long-running
    2867             :                  * requests that are still sitting on a previously
    2868             :                  * used csn. SMB2_OP_NOTIFY can take VERY long.
    2869             :                  */
    2870           0 :                 generation_wrap += 1;
    2871             :         }
    2872             : 
    2873       58593 :         if (abs(cmp) > INT16_MAX) {
    2874             :                 /*
    2875             :                  * [MS-SMB2] 3.3.5.2.10 - Verifying the Channel Sequence Number:
    2876             :                  *
    2877             :                  * If the channel sequence number of the request and the one
    2878             :                  * known to the server are not equal, the channel sequence
    2879             :                  * number and outstanding request counts are only updated
    2880             :                  * "... if the unsigned difference using 16-bit arithmetic
    2881             :                  * between ChannelSequence and Open.ChannelSequence is less than
    2882             :                  * or equal to 0x7FFF ...".
    2883             :                  * Otherwise, an error is returned for the modifying
    2884             :                  * calls write, set_info, and ioctl.
    2885             :                  *
    2886             :                  * There are currently two issues with the description:
    2887             :                  *
    2888             :                  * * For the other calls, the document seems to imply
    2889             :                  *   that processing continues without adapting the
    2890             :                  *   counters (if the sequence numbers are not equal).
    2891             :                  *
    2892             :                  *   TODO: This needs clarification!
    2893             :                  *
    2894             :                  * * Also, the behaviour if the difference is larger
    2895             :                  *   than 0x7FFF is not clear. The document seems to
    2896             :                  *   imply that if such a difference is reached,
    2897             :                  *   the server starts to ignore the counters or
    2898             :                  *   in the case of the modifying calls, return errors.
    2899             :                  *
    2900             :                  *   TODO: This needs clarification!
    2901             :                  *
    2902             :                  * At this point Samba tries to be a little more
    2903             :                  * clever than the description in the MS-SMB2 document
    2904             :                  * by heuristically detecting and properly treating
    2905             :                  * a 16 bit overflow of the client-submitted sequence
    2906             :                  * number:
    2907             :                  *
    2908             :                  * If the stored channel sequence number is more than
    2909             :                  * 0x7FFF larger than the one from the request, then
    2910             :                  * the client-provided sequence number has likely
    2911             :                  * overflown. We treat this case as valid instead
    2912             :                  * of as failure.
    2913             :                  *
    2914             :                  * The MS-SMB2 behaviour would be setting cmp = -1.
    2915             :                  */
    2916           0 :                 cmp *= -1;
    2917             :         }
    2918             : 
    2919       58593 :         if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) {
    2920           0 :                 if (cmp == 0 && op->pre_request_count == 0) {
    2921           0 :                         op->request_count += 1;
    2922           0 :                         req->request_counters_updated = true;
    2923           0 :                 } else if (cmp > 0 && op->pre_request_count == 0) {
    2924           0 :                         op->pre_request_count += op->request_count;
    2925           0 :                         op->request_count = 1;
    2926           0 :                         op->global->channel_sequence = channel_sequence;
    2927           0 :                         op->global->channel_generation += generation_wrap;
    2928           0 :                         update_open = true;
    2929           0 :                         req->request_counters_updated = true;
    2930           0 :                 } else if (modify_call) {
    2931           0 :                         return NT_STATUS_FILE_NOT_AVAILABLE;
    2932             :                 }
    2933             :         } else {
    2934       58593 :                 if (cmp == 0) {
    2935       58593 :                         op->request_count += 1;
    2936       58593 :                         req->request_counters_updated = true;
    2937           0 :                 } else if (cmp > 0) {
    2938           0 :                         op->pre_request_count += op->request_count;
    2939           0 :                         op->request_count = 1;
    2940           0 :                         op->global->channel_sequence = channel_sequence;
    2941           0 :                         op->global->channel_generation += generation_wrap;
    2942           0 :                         update_open = true;
    2943           0 :                         req->request_counters_updated = true;
    2944           0 :                 } else if (modify_call) {
    2945           0 :                         return NT_STATUS_FILE_NOT_AVAILABLE;
    2946             :                 }
    2947             :         }
    2948       58593 :         req->channel_generation = op->global->channel_generation;
    2949             : 
    2950       58593 :         if (update_open) {
    2951           0 :                 status = smbXsrv_open_update(op);
    2952             :         }
    2953             : 
    2954       58593 :         return status;
    2955             : }
    2956             : 
    2957      157044 : NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
    2958             : {
    2959      157044 :         struct smbXsrv_connection *xconn = req->xconn;
    2960      157044 :         const struct smbd_smb2_dispatch_table *call = NULL;
    2961      157044 :         const struct iovec *intf_v = SMBD_SMB2_IN_TF_IOV(req);
    2962             :         const uint8_t *inhdr;
    2963             :         uint16_t opcode;
    2964             :         uint32_t flags;
    2965             :         uint64_t mid;
    2966             :         NTSTATUS status;
    2967             :         NTSTATUS session_status;
    2968             :         uint32_t allowed_flags;
    2969             :         NTSTATUS return_value;
    2970      157044 :         struct smbXsrv_session *x = NULL;
    2971      157044 :         bool signing_required = false;
    2972      157044 :         bool encryption_desired = false;
    2973      157044 :         bool encryption_required = false;
    2974             : 
    2975      157044 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    2976             : 
    2977      157044 :         DO_PROFILE_INC(request);
    2978             : 
    2979      157044 :         SMB_ASSERT(!req->request_counters_updated);
    2980             : 
    2981             :         /* TODO: verify more things */
    2982             : 
    2983      157044 :         flags = IVAL(inhdr, SMB2_HDR_FLAGS);
    2984      157044 :         opcode = SVAL(inhdr, SMB2_HDR_OPCODE);
    2985      157044 :         mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
    2986      157044 :         DBG_DEBUG("opcode[%s] mid = %"PRIu64"\n",
    2987             :                   smb2_opcode_name(opcode),
    2988             :                   mid);
    2989             : 
    2990      157044 :         if (xconn->protocol >= PROTOCOL_SMB2_02) {
    2991             :                 /*
    2992             :                  * once the protocol is negotiated
    2993             :                  * SMB2_OP_NEGPROT is not allowed anymore
    2994             :                  */
    2995      148671 :                 if (opcode == SMB2_OP_NEGPROT) {
    2996             :                         /* drop the connection */
    2997           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2998             :                 }
    2999             :         } else {
    3000             :                 /*
    3001             :                  * if the protocol is not negotiated yet
    3002             :                  * only SMB2_OP_NEGPROT is allowed.
    3003             :                  */
    3004        8373 :                 if (opcode != SMB2_OP_NEGPROT) {
    3005             :                         /* drop the connection */
    3006           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3007             :                 }
    3008             :         }
    3009             : 
    3010             :         /*
    3011             :          * Check if the client provided a valid session id.
    3012             :          *
    3013             :          * As some command don't require a valid session id
    3014             :          * we defer the check of the session_status
    3015             :          */
    3016      157044 :         session_status = smbd_smb2_request_check_session(req);
    3017      157044 :         x = req->session;
    3018      157044 :         if (x != NULL) {
    3019      143673 :                 signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
    3020      143673 :                 encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
    3021      143673 :                 encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
    3022             :         }
    3023             : 
    3024      157044 :         req->async_internal = false;
    3025      157044 :         req->do_signing = false;
    3026      157044 :         if (opcode != SMB2_OP_SESSSETUP) {
    3027      150270 :                 req->do_encryption = encryption_desired;
    3028             :         } else {
    3029        6774 :                 req->do_encryption = false;
    3030             :         }
    3031      157044 :         req->was_encrypted = false;
    3032      157044 :         if (intf_v->iov_len == SMB2_TF_HDR_SIZE) {
    3033         624 :                 const uint8_t *intf = SMBD_SMB2_IN_TF_PTR(req);
    3034         624 :                 uint64_t tf_session_id = BVAL(intf, SMB2_TF_SESSION_ID);
    3035             : 
    3036         624 :                 if (x != NULL && x->global->session_wire_id != tf_session_id) {
    3037           0 :                         DEBUG(0,("smbd_smb2_request_dispatch: invalid session_id"
    3038             :                                  "in SMB2_HDR[%llu], SMB2_TF[%llu]\n",
    3039             :                                  (unsigned long long)x->global->session_wire_id,
    3040             :                                  (unsigned long long)tf_session_id));
    3041             :                         /*
    3042             :                          * TODO: windows allows this...
    3043             :                          * should we drop the connection?
    3044             :                          *
    3045             :                          * For now we just return ACCESS_DENIED
    3046             :                          * (Windows clients never trigger this)
    3047             :                          * and wait for an update of [MS-SMB2].
    3048             :                          */
    3049           0 :                         return smbd_smb2_request_error(req,
    3050             :                                         NT_STATUS_ACCESS_DENIED);
    3051             :                 }
    3052             : 
    3053         624 :                 req->was_encrypted = true;
    3054         624 :                 req->do_encryption = true;
    3055             :         }
    3056             : 
    3057      157044 :         if (encryption_required && !req->was_encrypted) {
    3058           0 :                 req->do_encryption = true;
    3059           0 :                 return smbd_smb2_request_error(req,
    3060             :                                 NT_STATUS_ACCESS_DENIED);
    3061             :         }
    3062             : 
    3063      157044 :         call = smbd_smb2_call(opcode);
    3064      157044 :         if (call == NULL) {
    3065           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    3066             :         }
    3067             : 
    3068      157044 :         allowed_flags = SMB2_HDR_FLAG_CHAINED |
    3069             :                         SMB2_HDR_FLAG_SIGNED |
    3070             :                         SMB2_HDR_FLAG_DFS;
    3071      157044 :         if (xconn->protocol >= PROTOCOL_SMB3_11) {
    3072       78502 :                 allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
    3073             :         }
    3074      157044 :         if (opcode == SMB2_OP_NEGPROT) {
    3075        8373 :                 if (lp_server_max_protocol() >= PROTOCOL_SMB3_11) {
    3076        4846 :                         allowed_flags |= SMB2_HDR_FLAG_PRIORITY_MASK;
    3077             :                 }
    3078             :         }
    3079      157044 :         if (opcode == SMB2_OP_CANCEL) {
    3080          18 :                 allowed_flags |= SMB2_HDR_FLAG_ASYNC;
    3081             :         }
    3082      157044 :         if (xconn->protocol >= PROTOCOL_SMB3_00) {
    3083       78590 :                 allowed_flags |= SMB2_HDR_FLAG_REPLAY_OPERATION;
    3084             :         }
    3085      157044 :         if ((flags & ~allowed_flags) != 0) {
    3086           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    3087             :         }
    3088             : 
    3089      157044 :         if (flags & SMB2_HDR_FLAG_CHAINED) {
    3090             :                 /*
    3091             :                  * This check is mostly for giving the correct error code
    3092             :                  * for compounded requests.
    3093             :                  */
    3094           0 :                 if (!NT_STATUS_IS_OK(session_status)) {
    3095           0 :                         return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    3096             :                 }
    3097             :         } else {
    3098      157044 :                 req->compat_chain_fsp = NULL;
    3099             :         }
    3100             : 
    3101      157044 :         if (req->was_encrypted) {
    3102         624 :                 signing_required = false;
    3103      156420 :         } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
    3104      125195 :                 struct smb2_signing_key *signing_key = NULL;
    3105      125195 :                 bool has_channel = false;
    3106             : 
    3107      125195 :                 if (x == NULL) {
    3108             :                         /*
    3109             :                          * MS-SMB2: 3.3.5.2.4 Verifying the Signature.
    3110             :                          * If the SMB2 header of the SMB2 NEGOTIATE
    3111             :                          * request has the SMB2_FLAGS_SIGNED bit set in the
    3112             :                          * Flags field, the server MUST fail the request
    3113             :                          * with STATUS_INVALID_PARAMETER.
    3114             :                          *
    3115             :                          * Microsoft test tool checks this.
    3116             :                          */
    3117             : 
    3118          22 :                         if ((opcode == SMB2_OP_NEGPROT) &&
    3119           0 :                                         (flags & SMB2_HDR_FLAG_SIGNED)) {
    3120           0 :                                 status = NT_STATUS_INVALID_PARAMETER;
    3121             :                         } else {
    3122          22 :                                 status = NT_STATUS_USER_SESSION_DELETED;
    3123             :                         }
    3124          81 :                         return smbd_smb2_request_error(req, status);
    3125             :                 }
    3126             : 
    3127      125173 :                 signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
    3128             : 
    3129             :                 /*
    3130             :                  * If we have a signing key, we should
    3131             :                  * sign the response
    3132             :                  */
    3133      125173 :                 if (smb2_signing_key_valid(signing_key) && opcode != SMB2_OP_CANCEL) {
    3134      125165 :                         req->do_signing = true;
    3135             :                 }
    3136             : 
    3137      221621 :                 status = smb2_signing_check_pdu(signing_key,
    3138      221621 :                                                 SMBD_SMB2_IN_HDR_IOV(req),
    3139             :                                                 SMBD_SMB2_NUM_IOV_PER_REQ - 1);
    3140      125173 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
    3141          63 :                     opcode == SMB2_OP_SESSSETUP && !has_channel &&
    3142          34 :                     NT_STATUS_IS_OK(session_status))
    3143             :                 {
    3144          34 :                         if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
    3145          34 :                                 struct smbXsrv_session *session = NULL;
    3146             :                                 NTSTATUS error;
    3147             : 
    3148          34 :                                 error = smb2srv_session_lookup_global(req->xconn->client,
    3149          34 :                                                                       x->global->session_wire_id,
    3150             :                                                                       req,
    3151             :                                                                       &session);
    3152          34 :                                 if (!NT_STATUS_IS_OK(error)) {
    3153           0 :                                         return smbd_smb2_request_error(req, error);
    3154             :                                 }
    3155             : 
    3156             :                                 /*
    3157             :                                  * We fallback to a session of
    3158             :                                  * another process in order to
    3159             :                                  * get the signing correct.
    3160             :                                  *
    3161             :                                  * We don't set req->last_session_id here.
    3162             :                                  */
    3163          34 :                                 req->session = x = session;
    3164             :                         }
    3165          34 :                         goto skipped_signing;
    3166             :                 }
    3167      125139 :                 if (!NT_STATUS_IS_OK(status)) {
    3168          12 :                         return smbd_smb2_request_error(req, status);
    3169             :                 }
    3170             : 
    3171             :                 /*
    3172             :                  * Now that we know the request was correctly signed
    3173             :                  * we have to sign the response too.
    3174             :                  */
    3175      125127 :                 if (opcode != SMB2_OP_CANCEL) {
    3176      125119 :                         req->do_signing = true;
    3177             :                 }
    3178             : 
    3179      125127 :                 if (!NT_STATUS_IS_OK(session_status)) {
    3180          36 :                         return smbd_smb2_request_error(req, session_status);
    3181             :                 }
    3182             :         }
    3183             : 
    3184      156940 :         if (opcode == SMB2_OP_IOCTL) {
    3185             :                 /*
    3186             :                  * Some special IOCTL calls don't require
    3187             :                  * file, tcon nor session.
    3188             :                  *
    3189             :                  * They typically don't do any real action
    3190             :                  * on behalf of the client.
    3191             :                  *
    3192             :                  * They are mainly used to alter the behavior
    3193             :                  * of the connection for testing. So we can
    3194             :                  * run as root and skip all file, tcon and session
    3195             :                  * checks below.
    3196             :                  */
    3197             :                 static const struct smbd_smb2_dispatch_table _root_ioctl_call = {
    3198             :                         _OP(SMB2_OP_IOCTL),
    3199             :                         .as_root = true,
    3200             :                 };
    3201       81587 :                 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
    3202       81587 :                 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
    3203             :                 uint32_t in_ctl_code;
    3204       81587 :                 size_t needed = 8;
    3205             : 
    3206       81587 :                 if (needed > body_size) {
    3207           0 :                         return smbd_smb2_request_error(req,
    3208             :                                         NT_STATUS_INVALID_PARAMETER);
    3209             :                 }
    3210             : 
    3211       81587 :                 in_ctl_code = IVAL(body, 0x04);
    3212             :                 /*
    3213             :                  * Only add trusted IOCTL codes here!
    3214             :                  */
    3215       81587 :                 switch (in_ctl_code) {
    3216           0 :                 case FSCTL_SMBTORTURE_FORCE_UNACKED_TIMEOUT:
    3217           0 :                         call = &_root_ioctl_call;
    3218           0 :                         break;
    3219        2311 :                 case FSCTL_VALIDATE_NEGOTIATE_INFO:
    3220        2311 :                         call = &_root_ioctl_call;
    3221        2311 :                         break;
    3222           0 :                 case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
    3223           0 :                         call = &_root_ioctl_call;
    3224           0 :                         break;
    3225             :                 }
    3226             :         }
    3227             : 
    3228      195427 : skipped_signing:
    3229             : 
    3230      156974 :         if (flags & SMB2_HDR_FLAG_CHAINED) {
    3231           0 :                 req->compound_related = true;
    3232             :         }
    3233             : 
    3234      156974 :         if (call->need_session) {
    3235      139450 :                 if (!NT_STATUS_IS_OK(session_status)) {
    3236          30 :                         return smbd_smb2_request_error(req, session_status);
    3237             :                 }
    3238             :         }
    3239             : 
    3240      156944 :         if (call->need_tcon) {
    3241      133802 :                 SMB_ASSERT(call->need_session);
    3242             : 
    3243             :                 /*
    3244             :                  * This call needs to be run as user.
    3245             :                  *
    3246             :                  * smbd_smb2_request_check_tcon()
    3247             :                  * calls change_to_user() on success.
    3248             :                  * Which implies set_current_user_info()
    3249             :                  * and chdir_current_service().
    3250             :                  */
    3251      133802 :                 status = smbd_smb2_request_check_tcon(req);
    3252      133802 :                 if (!NT_STATUS_IS_OK(status)) {
    3253          38 :                         return smbd_smb2_request_error(req, status);
    3254             :                 }
    3255      133764 :                 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
    3256           0 :                         encryption_desired = true;
    3257             :                 }
    3258      133764 :                 if (req->tcon->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
    3259           0 :                         encryption_required = true;
    3260             :                 }
    3261      133764 :                 if (encryption_required && !req->was_encrypted) {
    3262           0 :                         req->do_encryption = true;
    3263           0 :                         return smbd_smb2_request_error(req,
    3264             :                                 NT_STATUS_ACCESS_DENIED);
    3265      133764 :                 } else if (encryption_desired) {
    3266           0 :                         req->do_encryption = true;
    3267             :                 }
    3268       23142 :         } else if (call->need_session) {
    3269        5618 :                 struct auth_session_info *session_info = NULL;
    3270             : 
    3271             :                 /*
    3272             :                  * Unless we also have need_tcon (see above),
    3273             :                  * we still need to call set_current_user_info().
    3274             :                  */
    3275             : 
    3276        5618 :                 session_info = req->session->global->auth_session_info;
    3277        5618 :                 if (session_info == NULL) {
    3278           0 :                         return NT_STATUS_INVALID_HANDLE;
    3279             :                 }
    3280             : 
    3281        9423 :                 set_current_user_info(session_info->unix_info->sanitized_username,
    3282        5618 :                                       session_info->unix_info->unix_name,
    3283        5618 :                                       session_info->info->domain_name);
    3284             :         }
    3285             : 
    3286      156906 :         if (req->session) {
    3287      143557 :                 bool update_session_global = false;
    3288      143557 :                 bool update_tcon_global = false;
    3289             : 
    3290      143557 :                 smb2srv_update_crypto_flags(req, opcode,
    3291             :                                             &update_session_global,
    3292             :                                             &update_tcon_global);
    3293             : 
    3294      143557 :                 if (update_session_global) {
    3295        6308 :                         status = smbXsrv_session_update(x);
    3296        6308 :                         if (!NT_STATUS_IS_OK(status)) {
    3297           0 :                                 return smbd_smb2_request_error(req, status);
    3298             :                         }
    3299             :                 }
    3300      143557 :                 if (update_tcon_global) {
    3301        5447 :                         status = smbXsrv_tcon_update(req->tcon);
    3302        5447 :                         if (!NT_STATUS_IS_OK(status)) {
    3303           0 :                                 return smbd_smb2_request_error(req, status);
    3304             :                         }
    3305             :                 }
    3306             :         }
    3307             : 
    3308      156906 :         if (call->fileid_ofs != 0) {
    3309      114134 :                 size_t needed = call->fileid_ofs + 16;
    3310      114134 :                 const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
    3311      114134 :                 size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
    3312             :                 uint64_t file_id_persistent;
    3313             :                 uint64_t file_id_volatile;
    3314             :                 struct files_struct *fsp;
    3315             : 
    3316      114134 :                 SMB_ASSERT(call->need_tcon);
    3317             : 
    3318      114134 :                 if (needed > body_size) {
    3319           0 :                         return smbd_smb2_request_error(req,
    3320             :                                         NT_STATUS_INVALID_PARAMETER);
    3321             :                 }
    3322             : 
    3323      114134 :                 file_id_persistent      = BVAL(body, call->fileid_ofs + 0);
    3324      114134 :                 file_id_volatile        = BVAL(body, call->fileid_ofs + 8);
    3325             : 
    3326      114134 :                 fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
    3327      114134 :                 if (fsp == NULL) {
    3328        1657 :                         if (req->compound_related &&
    3329           0 :                             !NT_STATUS_IS_OK(req->compound_create_err))
    3330             :                         {
    3331           0 :                                 return smbd_smb2_request_error(req,
    3332             :                                                 req->compound_create_err);
    3333             :                         }
    3334             :                         /*
    3335             :                          * smbd_smb2_request_process_ioctl()
    3336             :                          * has more checks in order to return more
    3337             :                          * detailed error codes...
    3338             :                          */
    3339        1657 :                         if (opcode != SMB2_OP_IOCTL) {
    3340           2 :                                 return smbd_smb2_request_error(req,
    3341             :                                                 NT_STATUS_FILE_CLOSED);
    3342             :                         }
    3343             :                 } else {
    3344      112477 :                         if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
    3345           0 :                                 return smbd_smb2_request_error(req,
    3346             :                                                 NT_STATUS_ACCESS_DENIED);
    3347             :                         }
    3348             :                 }
    3349             :         }
    3350             : 
    3351      156904 :         status = smbd_smb2_request_dispatch_update_counts(req, call->modify);
    3352      156904 :         if (!NT_STATUS_IS_OK(status)) {
    3353           0 :                 return smbd_smb2_request_error(req, status);
    3354             :         }
    3355             : 
    3356      156904 :         if (call->as_root) {
    3357       25543 :                 SMB_ASSERT(call->fileid_ofs == 0);
    3358             :                 /* This call needs to be run as root */
    3359       25543 :                 change_to_root_user();
    3360             :         } else {
    3361      131361 :                 SMB_ASSERT(call->need_tcon);
    3362             :         }
    3363             : 
    3364             : #define _INBYTES(_r) \
    3365             :         iov_buflen(SMBD_SMB2_IN_HDR_IOV(_r), SMBD_SMB2_NUM_IOV_PER_REQ-1)
    3366             : 
    3367      156904 :         switch (opcode) {
    3368        8373 :         case SMB2_OP_NEGPROT:
    3369        8373 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_negprot, profile_p,
    3370             :                                                req->profile, _INBYTES(req));
    3371        8373 :                 return_value = smbd_smb2_request_process_negprot(req);
    3372        8373 :                 break;
    3373             : 
    3374        6762 :         case SMB2_OP_SESSSETUP:
    3375        6762 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_sesssetup, profile_p,
    3376             :                                                req->profile, _INBYTES(req));
    3377        6762 :                 return_value = smbd_smb2_request_process_sesssetup(req);
    3378        6762 :                 break;
    3379             : 
    3380           9 :         case SMB2_OP_LOGOFF:
    3381           9 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_logoff, profile_p,
    3382             :                                                req->profile, _INBYTES(req));
    3383           9 :                 return_value = smbd_smb2_request_process_logoff(req);
    3384           9 :                 break;
    3385             : 
    3386        5609 :         case SMB2_OP_TCON:
    3387        5609 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tcon, profile_p,
    3388             :                                                req->profile, _INBYTES(req));
    3389        5609 :                 return_value = smbd_smb2_request_process_tcon(req);
    3390        5609 :                 break;
    3391             : 
    3392        2401 :         case SMB2_OP_TDIS:
    3393        2401 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_tdis, profile_p,
    3394             :                                                req->profile, _INBYTES(req));
    3395        2401 :                 return_value = smbd_smb2_request_process_tdis(req);
    3396        2401 :                 break;
    3397             : 
    3398       17229 :         case SMB2_OP_CREATE:
    3399       17229 :                 if (req->subreq == NULL) {
    3400       17229 :                         SMBPROFILE_IOBYTES_ASYNC_START(smb2_create, profile_p,
    3401             :                                                        req->profile, _INBYTES(req));
    3402             :                 } else {
    3403           0 :                         SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(req->profile);
    3404             :                 }
    3405       17229 :                 return_value = smbd_smb2_request_process_create(req);
    3406       17227 :                 break;
    3407             : 
    3408       15148 :         case SMB2_OP_CLOSE:
    3409       15148 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_close, profile_p,
    3410             :                                                req->profile, _INBYTES(req));
    3411       15148 :                 return_value = smbd_smb2_request_process_close(req);
    3412       12658 :                 break;
    3413             : 
    3414           0 :         case SMB2_OP_FLUSH:
    3415           0 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_flush, profile_p,
    3416             :                                                req->profile, _INBYTES(req));
    3417           0 :                 return_value = smbd_smb2_request_process_flush(req);
    3418           0 :                 break;
    3419             : 
    3420        6358 :         case SMB2_OP_READ:
    3421        6358 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_read, profile_p,
    3422             :                                                req->profile, _INBYTES(req));
    3423        6358 :                 return_value = smbd_smb2_request_process_read(req);
    3424        6358 :                 break;
    3425             : 
    3426        6348 :         case SMB2_OP_WRITE:
    3427        6348 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_write, profile_p,
    3428             :                                                req->profile, _INBYTES(req));
    3429        6348 :                 return_value = smbd_smb2_request_process_write(req);
    3430        6348 :                 break;
    3431             : 
    3432          17 :         case SMB2_OP_LOCK:
    3433          17 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_lock, profile_p,
    3434             :                                                req->profile, _INBYTES(req));
    3435          17 :                 return_value = smbd_smb2_request_process_lock(req);
    3436          17 :                 break;
    3437             : 
    3438       81585 :         case SMB2_OP_IOCTL:
    3439       81585 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_ioctl, profile_p,
    3440             :                                                req->profile, _INBYTES(req));
    3441       81585 :                 return_value = smbd_smb2_request_process_ioctl(req);
    3442       81585 :                 break;
    3443             : 
    3444          18 :         case SMB2_OP_CANCEL:
    3445          18 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
    3446             :                                                req->profile, _INBYTES(req));
    3447          18 :                 return_value = smbd_smb2_request_process_cancel(req);
    3448          18 :                 SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
    3449             : 
    3450             :                 /*
    3451             :                  * We don't need the request anymore cancel requests never
    3452             :                  * have a response.
    3453             :                  *
    3454             :                  * smbd_smb2_request_process_cancel() already called
    3455             :                  * DLIST_REMOVE(xconn->smb2.requests, req);
    3456             :                  */
    3457          18 :                 TALLOC_FREE(req);
    3458             : 
    3459          18 :                 break;
    3460             : 
    3461          60 :         case SMB2_OP_KEEPALIVE:
    3462          60 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_keepalive, profile_p,
    3463             :                                                req->profile, _INBYTES(req));
    3464          60 :                 return_value = smbd_smb2_request_process_keepalive(req);
    3465          60 :                 break;
    3466             : 
    3467        4287 :         case SMB2_OP_QUERY_DIRECTORY:
    3468        4287 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_find, profile_p,
    3469             :                                                req->profile, _INBYTES(req));
    3470        4287 :                 return_value = smbd_smb2_request_process_query_directory(req);
    3471        4287 :                 break;
    3472             : 
    3473          60 :         case SMB2_OP_NOTIFY:
    3474          60 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_notify, profile_p,
    3475             :                                                req->profile, _INBYTES(req));
    3476          60 :                 return_value = smbd_smb2_request_process_notify(req);
    3477          60 :                 break;
    3478             : 
    3479        1620 :         case SMB2_OP_GETINFO:
    3480        1620 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_getinfo, profile_p,
    3481             :                                                req->profile, _INBYTES(req));
    3482        1620 :                 return_value = smbd_smb2_request_process_getinfo(req);
    3483        1620 :                 break;
    3484             : 
    3485        1020 :         case SMB2_OP_SETINFO:
    3486        1020 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_setinfo, profile_p,
    3487             :                                                req->profile, _INBYTES(req));
    3488        1020 :                 return_value = smbd_smb2_request_process_setinfo(req);
    3489        1020 :                 break;
    3490             : 
    3491           0 :         case SMB2_OP_BREAK:
    3492           0 :                 SMBPROFILE_IOBYTES_ASYNC_START(smb2_break, profile_p,
    3493             :                                                req->profile, _INBYTES(req));
    3494           0 :                 return_value = smbd_smb2_request_process_break(req);
    3495           0 :                 break;
    3496             : 
    3497           0 :         default:
    3498           0 :                 return_value = smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    3499           0 :                 break;
    3500             :         }
    3501      154412 :         return return_value;
    3502             : }
    3503             : 
    3504      156976 : static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
    3505             : {
    3506      156976 :         struct smbXsrv_connection *xconn = req->xconn;
    3507             :         const uint8_t *inhdr;
    3508             :         uint16_t channel_sequence;
    3509             :         struct smbXsrv_open *op;
    3510             : 
    3511      156976 :         if (!req->request_counters_updated) {
    3512       98383 :                 return;
    3513             :         }
    3514             : 
    3515       58593 :         req->request_counters_updated = false;
    3516             : 
    3517       58593 :         if (xconn->protocol < PROTOCOL_SMB3_00) {
    3518           0 :                 return;
    3519             :         }
    3520             : 
    3521       58593 :         if (req->compat_chain_fsp == NULL) {
    3522        7949 :                 return;
    3523             :         }
    3524             : 
    3525       50644 :         op = req->compat_chain_fsp->op;
    3526       50644 :         if (op == NULL) {
    3527           0 :                 return;
    3528             :         }
    3529             : 
    3530       50644 :         inhdr = SMBD_SMB2_IN_HDR_PTR(req);
    3531       50644 :         channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
    3532             : 
    3533       96028 :         if ((op->global->channel_sequence == channel_sequence) &&
    3534       50644 :             (op->global->channel_generation == req->channel_generation)) {
    3535       50644 :                 SMB_ASSERT(op->request_count > 0);
    3536       50644 :                 op->request_count -= 1;
    3537             :         } else {
    3538           0 :                 SMB_ASSERT(op->pre_request_count > 0);
    3539           0 :                 op->pre_request_count -= 1;
    3540             :         }
    3541             : }
    3542             : 
    3543      156976 : static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
    3544             : {
    3545      156976 :         struct smbXsrv_connection *xconn = req->xconn;
    3546      156976 :         int first_idx = 1;
    3547      156976 :         struct iovec *firsttf = SMBD_SMB2_IDX_TF_IOV(req,out,first_idx);
    3548      156976 :         struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
    3549      156976 :         struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
    3550             :         NTSTATUS status;
    3551             :         bool ok;
    3552             : 
    3553      156976 :         req->subreq = NULL;
    3554      156976 :         TALLOC_FREE(req->async_te);
    3555             : 
    3556             :         /* MS-SMB2: 3.3.4.1 Sending Any Outgoing Message */
    3557      156976 :         smbd_smb2_request_reply_update_counts(req);
    3558             : 
    3559      157283 :         if (req->do_encryption &&
    3560         921 :             (firsttf->iov_len == 0) &&
    3561         921 :             (!smb2_signing_key_valid(req->first_enc_key)) &&
    3562        1228 :             (req->session != NULL) &&
    3563         614 :             smb2_signing_key_valid(req->session->global->encryption_key))
    3564             :         {
    3565         614 :                 struct smb2_signing_key *encryption_key =
    3566         614 :                         req->session->global->encryption_key;
    3567             :                 uint8_t *tf;
    3568         614 :                 uint64_t session_id = req->session->global->session_wire_id;
    3569             :                 uint64_t nonce_high;
    3570             :                 uint64_t nonce_low;
    3571             : 
    3572         614 :                 status = smb2_get_new_nonce(req->session,
    3573             :                                             &nonce_high,
    3574             :                                             &nonce_low);
    3575         614 :                 if (!NT_STATUS_IS_OK(status)) {
    3576           0 :                         return status;
    3577             :                 }
    3578             : 
    3579             :                 /*
    3580             :                  * We need to place the SMB2_TRANSFORM header before the
    3581             :                  * first SMB2 header
    3582             :                  */
    3583             : 
    3584             :                 /*
    3585             :                  * we need to remember the encryption key
    3586             :                  * and defer the signing/encryption until
    3587             :                  * we are sure that we do not change
    3588             :                  * the header again.
    3589             :                  */
    3590         614 :                 status = smb2_signing_key_copy(req,
    3591             :                                                encryption_key,
    3592             :                                                &req->first_enc_key);
    3593         614 :                 if (!NT_STATUS_IS_OK(status)) {
    3594           0 :                         return status;
    3595             :                 }
    3596             : 
    3597         614 :                 tf = talloc_zero_array(req, uint8_t,
    3598             :                                        SMB2_TF_HDR_SIZE);
    3599         614 :                 if (tf == NULL) {
    3600           0 :                         return NT_STATUS_NO_MEMORY;
    3601             :                 }
    3602             : 
    3603         614 :                 SIVAL(tf, SMB2_TF_PROTOCOL_ID, SMB2_TF_MAGIC);
    3604         614 :                 SBVAL(tf, SMB2_TF_NONCE+0, nonce_low);
    3605         614 :                 SBVAL(tf, SMB2_TF_NONCE+8, nonce_high);
    3606         614 :                 SBVAL(tf, SMB2_TF_SESSION_ID, session_id);
    3607             : 
    3608         614 :                 firsttf->iov_base = (void *)tf;
    3609         614 :                 firsttf->iov_len = SMB2_TF_HDR_SIZE;
    3610             :         }
    3611             : 
    3612      156976 :         if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
    3613           0 :             (smb2_signing_key_valid(req->last_sign_key)) &&
    3614           0 :             (firsttf->iov_len == 0))
    3615             :         {
    3616           0 :                 int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
    3617           0 :                 struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
    3618             : 
    3619             :                 /*
    3620             :                  * As we are sure the header of the last request in the
    3621             :                  * compound chain will not change, we can to sign here
    3622             :                  * with the last signing key we remembered.
    3623             :                  */
    3624           0 :                 status = smb2_signing_sign_pdu(req->last_sign_key,
    3625             :                                                lasthdr,
    3626             :                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
    3627           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3628           0 :                         return status;
    3629             :                 }
    3630             :         }
    3631      156976 :         TALLOC_FREE(req->last_sign_key);
    3632             : 
    3633      156976 :         SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
    3634             :                 iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
    3635             : 
    3636      156976 :         req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
    3637             : 
    3638      156976 :         if (req->current_idx < req->out.vector_count) {
    3639             :                 /*
    3640             :                  * We must process the remaining compound
    3641             :                  * SMB2 requests before any new incoming SMB2
    3642             :                  * requests. This is because incoming SMB2
    3643             :                  * requests may include a cancel for a
    3644             :                  * compound request we haven't processed
    3645             :                  * yet.
    3646             :                  */
    3647           0 :                 struct tevent_immediate *im = tevent_create_immediate(req);
    3648           0 :                 if (!im) {
    3649           0 :                         return NT_STATUS_NO_MEMORY;
    3650             :                 }
    3651             : 
    3652           0 :                 if (req->do_signing && firsttf->iov_len == 0) {
    3653           0 :                         struct smbXsrv_session *x = req->session;
    3654           0 :                         struct smb2_signing_key *signing_key =
    3655           0 :                                 smbd_smb2_signing_key(x, xconn, NULL);
    3656             : 
    3657             :                         /*
    3658             :                          * we need to remember the signing key
    3659             :                          * and defer the signing until
    3660             :                          * we are sure that we do not change
    3661             :                          * the header again.
    3662             :                          */
    3663           0 :                         status = smb2_signing_key_copy(req,
    3664             :                                                        signing_key,
    3665             :                                                        &req->last_sign_key);
    3666           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3667           0 :                                 return status;
    3668             :                         }
    3669             :                 }
    3670             : 
    3671             :                 /*
    3672             :                  * smbd_smb2_request_dispatch() will redo the impersonation.
    3673             :                  * So we use req->xconn->client->raw_ev_ctx instead
    3674             :                  * of req->ev_ctx here.
    3675             :                  */
    3676           0 :                 tevent_schedule_immediate(im,
    3677             :                                         req->xconn->client->raw_ev_ctx,
    3678             :                                         smbd_smb2_request_dispatch_immediate,
    3679             :                                         req);
    3680           0 :                 return NT_STATUS_OK;
    3681             :         }
    3682             : 
    3683      156976 :         if (req->compound_related) {
    3684           0 :                 req->compound_related = false;
    3685             :         }
    3686             : 
    3687      156976 :         ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
    3688      156976 :         if (!ok) {
    3689           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    3690             :         }
    3691             : 
    3692             :         /* Set credit for these operations (zero credits if this
    3693             :            is a final reply for an async operation). */
    3694      156976 :         smb2_calculate_credits(req, req);
    3695             : 
    3696             :         /*
    3697             :          * now check if we need to sign the current response
    3698             :          */
    3699      156976 :         if (firsttf->iov_len == SMB2_TF_HDR_SIZE) {
    3700         614 :                 status = smb2_signing_encrypt_pdu(req->first_enc_key,
    3701             :                                         firsttf,
    3702         614 :                                         req->out.vector_count - first_idx);
    3703         614 :                 if (!NT_STATUS_IS_OK(status)) {
    3704           0 :                         return status;
    3705             :                 }
    3706      156362 :         } else if (req->do_signing) {
    3707      129566 :                 struct smbXsrv_session *x = req->session;
    3708       99527 :                 struct smb2_signing_key *signing_key =
    3709       30039 :                         smbd_smb2_signing_key(x, xconn, NULL);
    3710             : 
    3711      129566 :                 status = smb2_signing_sign_pdu(signing_key,
    3712             :                                                outhdr,
    3713             :                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
    3714      129566 :                 if (!NT_STATUS_IS_OK(status)) {
    3715           0 :                         return status;
    3716             :                 }
    3717             :         }
    3718      156976 :         TALLOC_FREE(req->first_enc_key);
    3719             : 
    3720      156976 :         if (req->preauth != NULL) {
    3721        4065 :                 gnutls_hash_hd_t hash_hnd = NULL;
    3722             :                 size_t i;
    3723             :                 int rc;
    3724             : 
    3725        4065 :                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
    3726        4065 :                 if (rc < 0) {
    3727           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3728             :                 }
    3729        4065 :                 rc = gnutls_hash(hash_hnd,
    3730        4065 :                             req->preauth->sha512_value,
    3731             :                             sizeof(req->preauth->sha512_value));
    3732        4065 :                 if (rc < 0) {
    3733           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
    3734           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3735             :                 }
    3736       20325 :                 for (i = 1; i < req->in.vector_count; i++) {
    3737       28040 :                         rc = gnutls_hash(hash_hnd,
    3738       16260 :                                          req->in.vector[i].iov_base,
    3739       16260 :                                          req->in.vector[i].iov_len);
    3740       16260 :                         if (rc < 0) {
    3741           0 :                                 gnutls_hash_deinit(hash_hnd, NULL);
    3742           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3743             :                         }
    3744             :                 }
    3745        4065 :                 if (rc < 0) {
    3746           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
    3747           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3748             :                 }
    3749        4065 :                 gnutls_hash_output(hash_hnd, req->preauth->sha512_value);
    3750             : 
    3751        4065 :                 rc = gnutls_hash(hash_hnd,
    3752        4065 :                                  req->preauth->sha512_value,
    3753             :                                  sizeof(req->preauth->sha512_value));
    3754        4065 :                 if (rc < 0) {
    3755           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
    3756           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3757             :                 }
    3758       20325 :                 for (i = 1; i < req->out.vector_count; i++) {
    3759       28040 :                         rc = gnutls_hash(hash_hnd,
    3760       16260 :                                          req->out.vector[i].iov_base,
    3761       16260 :                                          req->out.vector[i].iov_len);
    3762       16260 :                         if (rc < 0) {
    3763           0 :                                 gnutls_hash_deinit(hash_hnd, NULL);
    3764           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
    3765             :                         }
    3766             :                 }
    3767             : 
    3768        4065 :                 gnutls_hash_deinit(hash_hnd, req->preauth->sha512_value);
    3769             : 
    3770        4065 :                 req->preauth = NULL;
    3771             :         }
    3772             : 
    3773             :         /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
    3774      277051 :         if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
    3775      194305 :             outdyn->iov_base == NULL && outdyn->iov_len != 0) {
    3776             :                 /* Dynamic part is NULL. Chop it off,
    3777             :                    We're going to send it via sendfile. */
    3778           0 :                 req->out.vector_count -= 1;
    3779             :         }
    3780             : 
    3781             :         /*
    3782             :          * We're done with this request -
    3783             :          * move it off the "being processed" queue.
    3784             :          */
    3785      156976 :         DLIST_REMOVE(xconn->smb2.requests, req);
    3786             : 
    3787      156976 :         req->queue_entry.mem_ctx = req;
    3788      156976 :         req->queue_entry.vector = req->out.vector;
    3789      156976 :         req->queue_entry.count = req->out.vector_count;
    3790      156976 :         DLIST_ADD_END(xconn->smb2.send_queue, &req->queue_entry);
    3791      156976 :         xconn->smb2.send_queue_len++;
    3792             : 
    3793      156976 :         status = smbd_smb2_flush_send_queue(xconn);
    3794      156976 :         if (!NT_STATUS_IS_OK(status)) {
    3795        2492 :                 return status;
    3796             :         }
    3797             : 
    3798      154484 :         return NT_STATUS_OK;
    3799             : }
    3800             : 
    3801             : static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn);
    3802             : 
    3803           0 : void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
    3804             :                                         struct tevent_immediate *im,
    3805             :                                         void *private_data)
    3806             : {
    3807           0 :         struct smbd_smb2_request *req = talloc_get_type_abort(private_data,
    3808             :                                         struct smbd_smb2_request);
    3809           0 :         struct smbXsrv_connection *xconn = req->xconn;
    3810             :         NTSTATUS status;
    3811             : 
    3812           0 :         TALLOC_FREE(im);
    3813             : 
    3814           0 :         if (DEBUGLEVEL >= 10) {
    3815           0 :                 DEBUG(10,("smbd_smb2_request_dispatch_immediate: idx[%d] of %d vectors\n",
    3816             :                         req->current_idx, req->in.vector_count));
    3817           0 :                 print_req_vectors(req);
    3818             :         }
    3819             : 
    3820           0 :         status = smbd_smb2_request_dispatch(req);
    3821           0 :         if (!NT_STATUS_IS_OK(status)) {
    3822           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    3823           0 :                 return;
    3824             :         }
    3825             : 
    3826           0 :         status = smbd_smb2_request_next_incoming(xconn);
    3827           0 :         if (!NT_STATUS_IS_OK(status)) {
    3828           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    3829           0 :                 return;
    3830             :         }
    3831             : }
    3832             : 
    3833      156976 : NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
    3834             :                                    NTSTATUS status,
    3835             :                                    DATA_BLOB body, DATA_BLOB *dyn,
    3836             :                                    const char *location)
    3837             : {
    3838             :         uint8_t *outhdr;
    3839             :         struct iovec *outbody_v;
    3840             :         struct iovec *outdyn_v;
    3841             :         uint32_t next_command_ofs;
    3842             :         uint64_t mid;
    3843             : 
    3844      156976 :         outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
    3845      156976 :         mid = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
    3846             : 
    3847      156976 :         DBG_DEBUG("mid [%"PRIu64"] idx[%d] status[%s] "
    3848             :                   "body[%u] dyn[%s:%u] at %s\n",
    3849             :                   mid,
    3850             :                   req->current_idx,
    3851             :                   nt_errstr(status),
    3852             :                   (unsigned int)body.length,
    3853             :                   dyn ? "yes" : "no",
    3854             :                   (unsigned int)(dyn ? dyn->length : 0),
    3855             :                   location);
    3856             : 
    3857      156976 :         if (body.length < 2) {
    3858           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
    3859             :         }
    3860             : 
    3861      156976 :         if ((body.length % 2) != 0) {
    3862           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
    3863             :         }
    3864             : 
    3865      156976 :         outbody_v = SMBD_SMB2_OUT_BODY_IOV(req);
    3866      156976 :         outdyn_v = SMBD_SMB2_OUT_DYN_IOV(req);
    3867             : 
    3868      156976 :         next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
    3869      156976 :         SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
    3870             : 
    3871      156976 :         outbody_v->iov_base = (void *)body.data;
    3872      156976 :         outbody_v->iov_len = body.length;
    3873             : 
    3874      156976 :         if (dyn) {
    3875      132740 :                 outdyn_v->iov_base = (void *)dyn->data;
    3876      132740 :                 outdyn_v->iov_len = dyn->length;
    3877             :         } else {
    3878       24236 :                 outdyn_v->iov_base = NULL;
    3879       24236 :                 outdyn_v->iov_len = 0;
    3880             :         }
    3881             : 
    3882             :         /*
    3883             :          * See if we need to recalculate the offset to the next response
    3884             :          *
    3885             :          * Note that all responses may require padding (including the very last
    3886             :          * one).
    3887             :          */
    3888      156976 :         if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
    3889           0 :                 next_command_ofs  = SMB2_HDR_BODY;
    3890           0 :                 next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
    3891           0 :                 next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
    3892             :         }
    3893             : 
    3894      156976 :         if ((next_command_ofs % 8) != 0) {
    3895           0 :                 size_t pad_size = 8 - (next_command_ofs % 8);
    3896           0 :                 if (SMBD_SMB2_OUT_DYN_LEN(req) == 0) {
    3897             :                         /*
    3898             :                          * if the dyn buffer is empty
    3899             :                          * we can use it to add padding
    3900             :                          */
    3901             :                         uint8_t *pad;
    3902             : 
    3903           0 :                         pad = talloc_zero_array(req,
    3904             :                                                 uint8_t, pad_size);
    3905           0 :                         if (pad == NULL) {
    3906           0 :                                 return smbd_smb2_request_error(req,
    3907             :                                                 NT_STATUS_NO_MEMORY);
    3908             :                         }
    3909             : 
    3910           0 :                         outdyn_v->iov_base = (void *)pad;
    3911           0 :                         outdyn_v->iov_len = pad_size;
    3912             :                 } else {
    3913             :                         /*
    3914             :                          * For now we copy the dynamic buffer
    3915             :                          * and add the padding to the new buffer
    3916             :                          */
    3917             :                         size_t old_size;
    3918             :                         uint8_t *old_dyn;
    3919             :                         size_t new_size;
    3920             :                         uint8_t *new_dyn;
    3921             : 
    3922           0 :                         old_size = SMBD_SMB2_OUT_DYN_LEN(req);
    3923           0 :                         old_dyn = SMBD_SMB2_OUT_DYN_PTR(req);
    3924             : 
    3925           0 :                         new_size = old_size + pad_size;
    3926           0 :                         new_dyn = talloc_zero_array(req,
    3927             :                                                uint8_t, new_size);
    3928           0 :                         if (new_dyn == NULL) {
    3929           0 :                                 return smbd_smb2_request_error(req,
    3930             :                                                 NT_STATUS_NO_MEMORY);
    3931             :                         }
    3932             : 
    3933           0 :                         memcpy(new_dyn, old_dyn, old_size);
    3934           0 :                         memset(new_dyn + old_size, 0, pad_size);
    3935             : 
    3936           0 :                         outdyn_v->iov_base = (void *)new_dyn;
    3937           0 :                         outdyn_v->iov_len = new_size;
    3938             :                 }
    3939           0 :                 next_command_ofs += pad_size;
    3940             :         }
    3941             : 
    3942      156976 :         if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
    3943      156976 :                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
    3944             :         } else {
    3945           0 :                 SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
    3946             :         }
    3947      156976 :         return smbd_smb2_request_reply(req);
    3948             : }
    3949             : 
    3950        5432 : NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
    3951             :                                     NTSTATUS status,
    3952             :                                     DATA_BLOB *info,
    3953             :                                     const char *location)
    3954             : {
    3955        5432 :         struct smbXsrv_connection *xconn = req->xconn;
    3956             :         DATA_BLOB body;
    3957             :         DATA_BLOB _dyn;
    3958        5432 :         uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
    3959        5432 :         size_t unread_bytes = smbd_smb2_unread_bytes(req);
    3960             : 
    3961        5432 :         DBG_NOTICE("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| "
    3962             :                    "at %s\n", req->current_idx, nt_errstr(status),
    3963             :                    info ? " +info" : "", location);
    3964             : 
    3965        5432 :         if (unread_bytes) {
    3966             :                 /* Recvfile error. Drain incoming socket. */
    3967             :                 size_t ret;
    3968             : 
    3969           0 :                 errno = 0;
    3970           0 :                 ret = drain_socket(xconn->transport.sock, unread_bytes);
    3971           0 :                 if (ret != unread_bytes) {
    3972             :                         NTSTATUS error;
    3973             : 
    3974           0 :                         if (errno == 0) {
    3975           0 :                                 error = NT_STATUS_IO_DEVICE_ERROR;
    3976             :                         } else {
    3977           0 :                                 error = map_nt_error_from_unix_common(errno);
    3978             :                         }
    3979             : 
    3980           0 :                         DEBUG(2, ("Failed to drain %u bytes from SMB2 socket: "
    3981             :                                   "ret[%u] errno[%d] => %s\n",
    3982             :                                   (unsigned)unread_bytes,
    3983             :                                   (unsigned)ret, errno, nt_errstr(error)));
    3984           0 :                         return error;
    3985             :                 }
    3986             :         }
    3987             : 
    3988        5432 :         body.data = outhdr + SMB2_HDR_BODY;
    3989        5432 :         body.length = 8;
    3990        5432 :         SSVAL(body.data, 0, 9);
    3991             : 
    3992        5432 :         if (info) {
    3993           0 :                 SIVAL(body.data, 0x04, info->length);
    3994             :         } else {
    3995             :                 /* Allocated size of req->out.vector[i].iov_base
    3996             :                  * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for
    3997             :                  * 1 byte without having to do an alloc.
    3998             :                  */
    3999        5432 :                 info = &_dyn;
    4000        5432 :                 info->data = ((uint8_t *)outhdr) +
    4001        5432 :                         OUTVEC_ALLOC_SIZE - 1;
    4002        5432 :                 info->length = 1;
    4003        5432 :                 SCVAL(info->data, 0, 0);
    4004             :         }
    4005             : 
    4006             :         /*
    4007             :          * Note: Even if there is an error, continue to process the request.
    4008             :          * per MS-SMB2.
    4009             :          */
    4010             : 
    4011        5432 :         return smbd_smb2_request_done_ex(req, status, body, info, __location__);
    4012             : }
    4013             : 
    4014             : struct smbd_smb2_break_state {
    4015             :         struct tevent_req *req;
    4016             :         struct smbd_smb2_send_queue queue_entry;
    4017             :         uint8_t nbt_hdr[NBT_HDR_SIZE];
    4018             :         uint8_t hdr[SMB2_HDR_BODY];
    4019             :         struct iovec vector[1+SMBD_SMB2_NUM_IOV_PER_REQ];
    4020             : };
    4021             : 
    4022           0 : static struct tevent_req *smbd_smb2_break_send(TALLOC_CTX *mem_ctx,
    4023             :                                                struct tevent_context *ev,
    4024             :                                                struct smbXsrv_connection *xconn,
    4025             :                                                uint64_t session_id,
    4026             :                                                const uint8_t *body,
    4027             :                                                size_t body_len)
    4028             : {
    4029           0 :         struct tevent_req *req = NULL;
    4030           0 :         struct smbd_smb2_break_state *state = NULL;
    4031             :         NTSTATUS status;
    4032             :         bool ok;
    4033             : 
    4034           0 :         req = tevent_req_create(mem_ctx, &state,
    4035             :                                 struct smbd_smb2_break_state);
    4036           0 :         if (req == NULL) {
    4037           0 :                 return NULL;
    4038             :         }
    4039             : 
    4040           0 :         state->req = req;
    4041           0 :         tevent_req_defer_callback(req, ev);
    4042             : 
    4043           0 :         SIVAL(state->hdr, 0,                         SMB2_MAGIC);
    4044           0 :         SSVAL(state->hdr, SMB2_HDR_LENGTH,           SMB2_HDR_BODY);
    4045           0 :         SSVAL(state->hdr, SMB2_HDR_EPOCH,            0);
    4046           0 :         SIVAL(state->hdr, SMB2_HDR_STATUS,           0);
    4047           0 :         SSVAL(state->hdr, SMB2_HDR_OPCODE,           SMB2_OP_BREAK);
    4048           0 :         SSVAL(state->hdr, SMB2_HDR_CREDIT,           0);
    4049           0 :         SIVAL(state->hdr, SMB2_HDR_FLAGS,            SMB2_HDR_FLAG_REDIRECT);
    4050           0 :         SIVAL(state->hdr, SMB2_HDR_NEXT_COMMAND,     0);
    4051           0 :         SBVAL(state->hdr, SMB2_HDR_MESSAGE_ID,               UINT64_MAX);
    4052           0 :         SIVAL(state->hdr, SMB2_HDR_PID,                      0);
    4053           0 :         SIVAL(state->hdr, SMB2_HDR_TID,                      0);
    4054           0 :         SBVAL(state->hdr, SMB2_HDR_SESSION_ID,               session_id);
    4055           0 :         memset(state->hdr+SMB2_HDR_SIGNATURE, 0, 16);
    4056             : 
    4057           0 :         state->vector[0] = (struct iovec) {
    4058           0 :                 .iov_base = state->nbt_hdr,
    4059             :                 .iov_len  = sizeof(state->nbt_hdr)
    4060             :         };
    4061             : 
    4062           0 :         state->vector[1+SMBD_SMB2_TF_IOV_OFS] = (struct iovec) {
    4063             :                 .iov_base = NULL,
    4064             :                 .iov_len  = 0
    4065             :         };
    4066             : 
    4067           0 :         state->vector[1+SMBD_SMB2_HDR_IOV_OFS] = (struct iovec) {
    4068           0 :                 .iov_base = state->hdr,
    4069             :                 .iov_len  = sizeof(state->hdr)
    4070             :         };
    4071             : 
    4072           0 :         state->vector[1+SMBD_SMB2_BODY_IOV_OFS] = (struct iovec) {
    4073             :                 .iov_base = discard_const_p(uint8_t, body),
    4074             :                 .iov_len  = body_len,
    4075             :         };
    4076             : 
    4077             :         /*
    4078             :          * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
    4079             :          */
    4080             : 
    4081           0 :         ok = smb2_setup_nbt_length(state->vector,
    4082             :                                    1 + SMBD_SMB2_NUM_IOV_PER_REQ);
    4083           0 :         if (!ok) {
    4084           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
    4085           0 :                 return tevent_req_post(req, ev);
    4086             :         }
    4087             : 
    4088             :         /*
    4089             :          * We require TCP acks for this PDU to the client!
    4090             :          * We want 5 retransmissions and timeout when the
    4091             :          * retransmission timeout (rto) passed 6 times.
    4092             :          *
    4093             :          * required_acked_bytes gets a dummy value of
    4094             :          * UINT64_MAX, as long it's in xconn->smb2.send_queue,
    4095             :          * it'll get the real value when it's moved to
    4096             :          * xconn->ack.queue.
    4097             :          *
    4098             :          * state->queue_entry.ack.req gets completed with
    4099             :          * 1.  tevent_req_done(), when all bytes are acked.
    4100             :          * 2a. tevent_req_nterror(NT_STATUS_IO_TIMEOUT), when
    4101             :          *     the timeout expired before all bytes were acked.
    4102             :          * 2b. tevent_req_nterror(transport_error), when the
    4103             :          *     connection got a disconnect from the kernel.
    4104             :          */
    4105           0 :         state->queue_entry.ack.timeout =
    4106           0 :                 timeval_current_ofs_usec(xconn->ack.rto_usecs * 6);
    4107           0 :         state->queue_entry.ack.required_acked_bytes = UINT64_MAX;
    4108           0 :         state->queue_entry.ack.req = req;
    4109           0 :         state->queue_entry.mem_ctx = state;
    4110           0 :         state->queue_entry.vector = state->vector;
    4111           0 :         state->queue_entry.count = ARRAY_SIZE(state->vector);
    4112           0 :         DLIST_ADD_END(xconn->smb2.send_queue, &state->queue_entry);
    4113           0 :         xconn->smb2.send_queue_len++;
    4114             : 
    4115           0 :         status = smbd_smb2_flush_send_queue(xconn);
    4116           0 :         if (tevent_req_nterror(req, status)) {
    4117           0 :                 return tevent_req_post(req, ev);
    4118             :         }
    4119             : 
    4120           0 :         return req;
    4121             : }
    4122             : 
    4123           0 : static NTSTATUS smbd_smb2_break_recv(struct tevent_req *req)
    4124             : {
    4125           0 :         return tevent_req_simple_recv_ntstatus(req);
    4126             : }
    4127             : 
    4128             : struct smbXsrv_pending_break {
    4129             :         struct smbXsrv_pending_break *prev, *next;
    4130             :         struct smbXsrv_client *client;
    4131             :         bool disable_oplock_break_retries;
    4132             :         uint64_t session_id;
    4133             :         uint64_t last_channel_id;
    4134             :         union {
    4135             :                 uint8_t generic[1];
    4136             :                 uint8_t oplock[0x18];
    4137             :                 uint8_t lease[0x2c];
    4138             :         } body;
    4139             :         size_t body_len;
    4140             : };
    4141             : 
    4142             : static void smbXsrv_pending_break_done(struct tevent_req *subreq);
    4143             : 
    4144           0 : static struct smbXsrv_pending_break *smbXsrv_pending_break_create(
    4145             :                 struct smbXsrv_client *client,
    4146             :                 uint64_t session_id)
    4147             : {
    4148           0 :         struct smbXsrv_pending_break *pb = NULL;
    4149             : 
    4150           0 :         pb = talloc_zero(client, struct smbXsrv_pending_break);
    4151           0 :         if (pb == NULL) {
    4152           0 :                 return NULL;
    4153             :         }
    4154           0 :         pb->client = client;
    4155           0 :         pb->session_id = session_id;
    4156           0 :         pb->disable_oplock_break_retries = lp_smb2_disable_oplock_break_retry();
    4157             : 
    4158           0 :         return pb;
    4159             : }
    4160             : 
    4161             : static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb);
    4162             : 
    4163           0 : static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb)
    4164             : {
    4165           0 :         struct smbXsrv_client *client = pb->client;
    4166             :         NTSTATUS status;
    4167             : 
    4168           0 :         DLIST_ADD_END(client->pending_breaks, pb);
    4169           0 :         status = smbXsrv_client_pending_breaks_updated(client);
    4170           0 :         if (!NT_STATUS_IS_OK(status)) {
    4171           0 :                 return status;
    4172             :         }
    4173             : 
    4174           0 :         status = smbXsrv_pending_break_submit(pb);
    4175           0 :         if (!NT_STATUS_IS_OK(status)) {
    4176           0 :                 return status;
    4177             :         }
    4178             : 
    4179           0 :         return NT_STATUS_OK;
    4180             : }
    4181             : 
    4182           0 : static NTSTATUS smbXsrv_pending_break_submit(struct smbXsrv_pending_break *pb)
    4183             : {
    4184           0 :         struct smbXsrv_client *client = pb->client;
    4185           0 :         struct smbXsrv_session *session = NULL;
    4186           0 :         struct smbXsrv_connection *xconn = NULL;
    4187           0 :         struct smbXsrv_connection *oplock_xconn = NULL;
    4188           0 :         struct tevent_req *subreq = NULL;
    4189             :         NTSTATUS status;
    4190             : 
    4191           0 :         if (pb->session_id != 0) {
    4192           0 :                 status = get_valid_smbXsrv_session(client,
    4193             :                                                    pb->session_id,
    4194             :                                                    &session);
    4195           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
    4196           0 :                         return NT_STATUS_ABANDONED;
    4197             :                 }
    4198           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4199           0 :                         return status;
    4200             :                 }
    4201             : 
    4202           0 :                 if (pb->last_channel_id != 0) {
    4203             :                         /*
    4204             :                          * This is what current Windows servers
    4205             :                          * do, they don't retry on all available
    4206             :                          * channels. They only use the last channel.
    4207             :                          *
    4208             :                          * But it doesn't match the specification in
    4209             :                          * [MS-SMB2] "3.3.4.6 Object Store Indicates an
    4210             :                          * Oplock Break"
    4211             :                          *
    4212             :                          * Per default disable_oplock_break_retries is false
    4213             :                          * and we behave like the specification.
    4214             :                          */
    4215           0 :                         if (pb->disable_oplock_break_retries) {
    4216           0 :                                 return NT_STATUS_ABANDONED;
    4217             :                         }
    4218             :                 }
    4219             :         }
    4220             : 
    4221           0 :         for (xconn = client->connections; xconn != NULL; xconn = xconn->next) {
    4222           0 :                 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    4223           0 :                         continue;
    4224             :                 }
    4225             : 
    4226           0 :                 if (xconn->channel_id == 0) {
    4227             :                         /*
    4228             :                          * non-multichannel case
    4229             :                          */
    4230           0 :                         break;
    4231             :                 }
    4232             : 
    4233           0 :                 if (session != NULL) {
    4234           0 :                         struct smbXsrv_channel_global0 *c = NULL;
    4235             : 
    4236             :                         /*
    4237             :                          * Having a session means we're handling
    4238             :                          * an oplock break and we only need to
    4239             :                          * use channels available on the
    4240             :                          * session.
    4241             :                          */
    4242           0 :                         status = smbXsrv_session_find_channel(session, xconn, &c);
    4243           0 :                         if (!NT_STATUS_IS_OK(status)) {
    4244           0 :                                 continue;
    4245             :                         }
    4246             : 
    4247             :                         /*
    4248             :                          * This is what current Windows servers
    4249             :                          * do, they don't retry on all available
    4250             :                          * channels. They only use the last channel.
    4251             :                          *
    4252             :                          * But it doesn't match the specification
    4253             :                          * in [MS-SMB2] "3.3.4.6 Object Store Indicates an
    4254             :                          * Oplock Break"
    4255             :                          *
    4256             :                          * Per default disable_oplock_break_retries is false
    4257             :                          * and we behave like the specification.
    4258             :                          */
    4259           0 :                         if (pb->disable_oplock_break_retries) {
    4260           0 :                                 oplock_xconn = xconn;
    4261           0 :                                 continue;
    4262             :                         }
    4263             :                 }
    4264             : 
    4265           0 :                 if (xconn->channel_id > pb->last_channel_id) {
    4266             :                         /*
    4267             :                          * multichannel case
    4268             :                          */
    4269           0 :                         break;
    4270             :                 }
    4271             :         }
    4272             : 
    4273           0 :         if (xconn == NULL) {
    4274           0 :                 xconn = oplock_xconn;
    4275             :         }
    4276             : 
    4277           0 :         if (xconn == NULL) {
    4278             :                 /*
    4279             :                  * If there's no remaining connection available
    4280             :                  * tell the caller to stop...
    4281             :                  */
    4282           0 :                 return NT_STATUS_ABANDONED;
    4283             :         }
    4284             : 
    4285           0 :         pb->last_channel_id = xconn->channel_id;
    4286             : 
    4287           0 :         subreq = smbd_smb2_break_send(pb,
    4288             :                                       client->raw_ev_ctx,
    4289             :                                       xconn,
    4290             :                                       pb->session_id,
    4291           0 :                                       pb->body.generic,
    4292             :                                       pb->body_len);
    4293           0 :         if (subreq == NULL) {
    4294           0 :                 return NT_STATUS_NO_MEMORY;
    4295             :         }
    4296           0 :         tevent_req_set_callback(subreq,
    4297             :                                 smbXsrv_pending_break_done,
    4298             :                                 pb);
    4299             : 
    4300           0 :         return NT_STATUS_OK;
    4301             : }
    4302             : 
    4303           0 : static void smbXsrv_pending_break_done(struct tevent_req *subreq)
    4304             : {
    4305           0 :         struct smbXsrv_pending_break *pb =
    4306           0 :                 tevent_req_callback_data(subreq,
    4307             :                 struct smbXsrv_pending_break);
    4308           0 :         struct smbXsrv_client *client = pb->client;
    4309             :         NTSTATUS status;
    4310             : 
    4311           0 :         status = smbd_smb2_break_recv(subreq);
    4312           0 :         TALLOC_FREE(subreq);
    4313           0 :         if (!NT_STATUS_IS_OK(status)) {
    4314           0 :                 status = smbXsrv_pending_break_submit(pb);
    4315           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_ABANDONED)) {
    4316             :                         /*
    4317             :                          * If there's no remaing connection
    4318             :                          * there's no need to send a break again.
    4319             :                          */
    4320           0 :                         goto remove;
    4321             :                 }
    4322           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4323           0 :                         smbd_server_disconnect_client(client, nt_errstr(status));
    4324           0 :                         return;
    4325             :                 }
    4326           0 :                 return;
    4327             :         }
    4328             : 
    4329           0 : remove:
    4330           0 :         DLIST_REMOVE(client->pending_breaks, pb);
    4331           0 :         TALLOC_FREE(pb);
    4332             : 
    4333           0 :         status = smbXsrv_client_pending_breaks_updated(client);
    4334           0 :         if (!NT_STATUS_IS_OK(status)) {
    4335           0 :                 smbd_server_disconnect_client(client, nt_errstr(status));
    4336           0 :                 return;
    4337             :         }
    4338             : }
    4339             : 
    4340           0 : NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client,
    4341             :                                      struct smbXsrv_open *op,
    4342             :                                      uint8_t oplock_level)
    4343             : {
    4344           0 :         struct smbXsrv_pending_break *pb = NULL;
    4345           0 :         uint8_t *body = NULL;
    4346             : 
    4347           0 :         pb = smbXsrv_pending_break_create(client,
    4348           0 :                                           op->compat->vuid);
    4349           0 :         if (pb == NULL) {
    4350           0 :                 return NT_STATUS_NO_MEMORY;
    4351             :         }
    4352           0 :         pb->body_len = sizeof(pb->body.oplock);
    4353           0 :         body = pb->body.oplock;
    4354             : 
    4355           0 :         SSVAL(body, 0x00, pb->body_len);
    4356           0 :         SCVAL(body, 0x02, oplock_level);
    4357           0 :         SCVAL(body, 0x03, 0);           /* reserved */
    4358           0 :         SIVAL(body, 0x04, 0);           /* reserved */
    4359           0 :         SBVAL(body, 0x08, op->global->open_persistent_id);
    4360           0 :         SBVAL(body, 0x10, op->global->open_volatile_id);
    4361             : 
    4362           0 :         return smbXsrv_pending_break_schedule(pb);
    4363             : }
    4364             : 
    4365           0 : NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client,
    4366             :                                     uint16_t new_epoch,
    4367             :                                     uint32_t lease_flags,
    4368             :                                     struct smb2_lease_key *lease_key,
    4369             :                                     uint32_t current_lease_state,
    4370             :                                     uint32_t new_lease_state)
    4371             : {
    4372           0 :         struct smbXsrv_pending_break *pb = NULL;
    4373           0 :         uint8_t *body = NULL;
    4374             : 
    4375           0 :         pb = smbXsrv_pending_break_create(client,
    4376             :                                           0); /* no session_id */
    4377           0 :         if (pb == NULL) {
    4378           0 :                 return NT_STATUS_NO_MEMORY;
    4379             :         }
    4380           0 :         pb->body_len = sizeof(pb->body.lease);
    4381           0 :         body = pb->body.lease;
    4382             : 
    4383           0 :         SSVAL(body, 0x00, pb->body_len);
    4384           0 :         SSVAL(body, 0x02, new_epoch);
    4385           0 :         SIVAL(body, 0x04, lease_flags);
    4386           0 :         SBVAL(body, 0x08, lease_key->data[0]);
    4387           0 :         SBVAL(body, 0x10, lease_key->data[1]);
    4388           0 :         SIVAL(body, 0x18, current_lease_state);
    4389           0 :         SIVAL(body, 0x1c, new_lease_state);
    4390           0 :         SIVAL(body, 0x20, 0);           /* BreakReason, MUST be 0 */
    4391           0 :         SIVAL(body, 0x24, 0);           /* AccessMaskHint, MUST be 0 */
    4392           0 :         SIVAL(body, 0x28, 0);           /* ShareMaskHint, MUST be 0 */
    4393             : 
    4394           0 :         return smbXsrv_pending_break_schedule(pb);
    4395             : }
    4396             : 
    4397           0 : static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
    4398             : {
    4399             :         NTSTATUS status;
    4400             :         uint32_t flags;
    4401             :         uint64_t file_id_persistent;
    4402             :         uint64_t file_id_volatile;
    4403           0 :         struct smbXsrv_open *op = NULL;
    4404           0 :         struct files_struct *fsp = NULL;
    4405           0 :         const uint8_t *body = NULL;
    4406             : 
    4407             :         /*
    4408             :          * This is only called with a pktbuf
    4409             :          * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
    4410             :          * bytes
    4411             :          */
    4412             : 
    4413           0 :         if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
    4414             :                 /* Transform header. Cannot recvfile. */
    4415           0 :                 return false;
    4416             :         }
    4417           0 :         if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) {
    4418             :                 /* Not SMB2. Normal error path will cope. */
    4419           0 :                 return false;
    4420             :         }
    4421           0 :         if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) {
    4422             :                 /* Not SMB2. Normal error path will cope. */
    4423           0 :                 return false;
    4424             :         }
    4425           0 :         if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) {
    4426             :                 /* Needs to be a WRITE. */
    4427           0 :                 return false;
    4428             :         }
    4429           0 :         if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) {
    4430             :                 /* Chained. Cannot recvfile. */
    4431           0 :                 return false;
    4432             :         }
    4433           0 :         flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS);
    4434           0 :         if (flags & SMB2_HDR_FLAG_CHAINED) {
    4435             :                 /* Chained. Cannot recvfile. */
    4436           0 :                 return false;
    4437             :         }
    4438           0 :         if (flags & SMB2_HDR_FLAG_SIGNED) {
    4439             :                 /* Signed. Cannot recvfile. */
    4440           0 :                 return false;
    4441             :         }
    4442             : 
    4443           0 :         body = &state->pktbuf[SMB2_HDR_BODY];
    4444             : 
    4445           0 :         file_id_persistent      = BVAL(body, 0x10);
    4446           0 :         file_id_volatile        = BVAL(body, 0x18);
    4447             : 
    4448           0 :         status = smb2srv_open_lookup(state->req->xconn,
    4449             :                                      file_id_persistent,
    4450             :                                      file_id_volatile,
    4451             :                                      0, /* now */
    4452             :                                      &op);
    4453           0 :         if (!NT_STATUS_IS_OK(status)) {
    4454           0 :                 return false;
    4455             :         }
    4456             : 
    4457           0 :         fsp = op->compat;
    4458           0 :         if (fsp == NULL) {
    4459           0 :                 return false;
    4460             :         }
    4461           0 :         if (fsp->conn == NULL) {
    4462           0 :                 return false;
    4463             :         }
    4464             : 
    4465           0 :         if (IS_IPC(fsp->conn)) {
    4466           0 :                 return false;
    4467             :         }
    4468           0 :         if (IS_PRINT(fsp->conn)) {
    4469           0 :                 return false;
    4470             :         }
    4471           0 :         if (fsp_is_alternate_stream(fsp)) {
    4472           0 :                 return false;
    4473             :         }
    4474             : 
    4475           0 :         DEBUG(10,("Doing recvfile write len = %u\n",
    4476             :                 (unsigned int)(state->pktfull - state->pktlen)));
    4477             : 
    4478           0 :         return true;
    4479             : }
    4480             : 
    4481      330669 : static NTSTATUS smbd_smb2_request_next_incoming(struct smbXsrv_connection *xconn)
    4482             : {
    4483      330669 :         struct smbd_server_connection *sconn = xconn->client->sconn;
    4484      330669 :         struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
    4485             :         size_t max_send_queue_len;
    4486             :         size_t cur_send_queue_len;
    4487             : 
    4488      330669 :         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    4489             :                 /*
    4490             :                  * we're not supposed to do any io
    4491             :                  */
    4492           0 :                 return NT_STATUS_OK;
    4493             :         }
    4494             : 
    4495      330669 :         if (state->req != NULL) {
    4496             :                 /*
    4497             :                  * if there is already a tstream_readv_pdu
    4498             :                  * pending, we are done.
    4499             :                  */
    4500      176117 :                 return NT_STATUS_OK;
    4501             :         }
    4502             : 
    4503      154552 :         max_send_queue_len = MAX(1, xconn->smb2.credits.max/16);
    4504      154552 :         cur_send_queue_len = xconn->smb2.send_queue_len;
    4505             : 
    4506      154552 :         if (cur_send_queue_len > max_send_queue_len) {
    4507             :                 /*
    4508             :                  * if we have a lot of requests to send,
    4509             :                  * we wait until they are on the wire until we
    4510             :                  * ask for the next request.
    4511             :                  */
    4512           0 :                 return NT_STATUS_OK;
    4513             :         }
    4514             : 
    4515             :         /* ask for the next request */
    4516      154552 :         ZERO_STRUCTP(state);
    4517      154552 :         state->req = smbd_smb2_request_allocate(xconn);
    4518      154552 :         if (state->req == NULL) {
    4519           0 :                 return NT_STATUS_NO_MEMORY;
    4520             :         }
    4521      154552 :         state->req->sconn = sconn;
    4522      154552 :         state->req->xconn = xconn;
    4523      154552 :         state->min_recv_size = lp_min_receive_file_size();
    4524             : 
    4525      154552 :         TEVENT_FD_READABLE(xconn->transport.fde);
    4526             : 
    4527      154552 :         return NT_STATUS_OK;
    4528             : }
    4529             : 
    4530        5052 : NTSTATUS smbd_smb2_process_negprot(struct smbXsrv_connection *xconn,
    4531             :                                uint64_t expected_seq_low,
    4532             :                                const uint8_t *inpdu, size_t size)
    4533             : {
    4534        5052 :         struct smbd_server_connection *sconn = xconn->client->sconn;
    4535             :         NTSTATUS status;
    4536        5052 :         struct smbd_smb2_request *req = NULL;
    4537             : 
    4538        5052 :         DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
    4539             :                  (unsigned int)size));
    4540             : 
    4541        5052 :         status = smbd_initialize_smb2(xconn, expected_seq_low);
    4542        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4543           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4544           0 :                 return status;
    4545             :         }
    4546             : 
    4547             :         /*
    4548             :          * If a new connection joins the process, when we're
    4549             :          * already in a "pending break cycle", we need to
    4550             :          * turn on the ack checker on the new connection.
    4551             :          */
    4552        5052 :         status = smbXsrv_client_pending_breaks_updated(xconn->client);
    4553        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4554             :                 /*
    4555             :                  * If there's a problem, we disconnect the whole
    4556             :                  * client with all connections here!
    4557             :                  *
    4558             :                  * Instead of just the new connection.
    4559             :                  */
    4560           0 :                 smbd_server_disconnect_client(xconn->client, nt_errstr(status));
    4561           0 :                 return status;
    4562             :         }
    4563             : 
    4564        5052 :         status = smbd_smb2_request_create(xconn, inpdu, size, &req);
    4565        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4566           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4567           0 :                 return status;
    4568             :         }
    4569             : 
    4570        5052 :         status = smbd_smb2_request_validate(req);
    4571        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4572           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4573           0 :                 return status;
    4574             :         }
    4575             : 
    4576        5052 :         status = smbd_smb2_request_setup_out(req);
    4577        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4578           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4579           0 :                 return status;
    4580             :         }
    4581             : 
    4582             : #ifdef WITH_PROFILE
    4583             :         /*
    4584             :          * this was already counted at the SMB1 layer =>
    4585             :          * smbd_smb2_request_dispatch() should not count it twice.
    4586             :          */
    4587        5052 :         if (profile_p->values.request_stats.count > 0) {
    4588           0 :                 profile_p->values.request_stats.count--;
    4589             :         }
    4590             : #endif
    4591        5052 :         status = smbd_smb2_request_dispatch(req);
    4592        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4593           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4594           0 :                 return status;
    4595             :         }
    4596             : 
    4597        5052 :         status = smbd_smb2_request_next_incoming(xconn);
    4598        5052 :         if (!NT_STATUS_IS_OK(status)) {
    4599           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    4600           0 :                 return status;
    4601             :         }
    4602             : 
    4603        5052 :         sconn->num_requests++;
    4604        5052 :         return NT_STATUS_OK;
    4605             : }
    4606             : 
    4607      665996 : static int socket_error_from_errno(int ret,
    4608             :                                    int sys_errno,
    4609             :                                    bool *retry)
    4610             : {
    4611      665996 :         *retry = false;
    4612             : 
    4613      665996 :         if (ret >= 0) {
    4614      663225 :                 return 0;
    4615             :         }
    4616             : 
    4617        2771 :         if (ret != -1) {
    4618           0 :                 return EIO;
    4619             :         }
    4620             : 
    4621        2771 :         if (sys_errno == 0) {
    4622           0 :                 return EIO;
    4623             :         }
    4624             : 
    4625        2771 :         if (sys_errno == EINTR) {
    4626           0 :                 *retry = true;
    4627           0 :                 return sys_errno;
    4628             :         }
    4629             : 
    4630        2771 :         if (sys_errno == EINPROGRESS) {
    4631           0 :                 *retry = true;
    4632           0 :                 return sys_errno;
    4633             :         }
    4634             : 
    4635        2771 :         if (sys_errno == EAGAIN) {
    4636           0 :                 *retry = true;
    4637           0 :                 return sys_errno;
    4638             :         }
    4639             : 
    4640             :         /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
    4641        2771 :         if (sys_errno == ENOMEM) {
    4642           0 :                 *retry = true;
    4643           0 :                 return sys_errno;
    4644             :         }
    4645             : 
    4646             : #ifdef EWOULDBLOCK
    4647             : #if EWOULDBLOCK != EAGAIN
    4648             :         if (sys_errno == EWOULDBLOCK) {
    4649             :                 *retry = true;
    4650             :                 return sys_errno;
    4651             :         }
    4652             : #endif
    4653             : #endif
    4654             : 
    4655        2771 :         return sys_errno;
    4656             : }
    4657             : 
    4658      271307 : static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
    4659             : {
    4660             :         int ret;
    4661             :         int err;
    4662             :         bool retry;
    4663             :         NTSTATUS status;
    4664             : 
    4665      271307 :         if (xconn->smb2.send_queue == NULL) {
    4666        5694 :                 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
    4667        5694 :                 return NT_STATUS_OK;
    4668             :         }
    4669             : 
    4670      635216 :         while (xconn->smb2.send_queue != NULL) {
    4671      265626 :                 struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
    4672             :                 bool ok;
    4673             :                 struct msghdr msg;
    4674             : 
    4675      265626 :                 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    4676             :                         /*
    4677             :                          * we're not supposed to do any io
    4678             :                          * just flush all pending stuff.
    4679             :                          */
    4680           0 :                         xconn->smb2.send_queue_len--;
    4681           0 :                         DLIST_REMOVE(xconn->smb2.send_queue, e);
    4682             : 
    4683           0 :                         talloc_free(e->mem_ctx);
    4684      176130 :                         continue;
    4685             :                 }
    4686             : 
    4687      265626 :                 if (e->sendfile_header != NULL) {
    4688           0 :                         size_t size = 0;
    4689           0 :                         size_t i = 0;
    4690             :                         uint8_t *buf;
    4691             : 
    4692           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    4693             : 
    4694           0 :                         for (i=0; i < e->count; i++) {
    4695           0 :                                 size += e->vector[i].iov_len;
    4696             :                         }
    4697             : 
    4698           0 :                         if (size <= e->sendfile_header->length) {
    4699           0 :                                 buf = e->sendfile_header->data;
    4700             :                         } else {
    4701           0 :                                 buf = talloc_array(e->mem_ctx, uint8_t, size);
    4702           0 :                                 if (buf == NULL) {
    4703       55574 :                                         return NT_STATUS_NO_MEMORY;
    4704             :                                 }
    4705             :                         }
    4706             : 
    4707           0 :                         size = 0;
    4708           0 :                         for (i=0; i < e->count; i++) {
    4709           0 :                                 memcpy(buf+size,
    4710           0 :                                        e->vector[i].iov_base,
    4711           0 :                                        e->vector[i].iov_len);
    4712           0 :                                 size += e->vector[i].iov_len;
    4713             :                         }
    4714             : 
    4715           0 :                         e->sendfile_header->data = buf;
    4716           0 :                         e->sendfile_header->length = size;
    4717           0 :                         e->sendfile_status = &status;
    4718           0 :                         e->count = 0;
    4719             : 
    4720           0 :                         xconn->smb2.send_queue_len--;
    4721           0 :                         DLIST_REMOVE(xconn->smb2.send_queue, e);
    4722             : 
    4723           0 :                         size += e->sendfile_body_size;
    4724             : 
    4725             :                         /*
    4726             :                          * This triggers the sendfile path via
    4727             :                          * the destructor.
    4728             :                          */
    4729           0 :                         talloc_free(e->mem_ctx);
    4730             : 
    4731           0 :                         if (!NT_STATUS_IS_OK(status)) {
    4732           0 :                                 smbXsrv_connection_disconnect_transport(xconn,
    4733             :                                                                         status);
    4734           0 :                                 return status;
    4735             :                         }
    4736           0 :                         xconn->ack.unacked_bytes += size;
    4737           0 :                         continue;
    4738             :                 }
    4739             : 
    4740      265626 :                 msg = (struct msghdr) {
    4741      265626 :                         .msg_iov = e->vector,
    4742      265626 :                         .msg_iovlen = e->count,
    4743             :                 };
    4744             : 
    4745      265626 :                 ret = sendmsg(xconn->transport.sock, &msg, 0);
    4746      265626 :                 if (ret == 0) {
    4747             :                         /* propagate end of file */
    4748           0 :                         return NT_STATUS_INTERNAL_ERROR;
    4749             :                 }
    4750      265626 :                 err = socket_error_from_errno(ret, errno, &retry);
    4751      265626 :                 if (retry) {
    4752             :                         /* retry later */
    4753           0 :                         TEVENT_FD_WRITEABLE(xconn->transport.fde);
    4754           0 :                         return NT_STATUS_OK;
    4755             :                 }
    4756      265626 :                 if (err != 0) {
    4757        2492 :                         status = map_nt_error_from_unix_common(err);
    4758        2492 :                         smbXsrv_connection_disconnect_transport(xconn,
    4759             :                                                                 status);
    4760        2492 :                         return status;
    4761             :                 }
    4762             : 
    4763      263134 :                 xconn->ack.unacked_bytes += ret;
    4764             : 
    4765      263134 :                 ok = iov_advance(&e->vector, &e->count, ret);
    4766      263134 :                 if (!ok) {
    4767           0 :                         return NT_STATUS_INTERNAL_ERROR;
    4768             :                 }
    4769             : 
    4770      263134 :                 if (e->count > 0) {
    4771             :                         /* we have more to write */
    4772       87004 :                         TEVENT_FD_WRITEABLE(xconn->transport.fde);
    4773       87004 :                         return NT_STATUS_OK;
    4774             :                 }
    4775             : 
    4776      176130 :                 xconn->smb2.send_queue_len--;
    4777      176130 :                 DLIST_REMOVE(xconn->smb2.send_queue, e);
    4778             : 
    4779      176130 :                 if (e->ack.req == NULL) {
    4780      176130 :                         talloc_free(e->mem_ctx);
    4781      176130 :                         continue;
    4782             :                 }
    4783             : 
    4784           0 :                 e->ack.required_acked_bytes = xconn->ack.unacked_bytes;
    4785           0 :                 DLIST_ADD_END(xconn->ack.queue, e);
    4786             :         }
    4787             : 
    4788             :         /*
    4789             :          * Restart reads if we were blocked on
    4790             :          * draining the send queue.
    4791             :          */
    4792             : 
    4793      176117 :         status = smbd_smb2_request_next_incoming(xconn);
    4794      176117 :         if (!NT_STATUS_IS_OK(status)) {
    4795           0 :                 return status;
    4796             :         }
    4797             : 
    4798      176117 :         return NT_STATUS_OK;
    4799             : }
    4800             : 
    4801      343086 : static NTSTATUS smbd_smb2_io_handler(struct smbXsrv_connection *xconn,
    4802             :                                      uint16_t fde_flags)
    4803             : {
    4804      343086 :         struct smbd_server_connection *sconn = xconn->client->sconn;
    4805      343086 :         struct smbd_smb2_request_read_state *state = &xconn->smb2.request_read_state;
    4806      343086 :         struct smbd_smb2_request *req = NULL;
    4807      343086 :         size_t min_recvfile_size = UINT32_MAX;
    4808             :         int ret;
    4809             :         int err;
    4810             :         bool retry;
    4811             :         NTSTATUS status;
    4812             :         NTTIME now;
    4813             :         struct msghdr msg;
    4814             : 
    4815      343086 :         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    4816             :                 /*
    4817             :                  * we're not supposed to do any io
    4818             :                  */
    4819           0 :                 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
    4820           0 :                 TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
    4821           0 :                 return NT_STATUS_OK;
    4822             :         }
    4823             : 
    4824      343086 :         if (fde_flags & TEVENT_FD_WRITE) {
    4825       92685 :                 status = smbd_smb2_flush_send_queue(xconn);
    4826       92685 :                 if (!NT_STATUS_IS_OK(status)) {
    4827           0 :                         return status;
    4828             :                 }
    4829             :         }
    4830             : 
    4831      343086 :         if (!(fde_flags & TEVENT_FD_READ)) {
    4832       92487 :                 return NT_STATUS_OK;
    4833             :         }
    4834             : 
    4835      250599 :         if (state->req == NULL) {
    4836           0 :                 TEVENT_FD_NOT_READABLE(xconn->transport.fde);
    4837           0 :                 return NT_STATUS_OK;
    4838             :         }
    4839             : 
    4840      285985 : again:
    4841      402591 :         if (!state->hdr.done) {
    4842      154492 :                 state->hdr.done = true;
    4843             : 
    4844      154492 :                 state->vector.iov_base = (void *)state->hdr.nbt;
    4845      154492 :                 state->vector.iov_len = NBT_HDR_SIZE;
    4846             :         }
    4847             : 
    4848      402591 :         msg = (struct msghdr) {
    4849      402591 :                 .msg_iov = &state->vector,
    4850             :                 .msg_iovlen = 1,
    4851             :         };
    4852             : 
    4853      402591 :         ret = recvmsg(xconn->transport.sock, &msg, 0);
    4854      402591 :         if (ret == 0) {
    4855             :                 /* propagate end of file */
    4856        2221 :                 status = NT_STATUS_END_OF_FILE;
    4857        2221 :                 smbXsrv_connection_disconnect_transport(xconn,
    4858             :                                                         status);
    4859        2221 :                 return status;
    4860             :         }
    4861      400370 :         err = socket_error_from_errno(ret, errno, &retry);
    4862      400370 :         if (retry) {
    4863             :                 /* retry later */
    4864           0 :                 TEVENT_FD_READABLE(xconn->transport.fde);
    4865           0 :                 return NT_STATUS_OK;
    4866             :         }
    4867      400370 :         if (err != 0) {
    4868         279 :                 status = map_nt_error_from_unix_common(err);
    4869         279 :                 smbXsrv_connection_disconnect_transport(xconn,
    4870             :                                                         status);
    4871         279 :                 return status;
    4872             :         }
    4873             : 
    4874      400091 :         if (ret < state->vector.iov_len) {
    4875             :                 uint8_t *base;
    4876       96107 :                 base = (uint8_t *)state->vector.iov_base;
    4877       96107 :                 base += ret;
    4878       96107 :                 state->vector.iov_base = (void *)base;
    4879       96107 :                 state->vector.iov_len -= ret;
    4880             :                 /* we have more to read */
    4881       96107 :                 TEVENT_FD_READABLE(xconn->transport.fde);
    4882       96107 :                 return NT_STATUS_OK;
    4883             :         }
    4884             : 
    4885      303984 :         if (state->pktlen > 0) {
    4886      151992 :                 if (state->doing_receivefile && !is_smb2_recvfile_write(state)) {
    4887             :                         /*
    4888             :                          * Not a possible receivefile write.
    4889             :                          * Read the rest of the data.
    4890             :                          */
    4891           0 :                         state->doing_receivefile = false;
    4892             : 
    4893           0 :                         state->pktbuf = talloc_realloc(state->req,
    4894             :                                                        state->pktbuf,
    4895             :                                                        uint8_t,
    4896             :                                                        state->pktfull);
    4897           0 :                         if (state->pktbuf == NULL) {
    4898           0 :                                 return NT_STATUS_NO_MEMORY;
    4899             :                         }
    4900             : 
    4901           0 :                         state->vector.iov_base = (void *)(state->pktbuf +
    4902           0 :                                 state->pktlen);
    4903           0 :                         state->vector.iov_len = (state->pktfull -
    4904           0 :                                 state->pktlen);
    4905             : 
    4906           0 :                         state->pktlen = state->pktfull;
    4907           0 :                         goto again;
    4908             :                 }
    4909             : 
    4910             :                 /*
    4911             :                  * Either this is a receivefile write so we've
    4912             :                  * done a short read, or if not we have all the data.
    4913             :                  */
    4914      151992 :                 goto got_full;
    4915             :         }
    4916             : 
    4917             :         /*
    4918             :          * Now we analyze the NBT header
    4919             :          */
    4920      151992 :         if (state->hdr.nbt[0] != 0x00) {
    4921           0 :                 state->min_recv_size = 0;
    4922             :         }
    4923      151992 :         state->pktfull = smb2_len(state->hdr.nbt);
    4924      151992 :         if (state->pktfull == 0) {
    4925           0 :                 goto got_full;
    4926             :         }
    4927             : 
    4928      151992 :         if (state->min_recv_size != 0) {
    4929           0 :                 min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
    4930           0 :                 min_recvfile_size += state->min_recv_size;
    4931             :         }
    4932             : 
    4933      151992 :         if (state->pktfull > min_recvfile_size) {
    4934             :                 /*
    4935             :                  * Might be a receivefile write. Read the SMB2 HEADER +
    4936             :                  * SMB2_WRITE header first. Set 'doing_receivefile'
    4937             :                  * as we're *attempting* receivefile write. If this
    4938             :                  * turns out not to be a SMB2_WRITE request or otherwise
    4939             :                  * not suitable then we'll just read the rest of the data
    4940             :                  * the next time this function is called.
    4941             :                  */
    4942           0 :                 state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
    4943           0 :                 state->doing_receivefile = true;
    4944             :         } else {
    4945      151992 :                 state->pktlen = state->pktfull;
    4946             :         }
    4947             : 
    4948      151992 :         state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
    4949      151992 :         if (state->pktbuf == NULL) {
    4950           0 :                 return NT_STATUS_NO_MEMORY;
    4951             :         }
    4952             : 
    4953      151992 :         state->vector.iov_base = (void *)state->pktbuf;
    4954      151992 :         state->vector.iov_len = state->pktlen;
    4955             : 
    4956      151992 :         goto again;
    4957             : 
    4958      151992 : got_full:
    4959             : 
    4960      151992 :         if (state->hdr.nbt[0] != 0x00) {
    4961           0 :                 DEBUG(1,("ignore NBT[0x%02X] msg\n",
    4962             :                          state->hdr.nbt[0]));
    4963             : 
    4964           0 :                 req = state->req;
    4965           0 :                 ZERO_STRUCTP(state);
    4966           0 :                 state->req = req;
    4967           0 :                 state->min_recv_size = lp_min_receive_file_size();
    4968           0 :                 req = NULL;
    4969           0 :                 goto again;
    4970             :         }
    4971             : 
    4972      151992 :         req = state->req;
    4973      151992 :         state->req = NULL;
    4974             : 
    4975      151992 :         req->request_time = timeval_current();
    4976      151992 :         now = timeval_to_nttime(&req->request_time);
    4977             : 
    4978      151992 :         status = smbd_smb2_inbuf_parse_compound(xconn,
    4979             :                                                 now,
    4980             :                                                 state->pktbuf,
    4981             :                                                 state->pktlen,
    4982             :                                                 req,
    4983             :                                                 &req->in.vector,
    4984             :                                                 &req->in.vector_count);
    4985      151992 :         if (!NT_STATUS_IS_OK(status)) {
    4986           0 :                 return status;
    4987             :         }
    4988             : 
    4989      151992 :         if (state->doing_receivefile) {
    4990           0 :                 req->smb1req = talloc_zero(req, struct smb_request);
    4991           0 :                 if (req->smb1req == NULL) {
    4992           0 :                         return NT_STATUS_NO_MEMORY;
    4993             :                 }
    4994           0 :                 req->smb1req->unread_bytes = state->pktfull - state->pktlen;
    4995             :         }
    4996             : 
    4997      151992 :         ZERO_STRUCTP(state);
    4998             : 
    4999      151992 :         req->current_idx = 1;
    5000             : 
    5001      151992 :         DEBUG(10,("smbd_smb2_request idx[%d] of %d vectors\n",
    5002             :                  req->current_idx, req->in.vector_count));
    5003             : 
    5004      151992 :         status = smbd_smb2_request_validate(req);
    5005      151992 :         if (!NT_STATUS_IS_OK(status)) {
    5006           0 :                 return status;
    5007             :         }
    5008             : 
    5009      151992 :         status = smbd_smb2_request_setup_out(req);
    5010      151992 :         if (!NT_STATUS_IS_OK(status)) {
    5011           0 :                 return status;
    5012             :         }
    5013             : 
    5014      151992 :         status = smbd_smb2_request_dispatch(req);
    5015      149500 :         if (!NT_STATUS_IS_OK(status)) {
    5016           0 :                 return status;
    5017             :         }
    5018             : 
    5019      149500 :         sconn->num_requests++;
    5020             : 
    5021             :         /* The timeout_processing function isn't run nearly
    5022             :            often enough to implement 'max log size' without
    5023             :            overrunning the size of the file by many megabytes.
    5024             :            This is especially true if we are running at debug
    5025             :            level 10.  Checking every 50 SMB2s is a nice
    5026             :            tradeoff of performance vs log file size overrun. */
    5027             : 
    5028      151172 :         if ((sconn->num_requests % 50) == 0 &&
    5029        1672 :             need_to_check_log_size()) {
    5030         354 :                 change_to_root_user();
    5031         354 :                 check_log_size();
    5032             :         }
    5033             : 
    5034      149500 :         status = smbd_smb2_request_next_incoming(xconn);
    5035      149500 :         if (!NT_STATUS_IS_OK(status)) {
    5036           0 :                 return status;
    5037             :         }
    5038             : 
    5039      149500 :         return NT_STATUS_OK;
    5040             : }
    5041             : 
    5042      343086 : static void smbd_smb2_connection_handler(struct tevent_context *ev,
    5043             :                                          struct tevent_fd *fde,
    5044             :                                          uint16_t flags,
    5045             :                                          void *private_data)
    5046             : {
    5047      235868 :         struct smbXsrv_connection *xconn =
    5048      107218 :                 talloc_get_type_abort(private_data,
    5049             :                 struct smbXsrv_connection);
    5050             :         NTSTATUS status;
    5051             : 
    5052      343086 :         status = smbd_smb2_io_handler(xconn, flags);
    5053      340594 :         if (!NT_STATUS_IS_OK(status)) {
    5054        2500 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    5055          50 :                 return;
    5056             :         }
    5057             : }

Generated by: LCOV version 1.13