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

Generated by: LCOV version 1.14