1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/python/samba/tests/libsmb-basic.py
Volker Lendecke 23deb79a28 tests: Add reproducer for bug 15487
Show that smbd crashes if asked to return full information on close of a
stream handle with delete on close disposition set.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
2023-10-10 08:19:29 +00:00

269 lines
8.3 KiB
Python

# Unix SMB/CIFS implementation.
# Copyright Volker Lendecke <vl@samba.org> 2012
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Tests for samba.samba3.libsmb."""
from samba.samba3 import libsmb_samba_internal as libsmb
from samba.dcerpc import security
from samba import NTSTATUSError,ntstatus
from samba.ntstatus import NT_STATUS_DELETE_PENDING
from samba.credentials import SMB_ENCRYPTION_REQUIRED
import samba.tests.libsmb
import threading
import sys
import random
class LibsmbTestCase(samba.tests.libsmb.LibsmbTests):
class OpenClose(threading.Thread):
def __init__(self, conn, filename, num_ops):
threading.Thread.__init__(self)
self.conn = conn
self.filename = filename
self.num_ops = num_ops
self.exc = False
def run(self):
c = self.conn
try:
for i in range(self.num_ops):
f = c.create(self.filename, CreateDisposition=3,
DesiredAccess=security.SEC_STD_DELETE)
c.delete_on_close(f, True)
c.close(f)
except Exception:
self.exc = sys.exc_info()
def test_OpenClose(self):
c = libsmb.Conn(
self.server_ip,
"tmp",
self.lp,
self.creds,
multi_threaded=True,
force_smb1=True)
mythreads = []
for i in range(3):
t = LibsmbTestCase.OpenClose(c, "test" + str(i), 10)
mythreads.append(t)
for t in mythreads:
t.start()
for t in mythreads:
t.join()
if t.exc:
raise t.exc[0](t.exc[1])
def test_SMB3EncryptionRequired(self):
test_dir = 'testing_%d' % random.randint(0, 0xFFFF)
self.creds.set_smb_encryption(SMB_ENCRYPTION_REQUIRED)
c = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
c.mkdir(test_dir)
c.rmdir(test_dir)
def test_SMB1EncryptionRequired(self):
test_dir = 'testing_%d' % random.randint(0, 0xFFFF)
self.creds.set_smb_encryption(SMB_ENCRYPTION_REQUIRED)
c = libsmb.Conn(
self.server_ip,
"tmp",
self.lp,
self.creds,
force_smb1=True)
c.mkdir(test_dir)
c.rmdir(test_dir)
def test_RenameDstDelOnClose(self):
dstdir = "\\dst-subdir"
c1 = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
c2 = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
try:
c1.deltree(dstdir)
except:
pass
c1.mkdir(dstdir)
dnum = c1.create(dstdir, DesiredAccess=security.SEC_STD_DELETE)
c1.delete_on_close(dnum,1)
c2.savefile("\\src.txt", b"Content")
with self.assertRaises(NTSTATUSError) as cm:
c2.rename("\\src.txt", dstdir + "\\dst.txt")
if (cm.exception.args[0] != NT_STATUS_DELETE_PENDING):
raise AssertionError("Rename must fail with DELETE_PENDING")
c1.delete_on_close(dnum,0)
c1.close(dnum)
try:
c1.deltree(dstdir)
c1.unlink("\\src.txt")
except:
pass
def test_libsmb_CreateContexts(self):
c = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
cc_in = [(libsmb.SMB2_CREATE_TAG_MXAC, b'')]
fnum,cr,cc = c.create_ex("",CreateContexts=cc_in)
self.assertEqual(
cr['file_attributes'] & libsmb.FILE_ATTRIBUTE_DIRECTORY,
libsmb.FILE_ATTRIBUTE_DIRECTORY)
self.assertEqual(cc[0][0],libsmb.SMB2_CREATE_TAG_MXAC)
self.assertEqual(len(cc[0][1]),8)
c.close(fnum)
def test_libsmb_TortureCaseSensitivity(self):
testdir = "test_libsmb_torture_case_sensitivity"
filename = "file"
filepath = testdir + "/" + filename
c = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
try:
c.deltree(testdir)
except:
pass
c.mkdir(testdir)
try:
# Now check for all possible upper-/lowercase combinations:
# - testdir/file
# - TESTDIR/file
# - testdir/FILE
# - TESTDIR/FILE
dircases = [testdir, testdir, testdir.upper(), testdir.upper()]
filecases = [filename, filename.upper(), filename, filename.upper()]
tcases = [{'dir':dir, 'file':file} for dir,file in zip(dircases,filecases)]
for tcase in tcases:
testpath = tcase['dir'] + "/" + tcase['file']
# Create the testfile
h = c.create(filepath,
DesiredAccess=security.SEC_FILE_ALL,
CreateDisposition=libsmb.FILE_OPEN_IF)
c.close(h)
# Open
c.loadfile(testpath)
# Search
ls = [f['name'] for f in c.list(tcase['dir'], mask=tcase['file'])]
self.assertIn(filename, ls, msg='When searching for "%s" not found in "%s"' % (tcase['file'], tcase['dir']))
# Rename
c.rename(testpath, tcase['dir'] + "/tmp")
c.rename(tcase['dir'] + "/TMP", filepath)
c.loadfile(testpath)
# Delete
c.unlink(testpath)
finally:
c.deltree(testdir)
def test_libsmb_TortureDirCaseSensitive(self):
c = libsmb.Conn(self.server_ip, "lowercase", self.lp, self.creds)
c.mkdir("subdir")
c.mkdir("subdir/b")
ret = c.chkpath("SubDir/b")
c.rmdir("subdir/b")
c.rmdir("subdir")
self.assertTrue(ret)
def test_libsmb_shadow_depot(self):
c = libsmb.Conn(self.server_ip, "shadow_depot", self.lp, self.creds)
try:
fnum=c.create("x:y",CreateDisposition=libsmb.FILE_CREATE)
c.close(fnum)
except:
self.fail()
finally:
# "c" might have crashed, get a new connection
c1 = libsmb.Conn(self.server_ip, "shadow_depot", self.lp, self.creds)
c1.unlink("x")
c1 = None
def test_gencache_pollution_bz15481(self):
c = libsmb.Conn(self.server_ip, "tmp", self.lp, self.creds)
fh = c.create("file",
DesiredAccess=security.SEC_STD_DELETE,
CreateDisposition=libsmb.FILE_CREATE)
# prime the gencache File->file
fh_upper = c.create("File",
DesiredAccess=security.SEC_FILE_READ_ATTRIBUTE,
CreateDisposition=libsmb.FILE_OPEN)
c.close(fh_upper)
c.delete_on_close(fh, 1)
c.close(fh)
fh = c.create("File",
DesiredAccess=security.SEC_STD_DELETE,
CreateDisposition=libsmb.FILE_CREATE)
directory = c.list("\\", "File")
c.delete_on_close(fh, 1)
c.close(fh)
# Without the bugfix for 15481 we get 'file' not 'File'
self.assertEqual(directory[0]['name'], 'File')
def test_stream_close_with_full_information(self):
c = libsmb.Conn(self.server_ip, "streams_xattr", self.lp, self.creds)
try:
c.deltree("teststreams")
except:
pass
c.mkdir("teststreams")
fh = c.create("teststreams\\stream_full_close_info.txt:Stream",
DesiredAccess=security.SEC_STD_DELETE,
CreateDisposition=libsmb.FILE_CREATE)
c.delete_on_close(fh, 1)
try:
c.close(fh, libsmb.SMB2_CLOSE_FLAGS_FULL_INFORMATION)
except:
self.fail()
c.deltree("teststreams")
if __name__ == "__main__":
import unittest
unittest.main()