LCOV - code coverage report
Current view: top level - source4/smb_server/smb2 - fileio.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 227 334 68.0 %
Date: 2024-02-28 12:06:22 Functions: 16 18 88.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB2 implementation.
       3             :    
       4             :    Copyright (C) Stefan Metzmacher      2005
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libcli/smb2/smb2.h"
      22             : #include "libcli/smb2/smb2_calls.h"
      23             : #include "smb_server/smb_server.h"
      24             : #include "smb_server/smb2/smb2_server.h"
      25             : #include "ntvfs/ntvfs.h"
      26             : #include "libcli/raw/raw_proto.h"
      27             : #include "librpc/gen_ndr/ndr_security.h"
      28             : 
      29      209635 : static void smb2srv_create_send(struct ntvfs_request *ntvfs)
      30             : {
      31           0 :         struct smb2srv_request *req;
      32           0 :         union smb_open *io;
      33           0 :         DATA_BLOB blob;
      34             : 
      35      209635 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
      36             : 
      37             :         /* setup the blobs we should give in the reply */
      38      142574 :         if (io->smb2.out.maximal_access != 0) {
      39           0 :                 uint32_t data[2];
      40          12 :                 SIVAL(data, 0, 0);
      41          12 :                 SIVAL(data, 4, io->smb2.out.maximal_access);
      42          12 :                 SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs,
      43             :                                                    SMB2_CREATE_TAG_MXAC, 
      44             :                                                    data_blob_const(data, 8)));
      45             :         }
      46             :         
      47      142574 :         if (IVAL(io->smb2.out.on_disk_id, 0) != 0) {
      48          10 :                 SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs,
      49             :                                                    SMB2_CREATE_TAG_QFID,
      50             :                                                    data_blob_const(io->smb2.out.on_disk_id, 32)));
      51             :         }
      52             : 
      53      142574 :         SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs));
      54      142574 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length));
      55             : 
      56      142574 :         SCVAL(req->out.body, 0x02,   io->smb2.out.oplock_level);
      57      142574 :         SCVAL(req->out.body, 0x03,   io->smb2.out.reserved);
      58      142574 :         SIVAL(req->out.body, 0x04,   io->smb2.out.create_action);
      59      142574 :         SBVAL(req->out.body, 0x08,   io->smb2.out.create_time);
      60      142574 :         SBVAL(req->out.body, 0x10,   io->smb2.out.access_time);
      61      142574 :         SBVAL(req->out.body, 0x18,   io->smb2.out.write_time);
      62      142574 :         SBVAL(req->out.body, 0x20,   io->smb2.out.change_time);
      63      142574 :         SBVAL(req->out.body, 0x28,   io->smb2.out.alloc_size);
      64      142574 :         SBVAL(req->out.body, 0x30,   io->smb2.out.size);
      65      142574 :         SIVAL(req->out.body, 0x38,   io->smb2.out.file_attr);
      66      142574 :         SIVAL(req->out.body, 0x3C,   io->smb2.out.reserved2);
      67      142574 :         smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs);
      68      142574 :         SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, blob));
      69             : 
      70             :         /* also setup the chained file handle */
      71      142574 :         req->chained_file_handle = req->_chained_file_handle;
      72      142574 :         smb2srv_push_handle(req->chained_file_handle, 0, io->smb2.out.file.ntvfs);
      73             : 
      74      142574 :         smb2srv_send_reply(req);
      75             : }
      76             : 
      77      209639 : void smb2srv_create_recv(struct smb2srv_request *req)
      78             : {
      79           0 :         union smb_open *io;
      80           0 :         DATA_BLOB blob;
      81           0 :         int i;
      82             : 
      83      209639 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x38, true);
      84      209639 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_open);
      85      209639 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_create_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
      86             : 
      87      209639 :         ZERO_STRUCT(io->smb2.in);
      88      209639 :         io->smb2.level                       = RAW_OPEN_SMB2;
      89      209639 :         io->smb2.in.security_flags   = CVAL(req->in.body, 0x02);
      90      209639 :         io->smb2.in.oplock_level     = CVAL(req->in.body, 0x03);
      91      209639 :         io->smb2.in.impersonation_level      = IVAL(req->in.body, 0x04);
      92      209639 :         io->smb2.in.create_flags     = BVAL(req->in.body, 0x08);
      93      209639 :         io->smb2.in.reserved         = BVAL(req->in.body, 0x10);
      94      209639 :         io->smb2.in.desired_access   = IVAL(req->in.body, 0x18);
      95      209639 :         io->smb2.in.file_attributes  = IVAL(req->in.body, 0x1C);
      96      209639 :         io->smb2.in.share_access     = IVAL(req->in.body, 0x20);
      97      209639 :         io->smb2.in.create_disposition       = IVAL(req->in.body, 0x24);
      98      209639 :         io->smb2.in.create_options   = IVAL(req->in.body, 0x28);
      99      209639 :         SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
     100      209639 :         SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
     101      209639 :         SMB2SRV_CHECK(smb2_create_blob_parse(io, blob, &io->smb2.in.blobs));
     102             : 
     103             :         /* interpret the parsed tags that a server needs to respond to */
     104      209741 :         for (i=0;i<io->smb2.in.blobs.num_blobs;i++) {
     105         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_EXTA) == 0) {
     106           6 :                         SMB2SRV_CHECK(ea_pull_list_chained(&io->smb2.in.blobs.blobs[i].data, io, 
     107             :                                                            &io->smb2.in.eas.num_eas,
     108             :                                                            &io->smb2.in.eas.eas));
     109             :                 }
     110         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_SECD) == 0) {
     111           0 :                         enum ndr_err_code ndr_err;
     112          16 :                         io->smb2.in.sec_desc = talloc(io, struct security_descriptor);
     113          16 :                         if (io->smb2.in.sec_desc == NULL) {
     114           0 :                                 smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
     115           0 :                                 return;
     116             :                         }
     117          16 :                         ndr_err = ndr_pull_struct_blob(&io->smb2.in.blobs.blobs[i].data, io, 
     118          16 :                                                        io->smb2.in.sec_desc,
     119             :                                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     120          16 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     121           0 :                                 smb2srv_send_error(req,  ndr_map_error2ntstatus(ndr_err));
     122           0 :                                 return;
     123             :                         }
     124             :                 }
     125         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
     126          13 :                         io->smb2.in.durable_open = true;
     127             :                 }
     128         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNC) == 0) {
     129           0 :                         if (io->smb2.in.blobs.blobs[i].data.length != 16) {
     130           0 :                                 smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
     131           0 :                                 return;                         
     132             :                         }
     133           0 :                         io->smb2.in.durable_handle = talloc(io, struct smb2_handle);
     134           0 :                         if (io->smb2.in.durable_handle == NULL) {
     135           0 :                                 smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
     136           0 :                                 return;
     137             :                         }
     138           0 :                         smb2_pull_handle(io->smb2.in.blobs.blobs[i].data.data, io->smb2.in.durable_handle);
     139             :                 }
     140         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_ALSI) == 0) {
     141          38 :                         if (io->smb2.in.blobs.blobs[i].data.length != 8) {
     142           0 :                                 smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
     143           0 :                                 return;                         
     144             :                         }
     145          38 :                         io->smb2.in.alloc_size = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
     146             :                 }
     147         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
     148          13 :                         io->smb2.in.query_maximal_access = true;
     149             :                 }
     150         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
     151           1 :                         if (io->smb2.in.blobs.blobs[i].data.length != 8) {
     152           0 :                                 smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
     153           0 :                                 return;                         
     154             :                         }
     155           1 :                         io->smb2.in.timewarp = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);                     
     156             :                 }
     157         106 :                 if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
     158          10 :                         io->smb2.in.query_on_disk_id = true;
     159             :                 }
     160             :         }
     161             :                 
     162             :         /* the VFS backend does not yet handle NULL filenames */
     163      209635 :         if (io->smb2.in.fname == NULL) {
     164           0 :                 io->smb2.in.fname = "";
     165             :         }
     166             : 
     167      209635 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
     168             : }
     169             : 
     170      142403 : static void smb2srv_close_send(struct ntvfs_request *ntvfs)
     171             : {
     172           0 :         struct smb2srv_request *req;
     173           0 :         union smb_close *io;
     174             : 
     175      142403 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_close);
     176      142403 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x3C, false, 0));
     177             : 
     178      142403 :         SSVAL(req->out.body, 0x02,   io->smb2.out.flags);
     179      142403 :         SIVAL(req->out.body, 0x04,   io->smb2.out._pad);
     180      142403 :         SBVAL(req->out.body, 0x08,   io->smb2.out.create_time);
     181      142403 :         SBVAL(req->out.body, 0x10,   io->smb2.out.access_time);
     182      142403 :         SBVAL(req->out.body, 0x18,   io->smb2.out.write_time);
     183      142403 :         SBVAL(req->out.body, 0x20,   io->smb2.out.change_time);
     184      142403 :         SBVAL(req->out.body, 0x28,   io->smb2.out.alloc_size);
     185      142403 :         SBVAL(req->out.body, 0x30,   io->smb2.out.size);
     186      142403 :         SIVAL(req->out.body, 0x38,   io->smb2.out.file_attr);
     187             : 
     188             :         /* also destroy the chained file handle */
     189      142403 :         req->chained_file_handle = NULL;
     190      142403 :         memset(req->_chained_file_handle, 0, sizeof(req->_chained_file_handle));
     191             : 
     192      142403 :         smb2srv_send_reply(req);
     193             : }
     194             : 
     195      142898 : void smb2srv_close_recv(struct smb2srv_request *req)
     196             : {
     197           0 :         union smb_close *io;
     198             : 
     199      142898 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x18, false);
     200      142898 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_close);
     201      142898 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_close_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     202             : 
     203      142898 :         io->smb2.level                       = RAW_CLOSE_SMB2;
     204      142898 :         io->smb2.in.flags            = SVAL(req->in.body, 0x02);
     205      142898 :         io->smb2.in._pad             = IVAL(req->in.body, 0x04);
     206      142898 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x08);
     207             : 
     208      142898 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     209      142403 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
     210             : }
     211             : 
     212           3 : static void smb2srv_flush_send(struct ntvfs_request *ntvfs)
     213             : {
     214           0 :         struct smb2srv_request *req;
     215           0 :         union smb_flush *io;
     216             : 
     217           3 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_flush);
     218           3 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, false, 0));
     219             : 
     220           3 :         SSVAL(req->out.body, 0x02,   io->smb2.out.reserved);
     221             : 
     222           3 :         smb2srv_send_reply(req);
     223             : }
     224             : 
     225           3 : void smb2srv_flush_recv(struct smb2srv_request *req)
     226             : {
     227           0 :         union smb_flush *io;
     228             : 
     229           3 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x18, false);
     230           3 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_flush);
     231           3 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_flush_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     232             : 
     233           3 :         io->smb2.level                       = RAW_FLUSH_SMB2;
     234           3 :         io->smb2.in.reserved1                = SVAL(req->in.body, 0x02);
     235           3 :         io->smb2.in.reserved2                = IVAL(req->in.body, 0x04);
     236           3 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x08);
     237             : 
     238           3 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     239           3 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io));
     240             : }
     241             : 
     242        1612 : static void smb2srv_read_send(struct ntvfs_request *ntvfs)
     243             : {
     244           0 :         struct smb2srv_request *req;
     245           0 :         union smb_read *io;
     246             : 
     247        1612 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_read);
     248        1550 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, true, io->smb2.out.data.length));
     249             : 
     250             :         /* TODO: avoid the memcpy */
     251        1550 :         SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, io->smb2.out.data));
     252        1550 :         SIVAL(req->out.body, 0x08,   io->smb2.out.remaining);
     253        1550 :         SIVAL(req->out.body, 0x0C,   io->smb2.out.reserved);
     254             : 
     255        1550 :         smb2srv_send_reply(req);
     256             : }
     257             : 
     258        1612 : void smb2srv_read_recv(struct smb2srv_request *req)
     259             : {
     260           0 :         union smb_read *io;
     261             : 
     262        1612 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x30, true);
     263             : 
     264             :         /* MS-SMB2 2.2.19 read must have a single byte of zero */
     265        1612 :         if (req->in.body_size - req->in.body_fixed < 1) {
     266           0 :                 smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
     267           0 :                 return;
     268             :         }
     269        1612 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_read);
     270        1612 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     271             : 
     272        1612 :         io->smb2.level                       = RAW_READ_SMB2;
     273        1612 :         io->smb2.in._pad             = SVAL(req->in.body, 0x02);
     274        1612 :         io->smb2.in.length           = IVAL(req->in.body, 0x04);
     275        1612 :         io->smb2.in.offset           = BVAL(req->in.body, 0x08);
     276        1612 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x10);
     277        1612 :         io->smb2.in.min_count                = IVAL(req->in.body, 0x20);
     278        1612 :         io->smb2.in.channel          = IVAL(req->in.body, 0x24);
     279        1612 :         io->smb2.in.remaining                = IVAL(req->in.body, 0x28);
     280        1612 :         io->smb2.in.channel_offset      = SVAL(req->in.body, 0x2C);
     281        1612 :         io->smb2.in.channel_length      = SVAL(req->in.body, 0x2E);
     282             : 
     283        1612 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     284             : 
     285             :         /* preallocate the buffer for the backends */
     286        1612 :         io->smb2.out.data = data_blob_talloc(io, NULL, io->smb2.in.length);
     287        1612 :         if (io->smb2.out.data.length != io->smb2.in.length) {
     288           0 :                 SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
     289             :         }
     290             : 
     291        1612 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
     292             : }
     293             : 
     294        1814 : static void smb2srv_write_send(struct ntvfs_request *ntvfs)
     295             : {
     296           0 :         struct smb2srv_request *req;
     297           0 :         union smb_write *io;
     298             : 
     299        1814 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_write);
     300        1770 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, true, 0));
     301             : 
     302        1770 :         SSVAL(req->out.body, 0x02,   io->smb2.out._pad);
     303        1770 :         SIVAL(req->out.body, 0x04,   io->smb2.out.nwritten);
     304        1770 :         SBVAL(req->out.body, 0x08,   io->smb2.out.unknown1);
     305             : 
     306        1770 :         smb2srv_send_reply(req);
     307             : }
     308             : 
     309        1814 : void smb2srv_write_recv(struct smb2srv_request *req)
     310             : {
     311           0 :         union smb_write *io;
     312             : 
     313        1814 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x30, true);
     314        1814 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_write);
     315        1814 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     316             : 
     317             :         /* TODO: avoid the memcpy */
     318        1814 :         io->smb2.level                       = RAW_WRITE_SMB2;
     319        1814 :         SMB2SRV_CHECK(smb2_pull_o16s32_blob(&req->in, io, req->in.body+0x02, &io->smb2.in.data));
     320        1814 :         io->smb2.in.offset           = BVAL(req->in.body, 0x08);
     321        1814 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x10);
     322        1814 :         io->smb2.in.unknown1         = BVAL(req->in.body, 0x20);
     323        1814 :         io->smb2.in.unknown2         = BVAL(req->in.body, 0x28);
     324             : 
     325        1814 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     326        1814 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
     327             : }
     328             : 
     329         381 : static void smb2srv_lock_send(struct ntvfs_request *ntvfs)
     330             : {
     331           0 :         struct smb2srv_request *req;
     332           0 :         union smb_lock *io;
     333             : 
     334         381 :         SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock);
     335         259 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, false, 0));
     336             : 
     337         259 :         SSVAL(req->out.body, 0x02,   io->smb2.out.reserved);
     338             : 
     339         259 :         smb2srv_send_reply(req);
     340             : }
     341             : 
     342         384 : void smb2srv_lock_recv(struct smb2srv_request *req)
     343             : {
     344           0 :         union smb_lock *io;
     345           0 :         int i;
     346             : 
     347         384 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x30, false);
     348         382 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_lock);
     349         382 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_lock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     350             : 
     351         382 :         io->smb2.level                       = RAW_LOCK_SMB2;
     352         382 :         io->smb2.in.lock_count               = SVAL(req->in.body, 0x02);
     353         382 :         io->smb2.in.lock_sequence    = IVAL(req->in.body, 0x04);
     354         382 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x08);
     355         382 :         if (req->in.body_size < 24 + 24*(uint64_t)io->smb2.in.lock_count) {
     356           0 :                 DEBUG(0,("%s: lock buffer too small\n", __location__));
     357           0 :                 smb2srv_send_error(req,  NT_STATUS_FOOBAR);
     358           0 :                 return;
     359             :         }
     360         382 :         io->smb2.in.locks = talloc_array(io, struct smb2_lock_element, 
     361             :                                          io->smb2.in.lock_count);
     362         382 :         if (io->smb2.in.locks == NULL) {
     363           0 :                 smb2srv_send_error(req, NT_STATUS_NO_MEMORY);
     364           0 :                 return;
     365             :         }
     366             : 
     367         772 :         for (i=0;i<io->smb2.in.lock_count;i++) {
     368         390 :                 io->smb2.in.locks[i].offset  = BVAL(req->in.body, 24 + i*24);
     369         390 :                 io->smb2.in.locks[i].length  = BVAL(req->in.body, 32 + i*24);
     370         390 :                 io->smb2.in.locks[i].flags   = IVAL(req->in.body, 40 + i*24);
     371         390 :                 io->smb2.in.locks[i].reserved        = IVAL(req->in.body, 44 + i*24);
     372             :         }
     373             : 
     374         382 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     375         381 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, io));
     376             : }
     377             : 
     378       49082 : static void smb2srv_ioctl_send(struct ntvfs_request *ntvfs)
     379             : {
     380           0 :         struct smb2srv_request *req;
     381           0 :         union smb_ioctl *io;
     382             : 
     383       49082 :         SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_ioctl);
     384       47488 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x30, true, 0));
     385             : 
     386       47488 :         SSVAL(req->out.body, 0x02,   io->smb2.out.reserved);
     387       47488 :         SIVAL(req->out.body, 0x04,   io->smb2.out.function);
     388       47488 :         if (io->smb2.level == RAW_IOCTL_SMB2_NO_HANDLE) {
     389           0 :                 struct smb2_handle h;
     390           0 :                 h.data[0] = UINT64_MAX;
     391           0 :                 h.data[1] = UINT64_MAX;
     392           0 :                 smb2_push_handle(req->out.body + 0x08, &h);
     393             :         } else {
     394       47488 :                 smb2srv_push_handle(req->out.body, 0x08,io->smb2.in.file.ntvfs);
     395             :         }
     396       47488 :         SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x18, io->smb2.out.in));
     397       47488 :         SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x20, io->smb2.out.out));
     398       47488 :         SIVAL(req->out.body, 0x28,   io->smb2.out.flags);
     399       47488 :         SIVAL(req->out.body, 0x2C,   io->smb2.out.reserved2);
     400             : 
     401       47488 :         smb2srv_send_reply(req);
     402             : }
     403             : 
     404       49082 : void smb2srv_ioctl_recv(struct smb2srv_request *req)
     405             : {
     406           0 :         union smb_ioctl *io;
     407           0 :         struct smb2_handle h;
     408             : 
     409       49082 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x38, true);
     410       49082 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_ioctl);
     411       49082 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     412             : 
     413             :         /* TODO: avoid the memcpy */
     414       49082 :         io->smb2.in.reserved         = SVAL(req->in.body, 0x02);
     415       49082 :         io->smb2.in.function         = IVAL(req->in.body, 0x04);
     416             :         /* file handle ... */
     417       49082 :         SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x18, &io->smb2.in.out));
     418       49082 :         io->smb2.in.max_input_response       = IVAL(req->in.body, 0x20);
     419       49082 :         SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x24, &io->smb2.in.in));
     420       49082 :         io->smb2.in.max_output_response      = IVAL(req->in.body, 0x2C);
     421       49082 :         io->smb2.in.flags            = IVAL(req->in.body, 0x30);
     422       49082 :         io->smb2.in.reserved2                = IVAL(req->in.body, 0x34);
     423             : 
     424       49082 :         smb2_pull_handle(req->in.body + 0x08, &h);
     425       49082 :         if (h.data[0] == UINT64_MAX && h.data[1] == UINT64_MAX) {
     426        1565 :                 io->smb2.level               = RAW_IOCTL_SMB2_NO_HANDLE;
     427             :         } else {
     428       47517 :                 io->smb2.level               = RAW_IOCTL_SMB2;
     429       47517 :                 io->smb2.in.file.ntvfs       = smb2srv_pull_handle(req, req->in.body, 0x08);
     430       47517 :                 SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     431             :         }
     432             : 
     433       49082 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
     434             : }
     435             : 
     436           0 : static void smb2srv_notify_send(struct ntvfs_request *ntvfs)
     437             : {
     438           0 :         struct smb2srv_request *req;
     439           0 :         union smb_notify *io;
     440           0 :         size_t size = 0;
     441           0 :         int i;
     442           0 :         uint8_t *p;
     443           0 :         DATA_BLOB blob = data_blob(NULL, 0);
     444             : 
     445           0 :         SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_notify);
     446           0 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, 0));
     447             : 
     448             : #define MAX_BYTES_PER_CHAR 3
     449             :         
     450             :         /* work out how big the reply buffer could be */
     451           0 :         for (i=0;i<io->smb2.out.num_changes;i++) {
     452           0 :                 size += 12 + 3 + (1+strlen(io->smb2.out.changes[i].name.s)) * MAX_BYTES_PER_CHAR;
     453             :         }
     454             : 
     455           0 :         blob = data_blob_talloc(req, NULL, size);
     456           0 :         if (size > 0 && !blob.data) {
     457           0 :                 SMB2SRV_CHECK(NT_STATUS_NO_MEMORY);
     458             :         }
     459             : 
     460           0 :         p = blob.data;
     461             : 
     462             :         /* construct the changes buffer */
     463           0 :         for (i=0;i<io->smb2.out.num_changes;i++) {
     464           0 :                 uint32_t ofs;
     465           0 :                 ssize_t len;
     466             : 
     467           0 :                 SIVAL(p, 4, io->smb2.out.changes[i].action);
     468           0 :                 len = push_string(p + 12, io->smb2.out.changes[i].name.s, 
     469           0 :                                   blob.length - (p+12 - blob.data), STR_UNICODE);
     470           0 :                 SIVAL(p, 8, len);
     471             : 
     472           0 :                 ofs = len + 12;
     473             : 
     474           0 :                 if (ofs & 3) {
     475           0 :                         int pad = 4 - (ofs & 3);
     476           0 :                         memset(p+ofs, 0, pad);
     477           0 :                         ofs += pad;
     478             :                 }
     479             : 
     480           0 :                 if (i == io->smb2.out.num_changes-1) {
     481           0 :                         SIVAL(p, 0, 0);
     482             :                 } else {
     483           0 :                         SIVAL(p, 0, ofs);
     484             :                 }
     485             : 
     486           0 :                 p += ofs;
     487             :         }
     488             : 
     489           0 :         blob.length = p - blob.data;
     490             : 
     491           0 :         SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, blob));
     492             : 
     493           0 :         smb2srv_send_reply(req);
     494             : }
     495             : 
     496           0 : void smb2srv_notify_recv(struct smb2srv_request *req)
     497             : {
     498           0 :         union smb_notify *io;
     499             : 
     500           0 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x20, false);
     501           0 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_notify);
     502           0 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_notify_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     503             : 
     504           0 :         io->smb2.level                       = RAW_NOTIFY_SMB2;
     505           0 :         io->smb2.in.recursive                = SVAL(req->in.body, 0x02);
     506           0 :         io->smb2.in.buffer_size              = IVAL(req->in.body, 0x04);
     507           0 :         io->smb2.in.file.ntvfs               = smb2srv_pull_handle(req, req->in.body, 0x08);
     508           0 :         io->smb2.in.completion_filter        = IVAL(req->in.body, 0x18);
     509           0 :         io->smb2.in.unknown          = BVAL(req->in.body, 0x1C);
     510             : 
     511           0 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs);
     512           0 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_notify(req->ntvfs, io));
     513             : }
     514             : 
     515          42 : static void smb2srv_break_send(struct ntvfs_request *ntvfs)
     516             : {
     517           0 :         struct smb2srv_request *req;
     518           0 :         union smb_lock *io;
     519             : 
     520          42 :         SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock);
     521          42 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x18, false, 0));
     522             : 
     523          42 :         SCVAL(req->out.body, 0x02,   io->smb2_break.out.oplock_level);
     524          42 :         SCVAL(req->out.body, 0x03,   io->smb2_break.out.reserved);
     525          42 :         SIVAL(req->out.body, 0x04,   io->smb2_break.out.reserved2);
     526          42 :         smb2srv_push_handle(req->out.body, 0x08,io->smb2_break.out.file.ntvfs);
     527             : 
     528          42 :         smb2srv_send_reply(req);
     529             : }
     530             : 
     531          42 : void smb2srv_break_recv(struct smb2srv_request *req)
     532             : {
     533           0 :         union smb_lock *io;
     534             : 
     535          42 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x18, false);
     536          42 :         SMB2SRV_TALLOC_IO_PTR(io, union smb_lock);
     537          42 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_break_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     538             : 
     539          42 :         io->smb2_break.level         = RAW_LOCK_SMB2_BREAK;
     540          42 :         io->smb2_break.in.oplock_level       = CVAL(req->in.body, 0x02);
     541          42 :         io->smb2_break.in.reserved   = CVAL(req->in.body, 0x03);
     542          42 :         io->smb2_break.in.reserved2  = IVAL(req->in.body, 0x04);
     543          42 :         io->smb2_break.in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08);
     544             : 
     545          42 :         SMB2SRV_CHECK_FILE_HANDLE(io->smb2_break.in.file.ntvfs);
     546          42 :         SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, io));
     547             : }

Generated by: LCOV version 1.14