mirror of
https://github.com/samba-team/samba.git
synced 2025-03-11 16:58:40 +03:00
Compare commits
17 Commits
3294fb0667
...
6d71edab5a
Author | SHA1 | Date | |
---|---|---|---|
|
6d71edab5a | ||
|
b51a827e47 | ||
|
a10755881e | ||
|
306d4e7fff | ||
|
21ef00d0f0 | ||
|
26e8105518 | ||
|
44a2458ca4 | ||
|
8c468c6e5c | ||
|
d46bfc5d50 | ||
|
02cc280710 | ||
|
239d8f463b | ||
|
27198998ed | ||
|
8eccfbea7d | ||
|
a882e86104 | ||
|
475896028b | ||
|
be5531aaec | ||
|
6c619c77c9 |
@ -47,7 +47,7 @@ variables:
|
||||
# Set this to the contents of bootstrap/sha1sum.txt
|
||||
# which is generated by bootstrap/template.py --render
|
||||
#
|
||||
SAMBA_CI_CONTAINER_TAG: 936722ecb26bedf6ea0acd9228963ce45ed419d4
|
||||
SAMBA_CI_CONTAINER_TAG: d101907857587b6421907c45676497c336d45ea7
|
||||
#
|
||||
# We use the ubuntu2204 image as default as
|
||||
# it matches what we have on atb-devel-224
|
||||
@ -66,7 +66,7 @@ variables:
|
||||
SAMBA_CI_CONTAINER_IMAGE_opensuse155: opensuse155
|
||||
SAMBA_CI_CONTAINER_IMAGE_rocky8: rocky8
|
||||
SAMBA_CI_CONTAINER_IMAGE_centos9s: centos9s
|
||||
SAMBA_CI_CONTAINER_IMAGE_fedora40: fedora40
|
||||
SAMBA_CI_CONTAINER_IMAGE_fedora41: fedora41
|
||||
|
||||
include:
|
||||
# The image creation details are specified in a separate file
|
||||
@ -267,13 +267,13 @@ samba-def-build:
|
||||
samba-mit-build:
|
||||
extends: .shared_template_build_only
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora40}
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora41}
|
||||
stage: build_first
|
||||
|
||||
.needs_samba-mit-build:
|
||||
extends: .shared_template_test_only
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora40}
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora41}
|
||||
needs:
|
||||
- job: samba-mit-build
|
||||
artifacts: true
|
||||
@ -321,7 +321,7 @@ samba:
|
||||
samba-mitkrb5:
|
||||
extends: .shared_template
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora40}
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora41}
|
||||
|
||||
samba-minimal-smbd:
|
||||
extends: .shared_template
|
||||
@ -391,7 +391,7 @@ samba-addc-mit-4b:
|
||||
samba-fips:
|
||||
extends: .shared_template
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora40}
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora41}
|
||||
|
||||
samba-codecheck:
|
||||
extends: .shared_template
|
||||
@ -672,10 +672,10 @@ centos9s-samba-o3:
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_centos9s}
|
||||
|
||||
fedora40-samba-o3:
|
||||
fedora41-samba-o3:
|
||||
extends: .samba-o3-template
|
||||
variables:
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora40}
|
||||
SAMBA_CI_JOB_IMAGE: ${SAMBA_CI_CONTAINER_IMAGE_fedora41}
|
||||
|
||||
#
|
||||
# Keep the samba-o3 sections at the end ...
|
||||
|
@ -10,6 +10,7 @@
|
||||
variables:
|
||||
SAMBA_CI_IS_BROKEN_IMAGE: "no"
|
||||
SAMBA_CI_TEST_JOB: "samba-o3"
|
||||
SAMBA_CI_PLATFORM: "linux/amd64"
|
||||
before_script:
|
||||
# install prerequisites
|
||||
- dnf install -qy diffutils
|
||||
@ -27,7 +28,7 @@
|
||||
script: |
|
||||
set -xueo pipefail
|
||||
ci_image_name=samba-ci-${CI_JOB_NAME}
|
||||
podman build -t ${ci_image_name} --build-arg SHA1SUM=${SAMBA_CI_CONTAINER_TAG} bootstrap/generated-dists/${CI_JOB_NAME}
|
||||
podman build --platform ${SAMBA_CI_PLATFORM} --tag ${ci_image_name} --build-arg SHA1SUM=${SAMBA_CI_CONTAINER_TAG} bootstrap/generated-dists/${CI_JOB_NAME}
|
||||
ci_image_path="${SAMBA_CI_CONTAINER_REGISTRY}/${ci_image_name}"
|
||||
timestamp=$(date +%Y%m%d%H%M%S)
|
||||
container_hash=$(podman image inspect --format='{{ .Id }}' ${ci_image_name} | cut -c 1-9)
|
||||
@ -98,13 +99,14 @@ debian11:
|
||||
debian12:
|
||||
extends: .build_image_template
|
||||
|
||||
fedora40:
|
||||
fedora41:
|
||||
extends: .build_image_template
|
||||
|
||||
debian11-32bit:
|
||||
extends: .build_image_template
|
||||
variables:
|
||||
SAMBA_CI_TEST_JOB: "samba-32bit"
|
||||
SAMBA_CI_PLATFORM: "linux/i386"
|
||||
|
||||
rocky8:
|
||||
extends: .build_image_template
|
||||
|
@ -159,6 +159,10 @@ PKGS = [
|
||||
('', 'python3-libsemanage'),
|
||||
('', 'python3-policycoreutils'),
|
||||
|
||||
# A copy of the `crypt` module that was removed in Python 3.13
|
||||
# See also https://bugzilla.samba.org/show_bug.cgi?id=15756
|
||||
('', 'python3-crypt-r'),
|
||||
|
||||
# perl
|
||||
('libparse-yapp-perl', 'perl-Parse-Yapp'),
|
||||
('perl-modules', ''),
|
||||
@ -457,7 +461,7 @@ DEB_DISTS = {
|
||||
}
|
||||
},
|
||||
'debian11-32bit': {
|
||||
'docker_image': 'registry-1.docker.io/i386/debian:11',
|
||||
'docker_image': 'debian:11', # specify the platform in .gitlab-ci.yaml
|
||||
'vagrant_box': 'debian/bullseye32',
|
||||
'replace': {
|
||||
'language-pack-en': '', # included in locales
|
||||
@ -534,6 +538,7 @@ RPM_DISTS = {
|
||||
'ShellCheck': '',
|
||||
'shfmt': '',
|
||||
'codespell': '',
|
||||
'python3-crypt-r': '',
|
||||
}
|
||||
},
|
||||
'centos9s': {
|
||||
@ -553,11 +558,12 @@ RPM_DISTS = {
|
||||
'codespell': '',
|
||||
'libcephfs-devel': '', # not available anymore
|
||||
'curl': '', # Use installed curl-minimal
|
||||
'python3-crypt-r': '',
|
||||
}
|
||||
},
|
||||
'fedora40': {
|
||||
'docker_image': 'quay.io/fedora/fedora:40',
|
||||
'vagrant_box': 'fedora/40-cloud-base',
|
||||
'fedora41': {
|
||||
'docker_image': 'quay.io/fedora/fedora:41',
|
||||
'vagrant_box': 'fedora/41-cloud-base',
|
||||
'bootstrap': DNF_BOOTSTRAP,
|
||||
'replace': {
|
||||
'lsb-release': 'redhat-lsb',
|
||||
@ -581,6 +587,7 @@ RPM_DISTS = {
|
||||
'keyutils-libs-devel': 'keyutils-devel',
|
||||
'krb5-workstation': 'krb5-client',
|
||||
'python3-libsemanage': 'python3-semanage',
|
||||
'python3-crypt-r': '',
|
||||
'openldap-devel': 'openldap2-devel',
|
||||
'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
|
||||
'perl-JSON-Parse': 'perl-JSON-XS',
|
||||
|
10
bootstrap/generated-dists/Vagrantfile
vendored
10
bootstrap/generated-dists/Vagrantfile
vendored
@ -45,11 +45,11 @@ Vagrant.configure("2") do |config|
|
||||
v.vm.provision :shell, path: "debian12-32bit/locale.sh"
|
||||
end
|
||||
|
||||
config.vm.define "fedora40" do |v|
|
||||
v.vm.box = "fedora/40-cloud-base"
|
||||
v.vm.hostname = "fedora40"
|
||||
v.vm.provision :shell, path: "fedora40/bootstrap.sh"
|
||||
v.vm.provision :shell, path: "fedora40/locale.sh"
|
||||
config.vm.define "fedora41" do |v|
|
||||
v.vm.box = "fedora/41-cloud-base"
|
||||
v.vm.hostname = "fedora41"
|
||||
v.vm.provision :shell, path: "fedora41/bootstrap.sh"
|
||||
v.vm.provision :shell, path: "fedora41/locale.sh"
|
||||
end
|
||||
|
||||
config.vm.define "opensuse155" do |v|
|
||||
|
@ -3,7 +3,7 @@
|
||||
# See also bootstrap/config.py
|
||||
#
|
||||
|
||||
FROM registry-1.docker.io/i386/debian:11
|
||||
FROM debian:11
|
||||
|
||||
# pass in with --build-arg while build
|
||||
ARG SHA1SUM
|
||||
|
@ -3,7 +3,7 @@
|
||||
# See also bootstrap/config.py
|
||||
#
|
||||
|
||||
FROM quay.io/fedora/fedora:40
|
||||
FROM quay.io/fedora/fedora:41
|
||||
|
||||
# pass in with --build-arg while build
|
||||
ARG SHA1SUM
|
@ -92,6 +92,7 @@ dnf install -y \
|
||||
procps-ng \
|
||||
psmisc \
|
||||
python3 \
|
||||
python3-crypt-r \
|
||||
python3-cryptography \
|
||||
python3-dateutil \
|
||||
python3-devel \
|
@ -81,6 +81,7 @@ packages:
|
||||
- procps-ng
|
||||
- psmisc
|
||||
- python3
|
||||
- python3-crypt-r
|
||||
- python3-cryptography
|
||||
- python3-dateutil
|
||||
- python3-devel
|
@ -1 +1 @@
|
||||
936722ecb26bedf6ea0acd9228963ce45ed419d4
|
||||
d101907857587b6421907c45676497c336d45ea7
|
||||
|
@ -417,6 +417,6 @@ enum smb_whoami_flags {
|
||||
|
||||
#define INFO_LEVEL_IS_UNIX(level) ((((level) >= MIN_UNIX_INFO_LEVEL) && \
|
||||
((level) <= MAX_UNIX_INFO_LEVEL)) || \
|
||||
((level) == SMB2_FILE_POSIX_INFORMATION_INTERNAL))
|
||||
((level) == FSCC_FILE_POSIX_INFORMATION))
|
||||
|
||||
#endif /* __SMB_UNIX_EXT_H__ */
|
||||
|
@ -1493,8 +1493,7 @@ class PkInitTests(KDCBaseTest):
|
||||
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, 'SambaState'),
|
||||
x509.NameAttribute(NameOID.ORGANIZATION_NAME, 'SambaSelfTesting'),
|
||||
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, 'Users'),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME,
|
||||
f'{cert_name}/emailAddress={cert_name}'),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, f'{cert_name}'),
|
||||
]))
|
||||
|
||||
# The new certificate must be issued by the root CA.
|
||||
|
@ -24,6 +24,7 @@ from samba import credentials
|
||||
from samba import (ntstatus,NTSTATUSError)
|
||||
import samba.tests
|
||||
import os
|
||||
import stat
|
||||
|
||||
class LibsmbTests(samba.tests.TestCase):
|
||||
|
||||
@ -53,3 +54,10 @@ class LibsmbTests(samba.tests.TestCase):
|
||||
elif not (e.args[0] == ntstatus.NT_STATUS_OBJECT_NAME_NOT_FOUND or
|
||||
e.args[0] == ntstatus.NT_STATUS_OBJECT_PATH_NOT_FOUND):
|
||||
raise
|
||||
|
||||
def wire_mode_to_unix(self, wire):
|
||||
mode = libsmb.wire_mode_to_unix(wire)
|
||||
type = stat.S_IFMT(mode)
|
||||
perms = mode & (stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO|
|
||||
stat.S_ISUID|stat.S_ISGID|stat.S_ISVTX)
|
||||
return (type, perms)
|
||||
|
@ -22,9 +22,12 @@ from samba import reparse_symlink
|
||||
import samba.tests.libsmb
|
||||
import stat
|
||||
|
||||
def posix_context(mode):
|
||||
return (libsmb.SMB2_CREATE_TAG_POSIX, mode.to_bytes(4, 'little'))
|
||||
|
||||
class ReparsePoints(samba.tests.libsmb.LibsmbTests):
|
||||
|
||||
def connection(self):
|
||||
def connection(self, posix=False):
|
||||
share = samba.tests.env_get_var_value("SHARENAME", allow_missing=True)
|
||||
if not share:
|
||||
share = "tmp"
|
||||
@ -34,6 +37,7 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
|
||||
share,
|
||||
self.lp,
|
||||
self.creds,
|
||||
posix=posix,
|
||||
force_smb1=smb1)
|
||||
return conn
|
||||
|
||||
@ -233,10 +237,14 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
|
||||
err = e.args[0]
|
||||
if (err != ntstatus.NT_STATUS_ACCESS_DENIED):
|
||||
raise
|
||||
finally:
|
||||
conn.close(dir_fd)
|
||||
self.clean_file(conn, dirname)
|
||||
|
||||
if (err == ntstatus.NT_STATUS_ACCESS_DENIED):
|
||||
self.fail("Could not set reparse point on directory")
|
||||
conn.delete_on_close(fd, 1)
|
||||
conn.close(dir_fd)
|
||||
self.clean_file(conn, dirname)
|
||||
return
|
||||
|
||||
with self.assertRaises(NTSTATUSError) as e:
|
||||
@ -397,22 +405,30 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
|
||||
|
||||
def do_test_nfs_reparse(self, filename, filetype, nfstype):
|
||||
"""Test special file reparse tag"""
|
||||
smb2 = self.connection()
|
||||
smb2 = self.connection(posix=True)
|
||||
smb1 = self.connection_posix()
|
||||
|
||||
self.clean_file(smb2, filename)
|
||||
smb1.mknod(filename, filetype | 0o755)
|
||||
|
||||
fd = smb2.create(
|
||||
fd,_,_ = smb2.create_ex(
|
||||
filename,
|
||||
DesiredAccess=sec.SEC_FILE_READ_ATTRIBUTE|sec.SEC_STD_DELETE,
|
||||
CreateOptions=libsmb.FILE_OPEN_REPARSE_POINT,
|
||||
CreateDisposition=libsmb.FILE_OPEN)
|
||||
CreateDisposition=libsmb.FILE_OPEN,
|
||||
ShareAccess=(libsmb.FILE_SHARE_READ|libsmb.FILE_SHARE_WRITE|libsmb.FILE_SHARE_DELETE),
|
||||
CreateContexts=[posix_context(0o600)])
|
||||
smb2.delete_on_close(fd, 1)
|
||||
|
||||
info = smb2.qfileinfo(fd, libsmb.FSCC_FILE_ATTRIBUTE_TAG_INFORMATION);
|
||||
self.assertEqual(info['tag'], libsmb.IO_REPARSE_TAG_NFS)
|
||||
|
||||
info = smb2.qfileinfo(fd, libsmb.FSCC_FILE_POSIX_INFORMATION);
|
||||
self.assertEqual(info['reparse_tag'], libsmb.IO_REPARSE_TAG_NFS)
|
||||
|
||||
type, perms = self.wire_mode_to_unix(info['perms'])
|
||||
self.assertEqual(type, filetype)
|
||||
|
||||
reparse = smb2.fsctl(fd, libsmb.FSCTL_GET_REPARSE_POINT, b'', 1024)
|
||||
(tag, ) = reparse_symlink.get(reparse)
|
||||
self.assertEqual(tag, nfstype)
|
||||
@ -425,6 +441,34 @@ class ReparsePoints(samba.tests.libsmb.LibsmbTests):
|
||||
"""Test SOCK reparse tag"""
|
||||
self.do_test_nfs_reparse('sock', stat.S_IFSOCK, 'NFS_SPECFILE_SOCK')
|
||||
|
||||
def test_reparsepoint_posix_type(self):
|
||||
conn = self.connection(posix=True)
|
||||
filename = 'reparse'
|
||||
self.clean_file(conn, filename)
|
||||
|
||||
fd,_,_ = conn.create_ex(
|
||||
filename,
|
||||
DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE,
|
||||
CreateDisposition=libsmb.FILE_CREATE,
|
||||
CreateContexts=[posix_context(0o600)])
|
||||
b = reparse_symlink.symlink_put("y", "y", 0, 0)
|
||||
conn.fsctl(fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
|
||||
conn.close(fd)
|
||||
|
||||
dirents = conn.list("", filename,info_level=libsmb.SMB2_FIND_POSIX_INFORMATION)
|
||||
self.assertEqual(
|
||||
dirents[0]["attrib"],
|
||||
libsmb.FILE_ATTRIBUTE_REPARSE_POINT|
|
||||
libsmb.FILE_ATTRIBUTE_ARCHIVE)
|
||||
self.assertEqual(
|
||||
dirents[0]["reparse_tag"],
|
||||
libsmb.IO_REPARSE_TAG_SYMLINK)
|
||||
|
||||
type, perms = self.wire_mode_to_unix(dirents[0]['perms'])
|
||||
self.assertEqual(type, stat.S_IFLNK)
|
||||
|
||||
self.clean_file(conn, filename)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
unittest.main()
|
||||
|
@ -70,13 +70,6 @@ class Smb3UnixTests(samba.tests.libsmb.LibsmbTests):
|
||||
|
||||
return (conn1, conn2)
|
||||
|
||||
def wire_mode_to_unix(self, wire):
|
||||
mode = libsmb.wire_mode_to_unix(wire)
|
||||
type = stat.S_IFMT(mode)
|
||||
perms = mode & (stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO|
|
||||
stat.S_ISUID|stat.S_ISGID|stat.S_ISVTX)
|
||||
return (type, perms)
|
||||
|
||||
def test_negotiate_context_posix(self):
|
||||
c = libsmb.Conn(
|
||||
self.server_ip,
|
||||
|
@ -455,6 +455,10 @@ if ($opt_mitkrb5 == 1) {
|
||||
$ENV{KRB5RCACHETYPE} = "none";
|
||||
}
|
||||
|
||||
# Enable support for SHA1 in OpenSSL
|
||||
# This is required e.g. for pkinit sha1 tests
|
||||
$ENV{OPENSSL_ENABLE_SHA1_SIGNATURES} = 1;
|
||||
|
||||
# After this many seconds, the server will self-terminate. All tests
|
||||
# must terminate in this time, and testenv will only stay alive this
|
||||
# long
|
||||
|
@ -341,8 +341,7 @@ Byte offset Type name description
|
||||
#define FSCC_FILE_MAXIMUM_INFORMATION 55
|
||||
|
||||
/* As yet undefined FSCC_ code for POSIX info level. */
|
||||
#define SMB2_FILE_POSIX_INFORMATION 100
|
||||
#define SMB2_FS_POSIX_INFORMATION 100
|
||||
#define FSCC_FILE_POSIX_INFORMATION 100
|
||||
|
||||
/* MS-FSCC 2.4 File System Information Classes */
|
||||
|
||||
@ -356,6 +355,9 @@ Byte offset Type name description
|
||||
#define FSCC_FS_OBJECTID_INFORMATION 8
|
||||
#define FSCC_FS_SECTOR_SIZE_INFORMATION 11
|
||||
|
||||
/* As yet undefined FSCC_ code for POSIX info level. */
|
||||
#define FSCC_FS_POSIX_INFORMATION 100
|
||||
|
||||
/* NT passthrough levels... */
|
||||
|
||||
#define NT_PASSTHROUGH_OFFSET 1000
|
||||
@ -412,8 +414,6 @@ Byte offset Type name description
|
||||
#define SMB2_FILE_RENAME_INFORMATION_INTERNAL (FSCC_FILE_RENAME_INFORMATION + SMB2_INFO_SPECIAL)
|
||||
#define SMB2_FILE_FULL_EA_INFORMATION (FSCC_FILE_FULL_EA_INFORMATION + SMB2_INFO_SPECIAL)
|
||||
#define SMB2_FILE_ALL_INFORMATION (FSCC_FILE_ALL_INFORMATION + SMB2_INFO_SPECIAL)
|
||||
#define SMB2_FILE_POSIX_INFORMATION_INTERNAL (SMB2_FILE_POSIX_INFORMATION + SMB2_INFO_SPECIAL)
|
||||
#define SMB2_FS_POSIX_INFORMATION_INTERNAL 1100
|
||||
|
||||
/* NT passthrough levels for qfsinfo. */
|
||||
|
||||
|
@ -5145,7 +5145,7 @@ static void cli_smb2_get_posix_fs_info_opened(struct tevent_req *subreq)
|
||||
state->cli,
|
||||
state->fnum,
|
||||
SMB2_0_INFO_FILESYSTEM, /* in_info_type */
|
||||
SMB2_FS_POSIX_INFORMATION, /* in_file_info_class */
|
||||
FSCC_FS_POSIX_INFORMATION, /* in_file_info_class */
|
||||
0xFFFF, /* in_max_output_length */
|
||||
NULL, /* in_input_buffer */
|
||||
0, /* in_additional_info */
|
||||
|
@ -60,6 +60,7 @@ c = libsmb.Conn("127.0.0.1",
|
||||
#include "trans2.h"
|
||||
#include "libsmb/clirap.h"
|
||||
#include "librpc/rpc/pyrpc_util.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
|
||||
#define LIST_ATTRIBUTE_MASK \
|
||||
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN)
|
||||
@ -1388,6 +1389,129 @@ static PyObject *py_cli_qfileinfo(struct py_cli_state *self, PyObject *args)
|
||||
(unsigned long long)tag);
|
||||
break;
|
||||
}
|
||||
case FSCC_FILE_POSIX_INFORMATION: {
|
||||
size_t data_off = 0;
|
||||
time_t btime;
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
time_t ctime;
|
||||
uint64_t size;
|
||||
uint64_t alloc_size;
|
||||
uint32_t attr;
|
||||
uint64_t ino;
|
||||
uint32_t dev;
|
||||
uint32_t nlinks;
|
||||
uint32_t reparse_tag;
|
||||
uint32_t mode;
|
||||
size_t sid_size;
|
||||
enum ndr_err_code ndr_err;
|
||||
struct dom_sid owner, group;
|
||||
struct dom_sid_buf owner_buf, group_buf;
|
||||
|
||||
if (num_rdata < 80) {
|
||||
PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btime = nt_time_to_unix(PULL_LE_U64(rdata, data_off));
|
||||
data_off += 8;
|
||||
atime = nt_time_to_unix(PULL_LE_U64(rdata, data_off));
|
||||
data_off += 8;
|
||||
mtime = nt_time_to_unix(PULL_LE_U64(rdata, data_off));
|
||||
data_off += 8;
|
||||
ctime = nt_time_to_unix(PULL_LE_U64(rdata, data_off));
|
||||
data_off += 8;
|
||||
size = PULL_LE_U64(rdata, data_off);
|
||||
data_off += 8;
|
||||
alloc_size = PULL_LE_U64(rdata, data_off);
|
||||
data_off += 8;
|
||||
attr = PULL_LE_U32(rdata, data_off);
|
||||
data_off += 4;
|
||||
ino = PULL_LE_U64(rdata, data_off);
|
||||
data_off += 8;
|
||||
dev = PULL_LE_U32(rdata, data_off);
|
||||
data_off += 4;
|
||||
/* 4 bytes reserved */
|
||||
data_off += 4;
|
||||
nlinks = PULL_LE_U32(rdata, data_off);
|
||||
data_off += 4;
|
||||
reparse_tag = PULL_LE_U32(rdata, data_off);
|
||||
data_off += 4;
|
||||
mode = PULL_LE_U32(rdata, data_off);
|
||||
data_off += 4;
|
||||
|
||||
ndr_err = ndr_pull_struct_blob_noalloc(
|
||||
rdata + data_off,
|
||||
num_rdata - data_off,
|
||||
&owner,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_dom_sid,
|
||||
&sid_size);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE);
|
||||
return NULL;
|
||||
}
|
||||
if (data_off + sid_size < data_off ||
|
||||
data_off + sid_size > num_rdata)
|
||||
{
|
||||
PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE);
|
||||
return NULL;
|
||||
}
|
||||
data_off += sid_size;
|
||||
|
||||
ndr_err = ndr_pull_struct_blob_noalloc(
|
||||
rdata + data_off,
|
||||
num_rdata - data_off,
|
||||
&group,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_dom_sid,
|
||||
&sid_size);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
PyErr_SetNTSTATUS(NT_STATUS_INVALID_NETWORK_RESPONSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = Py_BuildValue(
|
||||
"{s:i," /* attr */
|
||||
"s:K,s:K,s:K,s:K," /* dates */
|
||||
"s:K,s:K," /* sizes */
|
||||
"s:K,s:K,s:K," /* ino, dev, nlinks */
|
||||
"s:K,s:K," /* tag, mode */
|
||||
"s:s,s:s}", /* owner, group */
|
||||
|
||||
"attrib",
|
||||
attr,
|
||||
|
||||
"btime",
|
||||
(unsigned long long)btime,
|
||||
"atime",
|
||||
(unsigned long long)atime,
|
||||
"mtime",
|
||||
(unsigned long long)mtime,
|
||||
"ctime",
|
||||
(unsigned long long)ctime,
|
||||
|
||||
"allocation_size",
|
||||
(unsigned long long)alloc_size,
|
||||
"size",
|
||||
(unsigned long long)size,
|
||||
|
||||
"ino",
|
||||
(unsigned long long)ino,
|
||||
"dev",
|
||||
(unsigned long long)dev,
|
||||
"nlink",
|
||||
(unsigned long long)nlinks,
|
||||
|
||||
"reparse_tag",
|
||||
(unsigned long long)reparse_tag,
|
||||
"perms",
|
||||
(unsigned long long)mode,
|
||||
|
||||
"owner_sid",
|
||||
dom_sid_str_buf(&owner, &owner_buf),
|
||||
"group_sid",
|
||||
dom_sid_str_buf(&group, &group_buf));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
result = PyBytes_FromStringAndSize((char *)rdata, num_rdata);
|
||||
break;
|
||||
@ -3222,6 +3346,7 @@ MODULE_INIT_FUNC(libsmb_samba_cwrapper)
|
||||
ADD_FLAGS(FSCC_FILE_ID_GLOBAL_TX_DIRECTORY_INFORMATION);
|
||||
ADD_FLAGS(FSCC_FILE_STANDARD_LINK_INFORMATION);
|
||||
ADD_FLAGS(FSCC_FILE_MAXIMUM_INFORMATION);
|
||||
ADD_FLAGS(FSCC_FILE_POSIX_INFORMATION);
|
||||
|
||||
#define ADD_STRING(val) PyModule_AddObject(m, #val, PyBytes_FromString(val))
|
||||
|
||||
|
@ -687,7 +687,9 @@ static uint32_t dos_mode_post(uint32_t dosmode,
|
||||
dosmode |= dos_mode_from_name(fsp->conn, smb_fname->base_name, dosmode);
|
||||
|
||||
if (S_ISDIR(smb_fname->st.st_ex_mode)) {
|
||||
dosmode |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
if (!(dosmode & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
dosmode |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
} else if (dosmode == 0) {
|
||||
dosmode = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
@ -736,13 +738,12 @@ uint32_t fdos_mode(struct files_struct *fsp)
|
||||
* Everybody else wants to see symlinks as
|
||||
* reparse points
|
||||
*/
|
||||
result = FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
result = FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
return FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1223,10 +1223,9 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
||||
DATA_BLOB *new_cookie);
|
||||
|
||||
struct smb3_file_posix_information;
|
||||
void smb3_file_posix_information_init(
|
||||
NTSTATUS smb3_file_posix_information_init(
|
||||
connection_struct *conn,
|
||||
const struct stat_ex *st,
|
||||
uint32_t reparse_tag,
|
||||
const struct smb_filename *smb_fname,
|
||||
uint32_t dos_attributes,
|
||||
struct smb3_file_posix_information *dst);
|
||||
|
||||
|
@ -338,17 +338,17 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
|
||||
file_info_level = SMB2_FILE_ALL_INFORMATION;
|
||||
break;
|
||||
|
||||
case SMB2_FILE_POSIX_INFORMATION:
|
||||
case FSCC_FILE_POSIX_INFORMATION:
|
||||
if (!fsp->fsp_flags.posix_open) {
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
file_info_level = SMB2_FILE_POSIX_INFORMATION_INTERNAL;
|
||||
file_info_level = in_file_info_class;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* the levels directly map to the passthru levels */
|
||||
file_info_level = in_file_info_class + 1000;
|
||||
file_info_level = in_file_info_class + NT_PASSTHROUGH_OFFSET;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -465,8 +465,15 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
|
||||
int data_size = 0;
|
||||
size_t fixed_portion;
|
||||
|
||||
/* the levels directly map to the passthru levels */
|
||||
file_info_level = in_file_info_class + 1000;
|
||||
switch (in_file_info_class) {
|
||||
case FSCC_FS_POSIX_INFORMATION:
|
||||
file_info_level = in_file_info_class;
|
||||
break;
|
||||
default:
|
||||
/* the levels directly map to the passthru levels */
|
||||
file_info_level = in_file_info_class + NT_PASSTHROUGH_OFFSET;
|
||||
break;
|
||||
}
|
||||
|
||||
status = smbd_do_qfsinfo(smb2req->xconn, conn, state,
|
||||
file_info_level,
|
||||
|
@ -23,14 +23,132 @@
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "librpc/gen_ndr/smb3posix.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "source3/modules/util_reparse.h"
|
||||
#include "libcli/smb/reparse.h"
|
||||
|
||||
void smb3_file_posix_information_init(
|
||||
static NTSTATUS reparse_buffer_parse_posix_type(uint32_t reparse_tag,
|
||||
uint8_t *data,
|
||||
uint32_t len,
|
||||
mode_t *type)
|
||||
{
|
||||
struct reparse_data_buffer *reparse = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
|
||||
*type = S_IFLNK;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
if (reparse_tag != IO_REPARSE_TAG_NFS) {
|
||||
/*
|
||||
* Clients can create reparse points with arbitrary tags, return
|
||||
* anything that is not a NFS one (or symlink) as S_IFREG.
|
||||
*/
|
||||
DBG_INFO("Unhandled NFS reparse tag: 0x%" PRIx32 "\n",
|
||||
reparse->tag);
|
||||
*type = S_IFREG;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
reparse = talloc_zero(talloc_tos(), struct reparse_data_buffer);
|
||||
if (reparse == NULL) {
|
||||
DBG_ERR("talloc_zero() failed\n");
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = reparse_data_buffer_parse(reparse, reparse, data, len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(reparse);
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (reparse->parsed.nfs.type) {
|
||||
case NFS_SPECFILE_CHR:
|
||||
*type = S_IFCHR;
|
||||
break;
|
||||
case NFS_SPECFILE_BLK:
|
||||
*type = S_IFBLK;
|
||||
break;
|
||||
case NFS_SPECFILE_FIFO:
|
||||
*type = S_IFIFO;
|
||||
break;
|
||||
case NFS_SPECFILE_SOCK:
|
||||
*type = S_IFSOCK;
|
||||
break;
|
||||
default:
|
||||
DBG_ERR("Unhandled NFS reparse type: 0x%" PRIx64 "\n",
|
||||
reparse->parsed.nfs.type);
|
||||
TALLOC_FREE(reparse);
|
||||
return NT_STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||
}
|
||||
|
||||
TALLOC_FREE(reparse);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS smb3_file_posix_information_init(
|
||||
connection_struct *conn,
|
||||
const struct stat_ex *st,
|
||||
uint32_t reparse_tag,
|
||||
const struct smb_filename *smb_fname,
|
||||
uint32_t dos_attributes,
|
||||
struct smb3_file_posix_information *dst)
|
||||
{
|
||||
const struct stat_ex *st = &smb_fname->st;
|
||||
mode_t mode = st->st_ex_mode;
|
||||
uint32_t reparse_tag = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
case S_IFDIR:
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* All non-directory or regular files are reported
|
||||
* as reparse points. Client may or may not be able
|
||||
* to access these. This should already be set by
|
||||
* fdos_mode(), assert this.
|
||||
*/
|
||||
SMB_ASSERT(dos_attributes & FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dos_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
uint8_t *reparse_data = NULL;
|
||||
uint32_t reparse_len;
|
||||
mode_t type = S_IFREG;
|
||||
|
||||
status = fsctl_get_reparse_point(smb_fname->fsp,
|
||||
talloc_tos(),
|
||||
&reparse_tag,
|
||||
&reparse_data,
|
||||
UINT32_MAX,
|
||||
&reparse_len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("Could not get reparse point for %s: %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
status = reparse_buffer_parse_posix_type(reparse_tag,
|
||||
reparse_data,
|
||||
reparse_len,
|
||||
&type);
|
||||
TALLOC_FREE(reparse_data);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("Could not parse reparse data for %s: %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the type info we got via stat() and use what
|
||||
* we got from the reparse point.
|
||||
*/
|
||||
mode &= ~S_IFMT;
|
||||
mode |= type;
|
||||
}
|
||||
|
||||
*dst = (struct smb3_file_posix_information) {
|
||||
.end_of_file = get_file_size_stat(st),
|
||||
.allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,st),
|
||||
@ -40,9 +158,10 @@ void smb3_file_posix_information_init(
|
||||
.last_access_time = unix_timespec_to_nt_time(st->st_ex_atime),
|
||||
.last_write_time = unix_timespec_to_nt_time(st->st_ex_mtime),
|
||||
.change_time = unix_timespec_to_nt_time(st->st_ex_ctime),
|
||||
.file_attributes = dos_attributes,
|
||||
.cc.nlinks = st->st_ex_nlink,
|
||||
.cc.reparse_tag = reparse_tag,
|
||||
.cc.posix_mode = unix_mode_to_wire(st->st_ex_mode),
|
||||
.cc.posix_mode = unix_mode_to_wire(mode),
|
||||
.cc.owner = global_sid_NULL,
|
||||
.cc.group = global_sid_NULL,
|
||||
};
|
||||
@ -53,21 +172,5 @@ void smb3_file_posix_information_init(
|
||||
if (st->st_ex_gid != (uid_t)-1) {
|
||||
gid_to_sid(&dst->cc.group, st->st_ex_gid);
|
||||
}
|
||||
|
||||
switch (st->st_ex_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
dst->file_attributes = dos_attributes;
|
||||
break;
|
||||
case S_IFDIR:
|
||||
dst->file_attributes = dos_attributes | FILE_ATTRIBUTE_DIRECTORY;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* All non-directory or regular files are reported
|
||||
* as reparse points. Client may or may not be able
|
||||
* to access these.
|
||||
*/
|
||||
dst->file_attributes = FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
break;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_LEVEL);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->info_level = SMB2_FILE_POSIX_INFORMATION;
|
||||
state->info_level = FSCC_FILE_POSIX_INFORMATION;
|
||||
break;
|
||||
default:
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_INFO_CLASS);
|
||||
|
@ -1680,7 +1680,7 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
|
||||
|
||||
/* SMB2 UNIX Extension. */
|
||||
|
||||
case SMB2_FILE_POSIX_INFORMATION:
|
||||
case FSCC_FILE_POSIX_INFORMATION:
|
||||
{
|
||||
struct smb3_file_posix_information info = {};
|
||||
uint8_t buf[sizeof(info)];
|
||||
@ -1690,9 +1690,8 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
|
||||
.fixed_buf_size = true,
|
||||
};
|
||||
enum ndr_err_code ndr_err;
|
||||
uint32_t tag = 0;
|
||||
|
||||
DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
|
||||
DBG_DEBUG("FSCC_FILE_POSIX_INFORMATION\n");
|
||||
|
||||
p+= 4;
|
||||
SIVAL(p,0,reskey); p+= 4;
|
||||
@ -1701,21 +1700,12 @@ static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
}
|
||||
|
||||
if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
status = fsctl_get_reparse_tag(smb_fname->fsp,
|
||||
&tag);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("Could not get reparse "
|
||||
"tag for %s: %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
nt_errstr(status));
|
||||
return status;
|
||||
}
|
||||
status = smb3_file_posix_information_init(
|
||||
conn, smb_fname, mode, &info);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
smb3_file_posix_information_init(
|
||||
conn, &smb_fname->st, tag, mode, &info);
|
||||
|
||||
ndr_err = ndr_push_smb3_file_posix_information(
|
||||
&ndr, NDR_SCALARS|NDR_BUFFERS, &info);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
@ -1960,7 +1950,7 @@ static bool fsinfo_unix_valid_level(connection_struct *conn,
|
||||
{
|
||||
if (conn_using_smb2(conn->sconn) &&
|
||||
fsp->fsp_flags.posix_open &&
|
||||
info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
|
||||
info_level == FSCC_FS_POSIX_INFORMATION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -2473,7 +2463,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
|
||||
#endif
|
||||
|
||||
case SMB_QUERY_POSIX_FS_INFO:
|
||||
case SMB2_FS_POSIX_INFORMATION_INTERNAL:
|
||||
case FSCC_FS_POSIX_INFORMATION:
|
||||
{
|
||||
int rc;
|
||||
struct vfs_statvfs_struct svfs;
|
||||
@ -3648,7 +3638,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
|
||||
/*
|
||||
* SMB2 UNIX Extensions.
|
||||
*/
|
||||
case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
|
||||
case FSCC_FILE_POSIX_INFORMATION:
|
||||
{
|
||||
struct smb3_file_posix_information info = {};
|
||||
uint8_t buf[sizeof(info)];
|
||||
@ -3669,8 +3659,11 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
}
|
||||
|
||||
smb3_file_posix_information_init(
|
||||
conn, &smb_fname->st, 0, mode, &info);
|
||||
status = smb3_file_posix_information_init(
|
||||
conn, smb_fname, mode, &info);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
ndr_err = ndr_push_smb3_file_posix_information(
|
||||
&ndr, NDR_SCALARS|NDR_BUFFERS, &info);
|
||||
|
Loading…
x
Reference in New Issue
Block a user