LCOV - code coverage report
Current view: top level - source3/smbd - smb2_server.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 1752 2157 81.2 %
Date: 2021-09-23 10:06:22 Functions: 73 79 92.4 %

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

Generated by: LCOV version 1.13