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

Generated by: LCOV version 1.14