mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-local
(This used to be commit cd10b38176
)
This commit is contained in:
commit
437ca06107
@ -271,7 +271,7 @@ AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_ALLOW_UNDEF_FLAG],
|
||||
LD_SHLIB_ALLOW_UNDEF_FLAG="-undefined dynamic_lookup"
|
||||
;;
|
||||
*aix*)
|
||||
LD_SHLIB_ALLOW_UNDEF_FLAG="--Wl,-bnoentry"
|
||||
LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,-bnoentry"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -1354,7 +1354,7 @@ union smb_open {
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
/* SMBNTCreateX interface */
|
||||
/* SMBNTCreateX, nttrans and generic interface */
|
||||
struct {
|
||||
enum smb_open_level level;
|
||||
struct {
|
||||
@ -1377,6 +1377,9 @@ union smb_open {
|
||||
NTTRANS varient of the call */
|
||||
struct security_descriptor *sec_desc;
|
||||
struct smb_ea_list *ea_list;
|
||||
|
||||
/* some optional parameters from the SMB2 varient */
|
||||
bool query_maximal_access;
|
||||
} in;
|
||||
struct {
|
||||
union smb_handle file;
|
||||
@ -1392,6 +1395,10 @@ union smb_open {
|
||||
uint16_t file_type;
|
||||
uint16_t ipc_state;
|
||||
uint8_t is_directory;
|
||||
|
||||
/* optional return values matching SMB2 tagged
|
||||
values in the call */
|
||||
uint32_t maximal_access;
|
||||
} out;
|
||||
} ntcreatex, nttrans, generic;
|
||||
|
||||
|
@ -387,12 +387,13 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct
|
||||
/* pull out the parsed blobs */
|
||||
for (i=0;i<io->out.blobs.num_blobs;i++) {
|
||||
if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
|
||||
/* why 8 bytes not 4?? */
|
||||
/* TODO: this also contains a status field in
|
||||
first 4 bytes */
|
||||
if (io->out.blobs.blobs[i].data.length != 8) {
|
||||
smb2_request_destroy(req);
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 0);
|
||||
io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 4);
|
||||
}
|
||||
if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
|
||||
if (io->out.blobs.blobs[i].data.length != 32) {
|
||||
|
@ -233,6 +233,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
|
||||
io->smb2.out.size = io2->generic.out.size;
|
||||
io->smb2.out.file_attr = io2->generic.out.attrib;
|
||||
io->smb2.out.reserved2 = 0;
|
||||
io->smb2.out.maximal_access = io2->generic.out.maximal_access;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -522,6 +523,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
|
||||
io2->generic.in.fname = io->smb2.in.fname;
|
||||
io2->generic.in.sec_desc = io->smb2.in.sec_desc;
|
||||
io2->generic.in.ea_list = &io->smb2.in.eas;
|
||||
io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access;
|
||||
|
||||
/* we don't support timewarp yet */
|
||||
if (io->smb2.in.timewarp != 0) {
|
||||
|
@ -464,7 +464,11 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
/* on SMB, this bit is always granted, even if not
|
||||
asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -496,7 +500,9 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
|
||||
|
||||
/* expand the generic access bits to file specific bits */
|
||||
*access_mask = pvfs_translate_mask(*access_mask);
|
||||
*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
status = pvfs_acl_load(pvfs, name, -1, acl);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
||||
@ -518,8 +524,11 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
|
||||
/* check the acl against the required access mask */
|
||||
status = sec_access_check(sd, token, *access_mask, access_mask);
|
||||
|
||||
/* this bit is always granted, even if not asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
/* on SMB, this bit is always granted, even if not
|
||||
asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
talloc_free(acl);
|
||||
|
||||
@ -800,3 +809,15 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
return the maximum allowed access mask
|
||||
*/
|
||||
NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
|
||||
struct ntvfs_request *req,
|
||||
struct pvfs_filename *name,
|
||||
uint32_t *maximal_access)
|
||||
{
|
||||
*maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
return pvfs_access_check(pvfs, req, name, maximal_access);
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ NTSTATUS pvfs_ioctl(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
case RAW_IOCTL_SMB2:
|
||||
case RAW_IOCTL_SMB2_NO_HANDLE:
|
||||
return NT_STATUS_FS_DRIVER_REQUIRED;
|
||||
/* see WSPP SMB2 test 46 */
|
||||
return NT_STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
|
@ -68,13 +68,8 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs,
|
||||
int i,
|
||||
NTSTATUS status)
|
||||
{
|
||||
/* in SMB2 mode we also try to unlock failing lock */
|
||||
if (req->ctx->protocol != PROTOCOL_SMB2) {
|
||||
i--;
|
||||
}
|
||||
|
||||
/* undo the locks we just did */
|
||||
for (;i>=0;i--) {
|
||||
for (i--;i>=0;i--) {
|
||||
brl_unlock(pvfs->brl_context,
|
||||
f->brl_handle,
|
||||
locks[i].pid,
|
||||
@ -390,12 +385,9 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
|
||||
DLIST_ADD(f->pending_list, pending);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
/* in SMB2 mode we also try to unlock failing lock */
|
||||
if (req->ctx->protocol != PROTOCOL_SMB2) {
|
||||
i--;
|
||||
}
|
||||
|
||||
/* undo the locks we just did */
|
||||
for (;i>=0;i--) {
|
||||
for (i--;i>=0;i--) {
|
||||
brl_unlock(pvfs->brl_context,
|
||||
f->brl_handle,
|
||||
locks[i].pid,
|
||||
|
@ -252,8 +252,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
|
||||
} else {
|
||||
status = pvfs_access_check_create(pvfs, req, name, &access_mask);
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
f->ntvfs = h;
|
||||
@ -578,6 +582,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
|
||||
status = pvfs_access_check_create(pvfs, req, name, &access_mask);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
/* check that the parent isn't opened with delete on close set */
|
||||
status = pvfs_resolve_parent(pvfs, req, name, &parent);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
@ -1122,6 +1132,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
uint32_t create_options;
|
||||
uint32_t share_access;
|
||||
uint32_t access_mask;
|
||||
uint32_t create_action = NTCREATEX_ACTION_EXISTED;
|
||||
bool del_on_close;
|
||||
bool stream_existed, stream_truncate=false;
|
||||
uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
|
||||
@ -1134,6 +1145,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
return ntvfs_map_open(ntvfs, req, io);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(io->generic.out);
|
||||
|
||||
create_options = io->generic.in.create_options;
|
||||
share_access = io->generic.in.share_access;
|
||||
access_mask = io->generic.in.access_mask;
|
||||
@ -1169,6 +1182,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* we ignore some file_attr bits */
|
||||
io->ntcreatex.in.file_attr &= ~(FILE_ATTRIBUTE_NONINDEXED |
|
||||
FILE_ATTRIBUTE_COMPRESSED |
|
||||
FILE_ATTRIBUTE_REPARSE_POINT |
|
||||
FILE_ATTRIBUTE_SPARSE |
|
||||
FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
/* resolve the cifs name to a posix name */
|
||||
status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname,
|
||||
PVFS_RESOLVE_STREAMS, &name);
|
||||
@ -1210,6 +1230,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
} else {
|
||||
stream_truncate = true;
|
||||
}
|
||||
create_action = NTCREATEX_ACTION_TRUNCATED;
|
||||
break;
|
||||
|
||||
case NTCREATEX_DISP_OPEN:
|
||||
@ -1228,6 +1249,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
} else {
|
||||
stream_truncate = true;
|
||||
}
|
||||
create_action = NTCREATEX_ACTION_TRUNCATED;
|
||||
break;
|
||||
|
||||
case NTCREATEX_DISP_CREATE:
|
||||
@ -1272,8 +1294,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
/* check the security descriptor */
|
||||
status = pvfs_access_check(pvfs, req, name, &access_mask);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
|
||||
@ -1487,7 +1513,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
io->generic.out.oplock_level = oplock_granted;
|
||||
io->generic.out.file.ntvfs = h;
|
||||
io->generic.out.create_action = stream_existed?
|
||||
NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
|
||||
create_action:NTCREATEX_ACTION_CREATED;
|
||||
|
||||
io->generic.out.create_time = name->dos.create_time;
|
||||
io->generic.out.access_time = name->dos.access_time;
|
||||
io->generic.out.write_time = name->dos.write_time;
|
||||
|
@ -41,6 +41,10 @@ static uint32_t pvfs_fileinfo_access(union smb_fileinfo *info)
|
||||
needed = 0;
|
||||
break;
|
||||
|
||||
case RAW_FILEINFO_ACCESS_INFORMATION:
|
||||
needed = 0;
|
||||
break;
|
||||
|
||||
case RAW_FILEINFO_SEC_DESC:
|
||||
needed = 0;
|
||||
if (info->query_secdesc.in.secinfo_flags & (SECINFO_OWNER|SECINFO_GROUP)) {
|
||||
@ -216,6 +220,10 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
|
||||
|
||||
case RAW_FILEINFO_NAME_INFO:
|
||||
case RAW_FILEINFO_NAME_INFORMATION:
|
||||
if (req->ctx->protocol == PROTOCOL_SMB2) {
|
||||
/* strange that SMB2 doesn't have this */
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
info->name_info.out.fname.s = name->original_name;
|
||||
return NT_STATUS_OK;
|
||||
|
||||
|
@ -457,7 +457,12 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
/* possibly change the attribute */
|
||||
if (newstats.dos.attrib != h->name->dos.attrib) {
|
||||
mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
|
||||
mode_t mode;
|
||||
if ((newstats.dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
|
||||
if (!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (fchmod(h->fd, mode) == -1) {
|
||||
return pvfs_map_errno(pvfs, errno);
|
||||
|
@ -48,6 +48,5 @@ samba4.ntvfs.cifs.raw.
|
||||
^samba4.net.api.become.dc.*$ # Fails
|
||||
nss.test # Fails
|
||||
samba4.samba3sam.python # Conversion from EJS not yet finished
|
||||
samba4.samdb.python # Not finished yet
|
||||
raw.offline # Samba 4 doesn't have much offline support yet
|
||||
winreg* #Does not authenticate against the target server
|
||||
|
@ -47,6 +47,7 @@ class TestCaseInTempDir(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
super(TestCaseInTempDir, self).tearDown()
|
||||
self.assertEquals([], os.listdir(self.tempdir))
|
||||
os.rmdir(self.tempdir)
|
||||
|
||||
|
||||
|
@ -16,13 +16,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from auth import system_session
|
||||
from credentials import Credentials
|
||||
from samba.auth import system_session
|
||||
from samba.credentials import Credentials
|
||||
import os
|
||||
from samba.provision import setup_samdb
|
||||
from samba.provision import setup_samdb, guess_names, setup_templatesdb
|
||||
from samba.samdb import SamDB
|
||||
from samba.tests import cmdline_loadparm, TestCaseInTempDir
|
||||
import security
|
||||
from samba import security
|
||||
from unittest import TestCase
|
||||
import uuid
|
||||
|
||||
@ -42,14 +42,27 @@ class SamDBTestCase(TestCaseInTempDir):
|
||||
domainsid = security.random_sid()
|
||||
hostguid = str(uuid.uuid4())
|
||||
path = os.path.join(self.tempdir, "samdb.ldb")
|
||||
self.samdb = setup_samdb(path, setup_path, system_session(), creds,
|
||||
cmdline_loadparm, schemadn, configdn,
|
||||
self.domaindn, "example.com", "EXAMPLE.COM",
|
||||
"FOO", lambda x: None, "foo", domaindn,
|
||||
False, domainsid, "# no aci", domainguid,
|
||||
policyguid, "EXAMPLE", True, "secret",
|
||||
"secret", "secret", hostguid, invocationid,
|
||||
session_info = system_session()
|
||||
names = guess_names(lp=cmdline_loadparm, hostname="foo",
|
||||
domain="EXAMPLE.COM", dnsdomain="example.com",
|
||||
serverrole="domain controller",
|
||||
domaindn=self.domaindn, configdn=configdn,
|
||||
schemadn=schemadn)
|
||||
setup_templatesdb(os.path.join(self.tempdir, "templates.ldb"),
|
||||
setup_path, session_info=session_info,
|
||||
credentials=creds, lp=cmdline_loadparm)
|
||||
self.samdb = setup_samdb(path, setup_path, session_info, creds,
|
||||
cmdline_loadparm, names,
|
||||
lambda x: None, domainsid,
|
||||
"# no aci", domainguid,
|
||||
policyguid, False, "secret",
|
||||
"secret", "secret", invocationid,
|
||||
"secret", "domain controller")
|
||||
def tearDown(self):
|
||||
for f in ['templates.ldb', 'schema.ldb', 'configuration.ldb',
|
||||
'users.ldb', 'samdb.ldb']:
|
||||
os.remove(os.path.join(self.tempdir, f))
|
||||
super(SamDBTestCase, self).tearDown()
|
||||
|
||||
def test_add_foreign(self):
|
||||
self.samdb.add_foreign(self.domaindn, "S-1-5-7", "Somedescription")
|
||||
|
@ -340,8 +340,8 @@ plantest "provision.python" none $SUBUNITRUN samba.tests.provision
|
||||
plantest "samba3.python" none $SUBUNITRUN samba.tests.samba3
|
||||
plantest "samr.python" dc $SUBUNITRUN samba.tests.dcerpc.sam
|
||||
plantest "dcerpc.bare.python" dc $SUBUNITRUN samba.tests.dcerpc.bare
|
||||
plantest "samdb.python" dc $SUBUNITRUN samba.tests.samdb
|
||||
plantest "unixinfo.python" dc $SUBUNITRUN samba.tests.dcerpc.unix
|
||||
plantest "samdb.python" none $SUBUNITRUN samba.tests.samdb
|
||||
plantest "events.python" none PYTHONPATH="$PYTHONPATH:lib/events" $SUBUNITRUN tests
|
||||
plantest "messaging.python" none PYTHONPATH="$PYTHONPATH:lib/messaging/tests" $SUBUNITRUN bindings
|
||||
plantest "samba3sam.python" none PYTHONPATH="$PYTHONPATH:dsdb/samdb/ldb_modules/tests" $SUBUNITRUN samba3sam
|
||||
|
@ -55,8 +55,7 @@ static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
|
||||
|
||||
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, op->info->out.blob.length));
|
||||
|
||||
/* TODO: this is maybe a o16s32_blob */
|
||||
SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x02, op->info->out.blob));
|
||||
SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob));
|
||||
SSVAL(req->out.body, 0x06, 0);
|
||||
|
||||
smb2srv_send_reply(req);
|
||||
|
@ -36,6 +36,18 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
|
||||
DATA_BLOB blob;
|
||||
|
||||
SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
|
||||
|
||||
/* setup the blobs we should give in the reply */
|
||||
if (io->smb2.out.maximal_access != 0) {
|
||||
uint32_t data[2];
|
||||
SIVAL(data, 0, 0);
|
||||
SIVAL(data, 4, io->smb2.out.maximal_access);
|
||||
SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs,
|
||||
SMB2_CREATE_TAG_MXAC,
|
||||
data_blob_const(data, 8)));
|
||||
}
|
||||
|
||||
|
||||
SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs));
|
||||
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length));
|
||||
|
||||
|
@ -158,7 +158,8 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
|
||||
}
|
||||
|
||||
if (!smb_sess) {
|
||||
status = NT_STATUS_USER_SESSION_DELETED;
|
||||
/* see WSPP test suite - test 11 */
|
||||
status = NT_STATUS_REQUEST_NOT_ACCEPTED;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
@ -262,23 +262,6 @@ gentest_OBJ_FILES = $(torturesrcdir)/gentest.o
|
||||
|
||||
MANPAGES += $(torturesrcdir)/man/gentest.1
|
||||
|
||||
#################################
|
||||
# Start BINARY gentest_smb2
|
||||
[BINARY::gentest_smb2]
|
||||
INSTALLDIR = BINDIR
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-HOSTCONFIG \
|
||||
LIBSAMBA-UTIL \
|
||||
LIBPOPT \
|
||||
POPT_SAMBA \
|
||||
POPT_CREDENTIALS \
|
||||
LIBCLI_SMB \
|
||||
LIBCLI_RAW
|
||||
# End BINARY gentest_smb2
|
||||
#################################
|
||||
|
||||
gentest_smb2_OBJ_FILES = $(torturesrcdir)/gentest_smb2.o
|
||||
|
||||
#################################
|
||||
# Start BINARY masktest
|
||||
[BINARY::masktest]
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,7 @@
|
||||
if (v != correct) { \
|
||||
printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
|
||||
__location__, #v, (unsigned long long)v, (unsigned long long)correct); \
|
||||
return false; \
|
||||
return false; \
|
||||
}} while (0)
|
||||
|
||||
/*
|
||||
@ -52,7 +52,8 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
struct smb2_create io;
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||
uint32_t access_mask, file_attributes, denied_mask;
|
||||
uint32_t access_mask, file_attributes, file_attributes_set, denied_mask;
|
||||
union smb_fileinfo q;
|
||||
|
||||
ZERO_STRUCT(io);
|
||||
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
@ -115,7 +116,8 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
for (i=0;i<32;i++) {
|
||||
io.in.desired_access = 1<<i;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
|
||||
NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
|
||||
access_mask |= io.in.desired_access;
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
@ -131,6 +133,7 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.in.file_attributes = 0;
|
||||
file_attributes = 0;
|
||||
file_attributes_set = 0;
|
||||
denied_mask = 0;
|
||||
{
|
||||
int i;
|
||||
@ -146,12 +149,14 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
status = smb2_util_close(tree, io.out.file.handle);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
file_attributes_set |= io.out.file_attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EQUAL(file_attributes, 0xffff8048);
|
||||
CHECK_EQUAL(denied_mask, 0x4000);
|
||||
CHECK_EQUAL(file_attributes_set, 0x00001127);
|
||||
|
||||
smb2_deltree(tree, FNAME);
|
||||
|
||||
@ -177,6 +182,20 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
|
||||
|
||||
io.in.fname = FNAME;
|
||||
io.in.file_attributes = 0;
|
||||
io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
|
||||
io.in.query_maximal_access = true;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
|
||||
|
||||
q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
|
||||
q.access_information.in.file.handle = io.out.file.handle;
|
||||
status = smb2_getinfo_file(tree, tmp_ctx, &q);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
smb2_deltree(tree, FNAME);
|
||||
@ -237,6 +256,7 @@ static bool test_create_blob(struct torture_context *torture, struct smb2_tree *
|
||||
io.in.query_maximal_access = true;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
|
||||
|
||||
status = smb2_util_close(tree, io.out.file.handle);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
@ -106,7 +106,11 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
lck.in.reserved = 0x123ab3;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
lck.in.reserved = 0x123ab4;
|
||||
@ -115,7 +119,11 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
lck.in.reserved = 0x123ab5;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
lck.in.lock_count = 0x0001;
|
||||
@ -133,14 +141,22 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
el[0].flags = 0x00000000;
|
||||
@ -473,6 +489,51 @@ static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_t
|
||||
return test_lock_read_write(torture, tree, &s);
|
||||
}
|
||||
|
||||
|
||||
static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
NTSTATUS status;
|
||||
struct smb2_handle h;
|
||||
uint8_t buf[200];
|
||||
struct smb2_lock lck;
|
||||
struct smb2_lock_element el[2];
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "autounlock.txt", &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ZERO_STRUCT(lck);
|
||||
lck.in.locks = el;
|
||||
lck.in.lock_count = 0x0001;
|
||||
lck.in.file.handle = h;
|
||||
el[0].offset = 0;
|
||||
el[0].length = 1;
|
||||
el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* basic testing of SMB2 locking
|
||||
*/
|
||||
struct torture_suite *torture_smb2_lock_init(void)
|
||||
@ -483,6 +544,7 @@ struct torture_suite *torture_smb2_lock_init(void)
|
||||
torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
|
||||
torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
|
||||
torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
|
||||
torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
|
||||
|
||||
|
@ -44,6 +44,9 @@
|
||||
goto done; \
|
||||
}} while (0)
|
||||
|
||||
#define FNAME "smb2_readtest.dat"
|
||||
#define DNAME "smb2_readtest.dir"
|
||||
|
||||
static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
@ -55,7 +58,7 @@ static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tre
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "lock1.txt", &h);
|
||||
status = torture_smb2_testfile(tree, FNAME, &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
@ -139,7 +142,7 @@ static bool test_read_position(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "lock1.txt", &h);
|
||||
status = torture_smb2_testfile(tree, FNAME, &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
@ -172,6 +175,59 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_read_dir(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
NTSTATUS status;
|
||||
struct smb2_handle h;
|
||||
uint8_t buf[100];
|
||||
struct smb2_read rd;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||
|
||||
status = torture_smb2_testdir(tree, DNAME, &h);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf(__location__ " Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(rd);
|
||||
rd.in.file.handle = h;
|
||||
rd.in.length = 10;
|
||||
rd.in.offset = 0;
|
||||
rd.in.min_count = 1;
|
||||
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
rd.in.min_count = 11;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
rd.in.length = 0;
|
||||
rd.in.min_count = 2592;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
|
||||
rd.in.length = 0;
|
||||
rd.in.min_count = 0;
|
||||
rd.in.channel = 0;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
basic testing of SMB2 read
|
||||
*/
|
||||
@ -181,6 +237,7 @@ struct torture_suite *torture_smb2_read_init(void)
|
||||
|
||||
torture_suite_add_1smb2_test(suite, "EOF", test_read_eof);
|
||||
torture_suite_add_1smb2_test(suite, "POSITION", test_read_position);
|
||||
torture_suite_add_1smb2_test(suite, "DIR", test_read_dir);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2-READ tests");
|
||||
|
||||
|
@ -175,6 +175,10 @@ bool torture_smb2_setinfo(struct torture_context *torture)
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
|
||||
|
||||
printf("can't change a file to a directory\n");
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER);
|
||||
|
||||
printf("restore attribute\n");
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
|
Loading…
Reference in New Issue
Block a user