LCOV - code coverage report
Current view: top level - source3/smbd - smb2_server.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 1917 2436 78.7 %
Date: 2024-05-31 13:13:24 Functions: 75 79 94.9 %

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

Generated by: LCOV version 1.14