Trigger (and fix) a bug in Samba3 making smbd an infinite data source
authorVolker Lendecke <vl@samba.org>
Mon, 3 Nov 2008 14:25:02 +0000 (15:25 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 4 Nov 2008 08:41:15 +0000 (09:41 +0100)
A deferred open directly followed by a ulogoffX makes smbd3 send an infinite
stream of ERRinvuid replies :-(

source3/smbd/process.c
source4/torture/raw/raw.c
source4/torture/raw/samba3misc.c

index 215ae20077aec8e2258dd70a365ba44459116ead..bd0acbc3c61465620ac9e8e0039c3bbc9412b05d 100644 (file)
@@ -1424,6 +1424,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
 
                if (!change_to_user(conn,session_tag)) {
                        reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
+                       remove_deferred_open_smb_message(req->mid);
                        return conn;
                }
 
index 0a7fc3ebfd8c3f5dfdc175973d86ba4bd58a732b..138f26310684384977b4e184745068a75e4a321f 100644 (file)
@@ -71,6 +71,7 @@ NTSTATUS torture_raw_init(void)
        torture_suite_add_simple_test(suite, "SAMBA3ROOTDIRFID",
                                      torture_samba3_rootdirfid);
        torture_suite_add_simple_test(suite, "SAMBA3CHECKFSP", torture_samba3_checkfsp);
+       torture_suite_add_simple_test(suite, "SAMBA3OPLOCKLOGOFF", torture_samba3_oplock_logoff);
        torture_suite_add_simple_test(suite, "SAMBA3BADPATH", torture_samba3_badpath);
        torture_suite_add_simple_test(suite, "SAMBA3CASEINSENSITIVE",
                                      torture_samba3_caseinsensitive);
index 27b4d42dd808937772dc28165314bcabbbbc896f..8cdccb3906f3f01f1ebbdc9d080850eed1e825cb 100644 (file)
@@ -889,3 +889,83 @@ bool torture_samba3_rootdirfid(struct torture_context *tctx)
        return ret;
 }
 
+bool torture_samba3_oplock_logoff(struct torture_context *tctx)
+{
+       struct smbcli_state *cli;
+       NTSTATUS status;
+       uint16_t fnum1;
+       union smb_open io;
+       const char *fname = "testfile";
+       bool ret = false;
+       struct smbcli_request *req;
+       struct smb_echo echo_req;
+
+       if (!torture_open_connection(&cli, tctx, 0)) {
+               ret = false;
+               goto done;
+       }
+
+       smbcli_unlink(cli->tree, fname);
+
+       ZERO_STRUCT(io);
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.access_mask =
+               SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.fname = "testfile";
+       status = smb_raw_open(cli->tree, tctx, &io);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("first smb_open failed: %s\n", nt_errstr(status));
+               ret = false;
+               goto done;
+       }
+       fnum1 = io.ntcreatex.out.file.fnum;
+
+       /*
+        * Create a conflicting open, causing the one-second delay
+        */
+
+       req = smb_raw_open_send(cli->tree, &io);
+       if (req == NULL) {
+               d_printf("smb_raw_open_send failed\n");
+               ret = false;
+               goto done;
+       }
+
+       /*
+        * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
+        * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
+        * as long as the client is still connected.
+        */
+
+       status = smb_raw_ulogoff(cli->session);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("ulogoff failed: %s\n", nt_errstr(status));
+               ret = false;
+               goto done;
+       }
+
+       echo_req.in.repeat_count = 1;
+       echo_req.in.size = 1;
+       echo_req.in.data = (uint8_t *)"";
+
+       status = smb_raw_echo(cli->session->transport, &echo_req);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("smb_raw_echo returned %s\n",
+                        nt_errstr(status));
+               ret = false;
+               goto done;
+       }
+
+       ret = true;
+ done:
+       return ret;
+}