Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lts-team/packages/samba
  • thctlo/samba-lintianfix
  • arnaudr/samba
  • jrwren/samba
  • paride/samba
  • athos/samba
  • henrich/samba
  • cnotin/samba
  • mimi89999/samba
  • samba-team/samba
  • ahasenack/samba
  • jrtc27/samba
  • noel/samba
13 results
Show changes
Commits on Source (42)
Showing
with 434 additions and 106 deletions
......@@ -27,7 +27,7 @@ SAMBA_COPYRIGHT_STRING="Copyright Andrew Tridgell and the Samba Team 1992-2023"
########################################################
SAMBA_VERSION_MAJOR=4
SAMBA_VERSION_MINOR=19
SAMBA_VERSION_RELEASE=4
SAMBA_VERSION_RELEASE=5
########################################################
# If a official release has a serious bug #
......
==============================
Release Notes for Samba 4.19.5
February 19, 2024
==============================
This is the latest stable release of the Samba 4.19 release series.
Changes since 4.19.4
--------------------
o Ralph Boehme <slow@samba.org>
* BUG 13688: Windows 2016 fails to restore previous version of a file from a
shadow_copy2 snapshot.
* BUG 15549: Symlinks on AIX are broken in 4.19 (and a few version before
that).
o Bjoern Jacke <bj@sernet.de>
* BUG 12421: Fake directory create times has no effect.
o Björn Jacke <bjacke@samba.org>
* BUG 15550: ctime mixed up with mtime by smbd.
o David Mulder <dmulder@samba.org>
* BUG 15548: samba-gpupdate --rsop fails if machine is not in a site.
o Gabriel Nagy <gabriel.nagy@canonical.com>
* BUG 15557: gpupdate: The root cert import when NDES is not available is
broken.
o Andreas Schneider <asn@samba.org>
* BUG 15552: samba-gpupdate should print a useful message if cepces-submit
can't be found.
* BUG 15558: samba-gpupdate logging doesn't work.
o Jones Syue <jonessyue@qnap.com>
* BUG 15555: smbpasswd reset permissions only if not 0600.
#######################################
Reporting bugs & Development Discussion
#######################################
Please discuss this release on the samba-technical mailing list or by
joining the #samba-technical:matrix.org matrix room, or
#samba-technical IRC channel on irc.libera.chat.
If you do report problems then please try to send high quality
feedback. If you don't provide vital information to help us track down
the problem then you will probably be ignored. All bug reports should
be filed under the Samba 4.1 and newer product in the project's Bugzilla
database (https://bugzilla.samba.org/).
======================================================================
== Our Code, Our Bugs, Our Responsibility.
== The Samba Team
======================================================================
Release notes for older releases follow:
----------------------------------------
==============================
Release Notes for Samba 4.19.4
January 08, 2024
......@@ -78,8 +141,7 @@ database (https://bugzilla.samba.org/).
======================================================================
Release notes for older releases follow:
----------------------------------------
----------------------------------------------------------------------
==============================
Release Notes for Samba 4.19.3
November 27, 2023
......
......@@ -1450,7 +1450,7 @@ struct timespec get_ctimespec(const struct stat *pst)
{
struct timespec ret;
ret.tv_sec = pst->st_mtime;
ret.tv_sec = pst->st_ctime;
ret.tv_nsec = get_ctimensec(pst);
return ret;
}
......
......@@ -45,10 +45,12 @@ cert_wrap = b"""
-----BEGIN CERTIFICATE-----
%s
-----END CERTIFICATE-----"""
global_trust_dir = '/etc/pki/trust/anchors'
endpoint_re = '(https|HTTPS)://(?P<server>[a-zA-Z0-9.-]+)/ADPolicyProvider' + \
'_CEP_(?P<auth>[a-zA-Z]+)/service.svc/CEP'
global_trust_dirs = ['/etc/pki/trust/anchors', # SUSE
'/etc/pki/ca-trust/source/anchors', # RHEL/Fedora
'/usr/local/share/ca-certificates'] # Debian/Ubuntu
def octet_string_to_objectGUID(data):
"""Convert an octet string to an objectGUID."""
......@@ -156,7 +158,7 @@ def fetch_certification_authorities(ldb):
for es in res:
data = { 'name': get_string(es['cn'][0]),
'hostname': get_string(es['dNSHostName'][0]),
'cACertificate': get_string(es['cACertificate'][0])
'cACertificate': get_string(base64.b64encode(es['cACertificate'][0]))
}
result.append(data)
return result
......@@ -174,8 +176,7 @@ def fetch_template_attrs(ldb, name, attrs=None):
return {'msPKI-Minimal-Key-Size': ['2048']}
def format_root_cert(cert):
cert = base64.b64encode(cert.encode())
return cert_wrap % re.sub(b"(.{64})", b"\\1\n", cert, 0, re.DOTALL)
return cert_wrap % re.sub(b"(.{64})", b"\\1\n", cert.encode(), 0, re.DOTALL)
def find_cepces_submit():
certmonger_dirs = [os.environ.get("PATH"), '/usr/lib/certmonger',
......@@ -184,17 +185,19 @@ def find_cepces_submit():
def get_supported_templates(server):
cepces_submit = find_cepces_submit()
if os.path.exists(cepces_submit):
env = os.environ
env['CERTMONGER_OPERATION'] = 'GET-SUPPORTED-TEMPLATES'
p = Popen([cepces_submit, '--server=%s' % server, '--auth=Kerberos'],
env=env, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
if p.returncode != 0:
data = { 'Error': err.decode() }
log.error('Failed to fetch the list of supported templates.', data)
return out.strip().split()
return []
if not cepces_submit or not os.path.exists(cepces_submit):
log.error('Failed to find cepces-submit')
return []
env = os.environ
env['CERTMONGER_OPERATION'] = 'GET-SUPPORTED-TEMPLATES'
p = Popen([cepces_submit, '--server=%s' % server, '--auth=Kerberos'],
env=env, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
if p.returncode != 0:
data = {'Error': err.decode()}
log.error('Failed to fetch the list of supported templates.', data)
return out.strip().split()
def getca(ca, url, trust_dir):
......@@ -214,10 +217,11 @@ def getca(ca, url, trust_dir):
' installed or not configured.')
if 'cACertificate' in ca:
log.warn('Installing the server certificate only.')
der_certificate = base64.b64decode(ca['cACertificate'])
try:
cert = load_der_x509_certificate(ca['cACertificate'])
cert = load_der_x509_certificate(der_certificate)
except TypeError:
cert = load_der_x509_certificate(ca['cACertificate'],
cert = load_der_x509_certificate(der_certificate,
default_backend())
cert_data = cert.public_bytes(Encoding.PEM)
with open(root_cert, 'wb') as w:
......@@ -239,7 +243,8 @@ def getca(ca, url, trust_dir):
certs = load_der_pkcs7_certificates(r.content)
for i in range(0, len(certs)):
cert = certs[i].public_bytes(Encoding.PEM)
dest = '%s.%d' % (root_cert, i)
filename, extension = root_cert.rsplit('.', 1)
dest = '%s.%d.%s' % (filename, i, extension)
with open(dest, 'wb') as w:
w.write(cert)
root_certs.append(dest)
......@@ -249,12 +254,29 @@ def getca(ca, url, trust_dir):
return root_certs
def find_global_trust_dir():
"""Return the global trust dir using known paths from various Linux distros."""
for trust_dir in global_trust_dirs:
if os.path.isdir(trust_dir):
return trust_dir
return global_trust_dirs[0]
def update_ca_command():
"""Return the command to update the CA trust store."""
return which('update-ca-certificates') or which('update-ca-trust')
def changed(new_data, old_data):
"""Return True if any key present in both dicts has changed."""
return any((new_data[k] != old_data[k] if k in old_data else False) \
for k in new_data.keys())
def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
"""Install the root certificate chain."""
data = dict({'files': [], 'templates': []}, **ca)
url = 'http://%s/CertSrv/mscep/mscep.dll/pkiclient.exe?' % ca['hostname']
root_certs = getca(ca, url, trust_dir)
data['files'].extend(root_certs)
global_trust_dir = find_global_trust_dir()
for src in root_certs:
# Symlink the certs to global trust dir
dst = os.path.join(global_trust_dir, os.path.basename(src))
......@@ -273,7 +295,7 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
# already exists. Ignore the FileExistsError. Preserve the
# existing symlink in the unapply data.
data['files'].append(dst)
update = which('update-ca-certificates')
update = update_ca_command()
if update is not None:
Popen([update]).wait()
# Setup Certificate Auto Enrollment
......@@ -316,7 +338,7 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier):
def __str__(self):
return 'Cryptography\AutoEnrollment'
return r'Cryptography\AutoEnrollment'
def unapply(self, guid, attribute, value):
ca_cn = base64.b64decode(attribute)
......@@ -337,12 +359,13 @@ class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier):
# If the policy has changed, unapply, then apply new policy
old_val = self.cache_get_attribute_value(guid, attribute)
old_data = json.loads(old_val) if old_val is not None else {}
if all([(ca[k] == old_data[k] if k in old_data else False) \
for k in ca.keys()]) or \
self.cache_get_apply_state() == GPOSTATE.ENFORCE:
templates = ['%s.%s' % (ca['name'], t.decode()) for t in get_supported_templates(ca['hostname'])] \
if old_val is not None else []
new_data = { 'templates': templates, **ca }
if changed(new_data, old_data) or self.cache_get_apply_state() == GPOSTATE.ENFORCE:
self.unapply(guid, attribute, old_val)
# If policy is already applied, skip application
if old_val is not None and \
# If policy is already applied and unchanged, skip application
if old_val is not None and not changed(new_data, old_data) and \
self.cache_get_apply_state() != GPOSTATE.ENFORCE:
return
......@@ -368,7 +391,7 @@ class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier):
for gpo in changed_gpo_list:
if gpo.file_sys_path:
section = 'Software\Policies\Microsoft\Cryptography\AutoEnrollment'
section = r'Software\Policies\Microsoft\Cryptography\AutoEnrollment'
pol_file = 'MACHINE/Registry.pol'
path = os.path.join(gpo.file_sys_path, pol_file)
pol_conf = self.parse(path)
......@@ -396,7 +419,7 @@ class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier):
# remove any existing policy
ca_attrs = \
self.cache_get_all_attribute_values(gpo.name)
self.clean(gpo.name, remove=ca_attrs)
self.clean(gpo.name, remove=list(ca_attrs.keys()))
def __read_cep_data(self, guid, ldb, end_point_information,
trust_dir, private_dir):
......@@ -488,7 +511,7 @@ class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier):
def rsop(self, gpo):
output = {}
pol_file = 'MACHINE/Registry.pol'
section = 'Software\Policies\Microsoft\Cryptography\AutoEnrollment'
section = r'Software\Policies\Microsoft\Cryptography\AutoEnrollment'
if gpo.file_sys_path:
path = os.path.join(gpo.file_sys_path, pol_file)
pol_conf = self.parse(path)
......
......@@ -866,19 +866,25 @@ def get_gpo_list(dc_hostname, creds, lp, username):
# (S)ite
if gpo_list_machine:
site_dn = site_dn_for_machine(samdb, dc_hostname, lp, creds, username)
try:
log.debug("get_gpo_list: query SITE: [%s] for GPOs" % site_dn)
gp_link = get_gpo_link(samdb, site_dn)
except ldb.LdbError as e:
(enum, estr) = e.args
log.debug(estr)
else:
add_gplink_to_gpo_list(samdb, gpo_list, forced_gpo_list,
site_dn, gp_link,
gpo.GP_LINK_SITE,
add_only_forced_gpos, token)
site_dn = site_dn_for_machine(samdb, dc_hostname, lp, creds, username)
try:
log.debug("get_gpo_list: query SITE: [%s] for GPOs" % site_dn)
gp_link = get_gpo_link(samdb, site_dn)
except ldb.LdbError as e:
(enum, estr) = e.args
log.debug(estr)
else:
add_gplink_to_gpo_list(samdb, gpo_list, forced_gpo_list,
site_dn, gp_link,
gpo.GP_LINK_SITE,
add_only_forced_gpos, token)
except ldb.LdbError:
# [MS-GPOL] 3.2.5.1.4 Site Search: If the method returns
# ERROR_NO_SITENAME, the remainder of this message MUST be skipped
# and the protocol sequence MUST continue at GPO Search
pass
# (L)ocal
gpo_list.insert(0, gpo.GROUP_POLICY_OBJECT("Local Policy",
......
......@@ -24,9 +24,10 @@ import gettext
import random
import sys
logger = logging.getLogger()
logger = logging.getLogger("gp")
def logger_init(name, log_level):
logger = logging.getLogger(name)
logger.addHandler(logging.StreamHandler(sys.stdout))
logger.setLevel(logging.CRITICAL)
if log_level == 1:
......
......@@ -192,7 +192,7 @@ def compile_graph_key(key_items, nodes_above=None, elisions=None,
short = short[1:]
long = long[1:]
elision_str += ('\nelision%d[shape=plaintext; style=solid; '
'label="\“%s” means “%s”\\r"]\n'
'label="\\“%s” means “%s”\\r"]\n'
% ((i, short, long)))
above_lines = []
......
......@@ -14,4 +14,5 @@ if __name__ == "__main__":
assert opts.auth == 'Kerberos'
if 'CERTMONGER_OPERATION' in os.environ and \
os.environ['CERTMONGER_OPERATION'] == 'GET-SUPPORTED-TEMPLATES':
print('Machine') # Report a Machine template
templates = os.environ.get('CEPCES_SUBMIT_SUPPORTED_TEMPLATES', 'Machine').split(',')
print('\n'.join(templates)) # Report the requested templates
This diff is collapsed.
......@@ -1806,7 +1806,7 @@ class GpoCmdTestCase(SambaToolCmdTest):
'The test cse was not enabled')
self.assertIn('UserPolicy : False', out,
'The test cse should not have User policy enabled')
cse_ext = re.findall('^UniqueGUID\s+:\s+(.*)', out)
cse_ext = re.findall(r'^UniqueGUID\s+:\s+(.*)', out)
self.assertEquals(len(cse_ext), 1,
'The test cse GUID was not found')
cse_ext = cse_ext[0]
......
......@@ -296,7 +296,7 @@ tasks = {
"samba-no-opath-build": {
"git-clone-required": True,
"sequence": [
("configure", "ADDITIONAL_CFLAGS='-DDISABLE_OPATH=1' ./configure.developer --without-ad-dc " + samba_configure_params),
("configure", "ADDITIONAL_CFLAGS='-DDISABLE_OPATH=1 -DDISABLE_VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS=1 -DDISABLE_PROC_FDS=1' ./configure.developer --without-ad-dc " + samba_configure_params),
("make", "make -j"),
("check-clean-tree", CLEAN_SOURCE_TREE_CMD),
("chmod-R-a-w", "chmod -R a-w ."),
......
......@@ -14,3 +14,7 @@
# available this works fine. So for now restrict testing posix
# extensions to environments where we have O_PATH around
^samba.tests.smb1posix
# These don't work without /proc/fd support
^samba3.blackbox.shadow_copy_torture.*\(fileserver\)
^samba3.blackbox.virus_scanner.*\(fileserver:local\)
......@@ -3437,9 +3437,7 @@ sub provision($$)
[shadow_write]
path = $shadow_tstdir
comment = previous versions snapshots under mount point
vfs objects = shadow_copy2 streams_xattr error_inject
aio write size = 0
error_inject:pwrite = EBADF
vfs objects = shadow_copy2 streams_xattr
shadow:mountpoint = $shadow_tstdir
shadow:fixinodes = yes
smbd async dosmode = yes
......
......@@ -719,6 +719,12 @@ struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
const SMB_STRUCT_STAT *psbuf,
NTTIME twrp,
uint32_t flags);
NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
const char *connectpath,
const char *dir,
const char *target,
size_t unparsed,
char **_relative);
NTSTATUS filename_convert_dirfsp(
TALLOC_CTX *ctx,
connection_struct *conn,
......
......@@ -74,11 +74,6 @@
(fsp_get_io_fd(fsp) != -1) && \
(((fsp)->fsp_flags.can_read)))
#define CHECK_WRITE(fsp) \
((fsp)->fsp_flags.can_write && \
(!(fsp)->fsp_flags.is_pathref) && \
(fsp_get_io_fd(fsp) != -1))
#define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \
NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) )
......
......@@ -186,6 +186,7 @@ static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
if (S_ISDIR(pst->st_mode) && fake_dir_create_times) {
dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */
dst->st_ex_btime.tv_nsec = 0;
return;
}
dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
......
......@@ -259,6 +259,8 @@ NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl,
files_struct *src_fsp,
files_struct *dst_fsp)
{
NTSTATUS status;
if (src_fsp->vuid != dst_fsp->vuid) {
DBG_INFO("copy chunk handles not in the same session.\n");
return NT_STATUS_ACCESS_DENIED;
......@@ -317,10 +319,11 @@ NTSTATUS vfs_offload_token_check_handles(uint32_t fsctl,
*
* A non writable dst handle also doesn't make sense for other fsctls.
*/
if (!CHECK_WRITE(dst_fsp)) {
status = check_any_access_fsp(dst_fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
if (!NT_STATUS_IS_OK(status)) {
DBG_INFO("dest handle not writable (%s).\n",
smb_fname_str_dbg(dst_fsp->fsp_name));
return NT_STATUS_ACCESS_DENIED;
return status;
}
/*
* - The Open.GrantedAccess of the destination file does not include
......
......@@ -738,10 +738,13 @@ static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
/* We got access denied here. If we're already root,
or we didn't need to do a chown, or the fsp isn't
open with WRITE_OWNER access, just return. */
if (get_current_uid(handle->conn) == 0 || !chown_needed ||
!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
if (get_current_uid(handle->conn) == 0 || !chown_needed) {
return NT_STATUS_ACCESS_DENIED;
}
status = check_any_access_fsp(fsp, SEC_STD_WRITE_OWNER);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
* Only allow take-ownership, not give-ownership. That's the way Windows
......
......@@ -52,6 +52,9 @@ static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const
bool bval;
handle->conn->have_proc_fds = sys_have_proc_fds();
#ifdef DISABLE_PROC_FDS
handle->conn->have_proc_fds = false;
#endif
/*
* assume the kernel will support openat2(),
......@@ -70,6 +73,9 @@ static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const
handle->conn->open_how_resolve |=
VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
}
#ifdef DISABLE_VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
handle->conn->open_how_resolve &= ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
#endif
return 0; /* Return >= 0 for success */
}
......
......@@ -368,11 +368,14 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
}
if (get_current_uid(handle->conn) == 0 ||
chown_needed == false ||
!(fsp->access_mask & SEC_STD_WRITE_OWNER))
chown_needed == false)
{
return NT_STATUS_ACCESS_DENIED;
}
status = check_any_access_fsp(fsp, SEC_STD_WRITE_OWNER);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
* Only allow take-ownership, not give-ownership. That's the way Windows
......