LCOV - code coverage report
Current view: top level - source3/torture - test_oplock_cancel.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 45 72 62.5 %
Date: 2024-04-21 15:09:00 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Test cleanup behaviour
       4             :    Copyright (C) Volker Lendecke 2011
       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 "locking/proto.h"
      22             : #include "torture/proto.h"
      23             : #include "system/filesys.h"
      24             : #include "system/select.h"
      25             : #include "libsmb/libsmb.h"
      26             : #include "libcli/smb/smbXcli_base.h"
      27             : #include "libcli/security/security.h"
      28             : #include "lib/util/tevent_ntstatus.h"
      29             : 
      30             : struct create_cancel_state {
      31             :         uint8_t dummy;
      32             : };
      33             : 
      34             : static void create_cancel_done(struct tevent_req *subreq);
      35             : 
      36           2 : static struct tevent_req *create_cancel_send(
      37             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
      38             :         struct cli_state *cli, const char *fname)
      39             : {
      40           0 :         struct tevent_req *req, *subreq;
      41           0 :         struct create_cancel_state *state;
      42             : 
      43           2 :         req = tevent_req_create(mem_ctx, &state, struct create_cancel_state);
      44           2 :         if (req == NULL) {
      45           0 :                 return NULL;
      46             :         }
      47             : 
      48           2 :         subreq = cli_ntcreate_send(
      49             :                 mem_ctx, ev, cli, fname, 0, FILE_GENERIC_READ,
      50             :                 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE,
      51             :                 FILE_OPEN_IF, 0, SMB2_IMPERSONATION_IMPERSONATION, 0);
      52           2 :         if (tevent_req_nomem(subreq, req)) {
      53           0 :                 return tevent_req_post(req, ev);
      54             :         }
      55           2 :         if (!tevent_req_cancel(subreq)) {
      56           0 :                 tevent_req_oom(req);
      57           0 :                 return tevent_req_post(req, ev);
      58             :         }
      59           2 :         tevent_req_set_callback(subreq, create_cancel_done, req);
      60           2 :         return req;
      61             : }
      62             : 
      63           2 : static void create_cancel_done(struct tevent_req *subreq)
      64             : {
      65           2 :         struct tevent_req *req = tevent_req_callback_data(
      66             :                 subreq, struct tevent_req);
      67           0 :         NTSTATUS status;
      68             : 
      69           2 :         status = cli_ntcreate_recv(subreq, NULL, NULL);
      70           2 :         TALLOC_FREE(subreq);
      71           2 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) {
      72           0 :                 if (NT_STATUS_IS_OK(status)) {
      73           0 :                         status = NT_STATUS_UNSUCCESSFUL;
      74             :                 }
      75           0 :                 tevent_req_nterror(req, status);
      76           0 :                 return;
      77             :         }
      78           2 :         tevent_req_done(req);
      79             : }
      80             : 
      81           2 : static NTSTATUS create_cancel_recv(struct tevent_req *req)
      82             : {
      83           2 :         return tevent_req_simple_recv_ntstatus(req);
      84             : }
      85             : 
      86           2 : static NTSTATUS create_cancel(struct cli_state *cli, const char *fname)
      87             : {
      88           2 :         TALLOC_CTX *frame = talloc_stackframe();
      89           0 :         struct tevent_context *ev;
      90           0 :         struct tevent_req *req;
      91           2 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
      92             : 
      93           2 :         ev = samba_tevent_context_init(frame);
      94           2 :         if (ev == NULL) {
      95           0 :                 goto fail;
      96             :         }
      97           2 :         req = create_cancel_send(frame, ev, cli, fname);
      98           2 :         if (req == NULL) {
      99           0 :                 goto fail;
     100             :         }
     101           2 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     102           0 :                 goto fail;
     103             :         }
     104           2 :         status = create_cancel_recv(req);
     105           2 :  fail:
     106           2 :         TALLOC_FREE(frame);
     107           2 :         return status;
     108             : }
     109             : 
     110           2 : bool run_oplock_cancel(int dummy)
     111             : {
     112           0 :         struct cli_state *cli1, *cli2;
     113           2 :         const char *fname = "oplock-cancel";
     114           0 :         uint16_t fnum1;
     115           0 :         NTSTATUS status;
     116             :         /*
     117             :          * Currently this test seems to work only
     118             :          * with SMB2/3 and only against Samba.
     119             :          *
     120             :          * TODO: we should change our server
     121             :          * to ignore cancel for SMB2 Create
     122             :          * and behave like Windows.
     123             :          */
     124           2 :         int flags = CLI_FULL_CONNECTION_DISABLE_SMB1;
     125             : 
     126           2 :         if (!torture_open_connection_flags(&cli1, 0, flags)) {
     127           0 :                 return false;
     128             :         }
     129           2 :         cli1->use_oplocks = true;
     130             : 
     131           2 :         if (!torture_open_connection_flags(&cli2, 0, flags)) {
     132           0 :                 return false;
     133             :         }
     134           2 :         cli2->use_oplocks = true;
     135             : 
     136           2 :         status = cli_ntcreate(
     137             :                 cli1, fname, 0, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL,
     138             :                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0,
     139             :                 &fnum1, NULL);
     140           2 :         if (!NT_STATUS_IS_OK(status)) {
     141           0 :                 d_printf("cli_ntcreate failed: %s\n", nt_errstr(status));
     142           0 :                 return false;
     143             :         }
     144             : 
     145           2 :         status = create_cancel(cli2, fname);
     146           2 :         if (!NT_STATUS_IS_OK(status)) {
     147           0 :                 d_printf("create_cancel failed: %s\n", nt_errstr(status));
     148           0 :                 return false;
     149             :         }
     150             : 
     151           2 :         cli_close(cli1, fnum1);
     152             : 
     153           2 :         TALLOC_FREE(cli1);
     154             : 
     155             :         /*
     156             :          * Give cli1's smbd time to inform cli2's smbd
     157             :          */
     158           2 :         smb_msleep(5000);
     159             : 
     160           2 :         status = cli_unlink(cli2, fname,
     161             :                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
     162           2 :         if (!NT_STATUS_IS_OK(status)) {
     163           0 :                 d_printf("cli_unlink failed: %s\n", nt_errstr(status));
     164           0 :                 return false;
     165             :         }
     166             : 
     167           2 :         return true;
     168             : }

Generated by: LCOV version 1.14