5905 lines
195 KiB
Diff
5905 lines
195 KiB
Diff
From 3c29fc78029e1274f931e171c9e04c19ad0182c1 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Thu, 17 Aug 2023 01:05:54 +0300
|
|
Subject: [PATCH 01/63] gp: Support more global trust directories
|
|
|
|
In addition to the SUSE global trust directory, add support for RHEL and
|
|
Debian-based distributions (including Ubuntu).
|
|
|
|
To determine the correct directory to use, we iterate over the variants
|
|
and stop at the first which is a directory.
|
|
|
|
In case none is found, fallback to the first option which will produce a
|
|
warning as it did previously.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit a1b285e485c0b5a8747499bdbbb9f3f4fc025b2f)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 12 +++++++++++-
|
|
1 file changed, 11 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 312c8ddf467..1b90ab46e90 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -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."""
|
|
@@ -249,12 +251,20 @@ 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 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))
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 063606e8ec83a58972df47eb561ab267f8937ba4 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Thu, 17 Aug 2023 01:09:28 +0300
|
|
Subject: [PATCH 02/63] gp: Support update-ca-trust helper
|
|
|
|
This is used on RHEL/Fedora instead of update-ca-certificates. They
|
|
behave similarly so it's enough to change the command name.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit fa80d1d86439749c44e60cf9075e84dc9ed3c268)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 6 +++++-
|
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 1b90ab46e90..cefdafa21b2 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -258,6 +258,10 @@ def find_global_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 cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
"""Install the root certificate chain."""
|
|
data = dict({'files': [], 'templates': []}, **ca)
|
|
@@ -283,7 +287,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
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 3b548bf280ca59ef12a7af10a9131813067a850a Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Fri, 11 Aug 2023 18:46:42 +0300
|
|
Subject: [PATCH 03/63] gp: Change root cert extension suffix
|
|
|
|
On Ubuntu, certificates must end in '.crt' in order to be considered by
|
|
the `update-ca-certificates` helper.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit bce3a89204545dcab5fb39a712590f6e166f997b)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index cefdafa21b2..c562722906b 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -241,7 +241,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)
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7592ed5032836dc43f657f66607a0a4661edcdb4 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Fri, 18 Aug 2023 17:06:43 +0300
|
|
Subject: [PATCH 04/63] gp: Test with binary content for certificate data
|
|
|
|
This fails all GPO-related tests that call `gpupdate --rsop`.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit 1ef722cf66f9ec99f52939f1cfca031c5fe1ad70)
|
|
---
|
|
python/samba/tests/gpo.py | 8 ++++----
|
|
selftest/knownfail.d/gpo | 13 +++++++++++++
|
|
2 files changed, 17 insertions(+), 4 deletions(-)
|
|
create mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
|
|
index e4b75cc62a4..963f873f755 100644
|
|
--- a/python/samba/tests/gpo.py
|
|
+++ b/python/samba/tests/gpo.py
|
|
@@ -6783,14 +6783,14 @@ class GPOTests(tests.TestCase):
|
|
ldb.add({'dn': certa_dn,
|
|
'objectClass': 'certificationAuthority',
|
|
'authorityRevocationList': ['XXX'],
|
|
- 'cACertificate': 'XXX',
|
|
+ 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I',
|
|
'certificateRevocationList': ['XXX'],
|
|
})
|
|
# Write the dummy pKIEnrollmentService
|
|
enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn)
|
|
ldb.add({'dn': enroll_dn,
|
|
'objectClass': 'pKIEnrollmentService',
|
|
- 'cACertificate': 'XXXX',
|
|
+ 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I',
|
|
'certificateTemplates': ['Machine'],
|
|
'dNSHostName': hostname,
|
|
})
|
|
@@ -7201,14 +7201,14 @@ class GPOTests(tests.TestCase):
|
|
ldb.add({'dn': certa_dn,
|
|
'objectClass': 'certificationAuthority',
|
|
'authorityRevocationList': ['XXX'],
|
|
- 'cACertificate': 'XXX',
|
|
+ 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I',
|
|
'certificateRevocationList': ['XXX'],
|
|
})
|
|
# Write the dummy pKIEnrollmentService
|
|
enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn)
|
|
ldb.add({'dn': enroll_dn,
|
|
'objectClass': 'pKIEnrollmentService',
|
|
- 'cACertificate': 'XXXX',
|
|
+ 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I',
|
|
'certificateTemplates': ['Machine'],
|
|
'dNSHostName': hostname,
|
|
})
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
new file mode 100644
|
|
index 00000000000..0aad59607c2
|
|
--- /dev/null
|
|
+++ b/selftest/knownfail.d/gpo
|
|
@@ -0,0 +1,13 @@
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_centrify_crontab_ext
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_scripts_ext
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_rsop
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_access
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_files
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_issue
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_motd
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_openssh
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_startup_scripts
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_sudoers
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_symlink
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_advanced_gp_cert_auto_enroll_ext
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7f7b235bda9e85c5ea330e52e734d1113a884571 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Wed, 16 Aug 2023 12:20:11 +0300
|
|
Subject: [PATCH 05/63] gp: Convert CA certificates to base64
|
|
|
|
I don't know whether this applies universally, but in our case the
|
|
contents of `es['cACertificate'][0]` are binary, so cleanly converting
|
|
to a string fails with the following:
|
|
|
|
'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte
|
|
|
|
We found a fix to be encoding the certificate to base64 when
|
|
constructing the CA list.
|
|
|
|
Section 4.4.5.2 of MS-CAESO also suggests that the content of
|
|
`cACertificate` is binary (OCTET string).
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit 157335ee93eb866f9b6a47486a5668d6e76aced5)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 5 ++---
|
|
selftest/knownfail.d/gpo | 13 -------------
|
|
2 files changed, 2 insertions(+), 16 deletions(-)
|
|
delete mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index c562722906b..c8b5368c16a 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -158,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
|
|
@@ -176,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',
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
deleted file mode 100644
|
|
index 0aad59607c2..00000000000
|
|
--- a/selftest/knownfail.d/gpo
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_centrify_crontab_ext
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_scripts_ext
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_rsop
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_access
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_files
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_issue
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_motd
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_openssh
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_startup_scripts
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_sudoers
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_vgp_symlink
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_advanced_gp_cert_auto_enroll_ext
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 49cc74015a603e80048a38fe635cd1ac28938ee4 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Fri, 18 Aug 2023 17:16:23 +0300
|
|
Subject: [PATCH 06/63] gp: Test adding new cert templates enforces changes
|
|
|
|
Ensure that cepces-submit reporting additional templates and re-applying
|
|
will enforce the updated policy.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit 2d6943a864405f324c467e8c3464c31ac08457b0)
|
|
---
|
|
python/samba/tests/bin/cepces-submit | 3 +-
|
|
python/samba/tests/gpo.py | 48 ++++++++++++++++++++++++++++
|
|
selftest/knownfail.d/gpo | 2 ++
|
|
3 files changed, 52 insertions(+), 1 deletion(-)
|
|
create mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/tests/bin/cepces-submit b/python/samba/tests/bin/cepces-submit
|
|
index 668682a9f58..de63164692b 100755
|
|
--- a/python/samba/tests/bin/cepces-submit
|
|
+++ b/python/samba/tests/bin/cepces-submit
|
|
@@ -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
|
|
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
|
|
index 963f873f755..e75c411bde7 100644
|
|
--- a/python/samba/tests/gpo.py
|
|
+++ b/python/samba/tests/gpo.py
|
|
@@ -6812,6 +6812,23 @@ class GPOTests(tests.TestCase):
|
|
self.assertTrue(os.path.exists(machine_crt),
|
|
'Machine key was not generated')
|
|
|
|
+ # Subsequent apply should react to new certificate templates
|
|
+ os.environ['CEPCES_SUBMIT_SUPPORTED_TEMPLATES'] = 'Machine,Workstation'
|
|
+ self.addCleanup(os.environ.pop, 'CEPCES_SUBMIT_SUPPORTED_TEMPLATES')
|
|
+ ext.process_group_policy([], gpos, dname, dname)
|
|
+ self.assertTrue(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine key was not generated')
|
|
+ workstation_crt = os.path.join(dname, '%s.Workstation.crt' % ca_cn)
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not requested')
|
|
+ workstation_key = os.path.join(dname, '%s.Workstation.key' % ca_cn)
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not generated')
|
|
+
|
|
# Verify RSOP does not fail
|
|
ext.rsop([g for g in gpos if g.name == guid][0])
|
|
|
|
@@ -6829,11 +6846,17 @@ class GPOTests(tests.TestCase):
|
|
'Machine certificate was not removed')
|
|
self.assertFalse(os.path.exists(machine_crt),
|
|
'Machine key was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not removed')
|
|
out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate()
|
|
self.assertNotIn(get_bytes(ca_cn), out, 'CA was not removed')
|
|
out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate()
|
|
self.assertNotIn(b'Machine', out,
|
|
'Machine certificate not removed')
|
|
+ self.assertNotIn(b'Workstation', out,
|
|
+ 'Workstation certificate not removed')
|
|
|
|
# Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate
|
|
ldb.delete(certa_dn)
|
|
@@ -7233,6 +7256,25 @@ class GPOTests(tests.TestCase):
|
|
self.assertTrue(os.path.exists(machine_crt),
|
|
'Machine key was not generated')
|
|
|
|
+ # Subsequent apply should react to new certificate templates
|
|
+ os.environ['CEPCES_SUBMIT_SUPPORTED_TEMPLATES'] = 'Machine,Workstation'
|
|
+ self.addCleanup(os.environ.pop, 'CEPCES_SUBMIT_SUPPORTED_TEMPLATES')
|
|
+ ext.process_group_policy([], gpos, dname, dname)
|
|
+ for ca in ca_list:
|
|
+ self.assertTrue(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine key was not generated')
|
|
+
|
|
+ workstation_crt = os.path.join(dname, '%s.Workstation.crt' % ca)
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not requested')
|
|
+ workstation_key = os.path.join(dname, '%s.Workstation.key' % ca)
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not generated')
|
|
+
|
|
# Verify RSOP does not fail
|
|
ext.rsop([g for g in gpos if g.name == guid][0])
|
|
|
|
@@ -7250,12 +7292,18 @@ class GPOTests(tests.TestCase):
|
|
'Machine certificate was not removed')
|
|
self.assertFalse(os.path.exists(machine_crt),
|
|
'Machine key was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not removed')
|
|
out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate()
|
|
for ca in ca_list:
|
|
self.assertNotIn(get_bytes(ca), out, 'CA was not removed')
|
|
out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate()
|
|
self.assertNotIn(b'Machine', out,
|
|
'Machine certificate not removed')
|
|
+ self.assertNotIn(b'Workstation', out,
|
|
+ 'Workstation certificate not removed')
|
|
|
|
# Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate
|
|
ldb.delete(certa_dn)
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
new file mode 100644
|
|
index 00000000000..4edc1dce730
|
|
--- /dev/null
|
|
+++ b/selftest/knownfail.d/gpo
|
|
@@ -0,0 +1,2 @@
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_advanced_gp_cert_auto_enroll_ext
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 4c0906bd79f030e591701234bc54bc749a42d686 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Wed, 16 Aug 2023 12:37:17 +0300
|
|
Subject: [PATCH 07/63] gp: Template changes should invalidate cache
|
|
|
|
If certificate templates are added or removed, the autoenroll extension
|
|
should react to this and reapply the policy. Previously this wasn't
|
|
taken into account.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit 2a6ae997f2464b12b72b5314fa80d9784fb0f6c1)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 15 ++++++++++-----
|
|
selftest/knownfail.d/gpo | 2 --
|
|
2 files changed, 10 insertions(+), 7 deletions(-)
|
|
delete mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index c8b5368c16a..8233713e8ad 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -262,6 +262,11 @@ 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)
|
|
@@ -351,12 +356,12 @@ 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'])]
|
|
+ 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
|
|
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
deleted file mode 100644
|
|
index 4edc1dce730..00000000000
|
|
--- a/selftest/knownfail.d/gpo
|
|
+++ /dev/null
|
|
@@ -1,2 +0,0 @@
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_advanced_gp_cert_auto_enroll_ext
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e61f30dc2518d5a1c239f090baea4a309307f3f8 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Fri, 18 Aug 2023 17:26:59 +0300
|
|
Subject: [PATCH 08/63] gp: Test disabled enrollment unapplies policy
|
|
|
|
For this we need to stage a Registry.pol file with certificate
|
|
autoenrollment enabled, but with checkboxes unticked.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit ee814f7707a8ddef2657212cd6d31799501b7bb3)
|
|
---
|
|
python/samba/tests/gpo.py | 54 +++++++++++++++++++++++++++++++++++++++
|
|
selftest/knownfail.d/gpo | 1 +
|
|
2 files changed, 55 insertions(+)
|
|
create mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
|
|
index e75c411bde7..580f3568de8 100644
|
|
--- a/python/samba/tests/gpo.py
|
|
+++ b/python/samba/tests/gpo.py
|
|
@@ -281,6 +281,28 @@ b"""
|
|
</PolFile>
|
|
"""
|
|
|
|
+auto_enroll_unchecked_reg_pol = \
|
|
+b"""
|
|
+<?xml version="1.0" encoding="utf-8"?>
|
|
+<PolFile num_entries="3" signature="PReg" version="1">
|
|
+ <Entry type="4" type_name="REG_DWORD">
|
|
+ <Key>Software\Policies\Microsoft\Cryptography\AutoEnrollment</Key>
|
|
+ <ValueName>AEPolicy</ValueName>
|
|
+ <Value>0</Value>
|
|
+ </Entry>
|
|
+ <Entry type="4" type_name="REG_DWORD">
|
|
+ <Key>Software\Policies\Microsoft\Cryptography\AutoEnrollment</Key>
|
|
+ <ValueName>OfflineExpirationPercent</ValueName>
|
|
+ <Value>10</Value>
|
|
+ </Entry>
|
|
+ <Entry type="1" type_name="REG_SZ">
|
|
+ <Key>Software\Policies\Microsoft\Cryptography\AutoEnrollment</Key>
|
|
+ <ValueName>OfflineExpirationStoreNames</ValueName>
|
|
+ <Value>MY</Value>
|
|
+ </Entry>
|
|
+</PolFile>
|
|
+"""
|
|
+
|
|
advanced_enroll_reg_pol = \
|
|
b"""
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
@@ -6836,6 +6858,38 @@ class GPOTests(tests.TestCase):
|
|
ret = rsop(self.lp)
|
|
self.assertEqual(ret, 0, 'gpupdate --rsop failed!')
|
|
|
|
+ # Remove policy by staging pol file with auto-enroll unchecked
|
|
+ parser.load_xml(etree.fromstring(auto_enroll_unchecked_reg_pol.strip()))
|
|
+ ret = stage_file(reg_pol, ndr_pack(parser.pol_file))
|
|
+ self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
|
|
+ ext.process_group_policy([], gpos, dname, dname)
|
|
+ self.assertFalse(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(machine_crt),
|
|
+ 'Machine key was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not removed')
|
|
+
|
|
+ # Reapply policy by staging the enabled pol file
|
|
+ parser.load_xml(etree.fromstring(auto_enroll_reg_pol.strip()))
|
|
+ ret = stage_file(reg_pol, ndr_pack(parser.pol_file))
|
|
+ self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
|
|
+ ext.process_group_policy([], gpos, dname, dname)
|
|
+ self.assertTrue(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine key was not generated')
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation certificate was not requested')
|
|
+ self.assertTrue(os.path.exists(workstation_crt),
|
|
+ 'Workstation key was not generated')
|
|
+
|
|
# Remove policy
|
|
gp_db = store.get_gplog(machine_creds.get_username())
|
|
del_gpos = get_deleted_gpos_list(gp_db, [])
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
new file mode 100644
|
|
index 00000000000..83bc9f0ac1f
|
|
--- /dev/null
|
|
+++ b/selftest/knownfail.d/gpo
|
|
@@ -0,0 +1 @@
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7757b9b48546d71e19798d1260da97780caa99c3 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Wed, 16 Aug 2023 12:33:59 +0300
|
|
Subject: [PATCH 09/63] gp: Send list of keys instead of dict to remove
|
|
|
|
`cache_get_all_attribute_values` returns a dict whereas we need to pass
|
|
a list of keys to `remove`. These will be interpolated in the gpdb search.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
|
|
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
|
|
Autobuild-Date(master): Mon Aug 28 03:01:22 UTC 2023 on atb-devel-224
|
|
|
|
(cherry picked from commit 7dc181757c76b881ceaf1915ebb0bfbcf5aca83a)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 2 +-
|
|
selftest/knownfail.d/gpo | 1 -
|
|
2 files changed, 1 insertion(+), 2 deletions(-)
|
|
delete mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 8233713e8ad..64c35782ae8 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -415,7 +415,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):
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
deleted file mode 100644
|
|
index 83bc9f0ac1f..00000000000
|
|
--- a/selftest/knownfail.d/gpo
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 4e9b2e6409c5764ec0e66cc6c90b08e70f702e7c Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Tue, 9 Jan 2024 08:50:01 +0100
|
|
Subject: [PATCH 10/63] python:gp: Print a nice message if cepces-submit can't
|
|
be found
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15552
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
(cherry picked from commit 8eb42425a8eb1b30ca0e94dfc01d8175ae5cde4b)
|
|
|
|
Autobuild-User(v4-19-test): Jule Anger <janger@samba.org>
|
|
Autobuild-Date(v4-19-test): Mon Jan 15 11:11:31 UTC 2024 on atb-devel-224
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 24 ++++++++++++----------
|
|
1 file changed, 13 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 64c35782ae8..08d1a7348cd 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -185,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):
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From fb3aefff51c02cf8ba3f8dfeb7d3f971e8d4902a Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Mon, 8 Jan 2024 18:05:08 +0200
|
|
Subject: [PATCH 11/63] gpo: Test certificate policy without NDES
|
|
|
|
As of 8231eaf856b, the NDES feature is no longer required on Windows, as
|
|
cert auto-enroll can use the certificate from the LDAP request.
|
|
|
|
However, 157335ee93e changed the implementation to convert the LDAP
|
|
certificate to base64 due to it failing to cleanly convert to a string.
|
|
|
|
Because of insufficient test coverage I missed handling the part where
|
|
NDES is disabled or not reachable and the LDAP certificate was imported.
|
|
The call to load_der_x509_certificate now fails with an error because it
|
|
expects binary data, yet it receives a base64 encoded string.
|
|
|
|
This adds a test to confirm the issue.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15557
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit 0d1ff69936f18ea729fc11fbbb1569a833302572)
|
|
---
|
|
python/samba/tests/gpo.py | 126 ++++++++++++++++++++++++++++++++++++--
|
|
selftest/knownfail.d/gpo | 1 +
|
|
2 files changed, 121 insertions(+), 6 deletions(-)
|
|
create mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
|
|
index 580f3568de8..a78af17dba4 100644
|
|
--- a/python/samba/tests/gpo.py
|
|
+++ b/python/samba/tests/gpo.py
|
|
@@ -102,17 +102,21 @@ def dummy_certificate():
|
|
|
|
# Dummy requests structure for Certificate Auto Enrollment
|
|
class dummy_requests(object):
|
|
- @staticmethod
|
|
- def get(url=None, params=None):
|
|
+ class exceptions(object):
|
|
+ ConnectionError = Exception
|
|
+
|
|
+ def __init__(self, want_exception=False):
|
|
+ self.want_exception = want_exception
|
|
+
|
|
+ def get(self, url=None, params=None):
|
|
+ if self.want_exception:
|
|
+ raise self.exceptions.ConnectionError
|
|
+
|
|
dummy = requests.Response()
|
|
dummy._content = dummy_certificate()
|
|
dummy.headers = {'Content-Type': 'application/x-x509-ca-cert'}
|
|
return dummy
|
|
|
|
- class exceptions(object):
|
|
- ConnectionError = Exception
|
|
-cae.requests = dummy_requests
|
|
-
|
|
realm = os.environ.get('REALM')
|
|
policies = realm + '/POLICIES'
|
|
realm = realm.lower()
|
|
@@ -6764,6 +6768,114 @@ class GPOTests(tests.TestCase):
|
|
# Unstage the Registry.pol file
|
|
unstage_file(reg_pol)
|
|
|
|
+ def test_gp_cert_auto_enroll_ext_without_ndes(self):
|
|
+ local_path = self.lp.cache_path('gpo_cache')
|
|
+ guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
|
|
+ reg_pol = os.path.join(local_path, policies, guid,
|
|
+ 'MACHINE/REGISTRY.POL')
|
|
+ cache_dir = self.lp.get('cache directory')
|
|
+ store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
|
|
+
|
|
+ machine_creds = Credentials()
|
|
+ machine_creds.guess(self.lp)
|
|
+ machine_creds.set_machine_account()
|
|
+
|
|
+ # Initialize the group policy extension
|
|
+ cae.requests = dummy_requests(want_exception=True)
|
|
+ ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds,
|
|
+ machine_creds.get_username(), store)
|
|
+
|
|
+ gpos = get_gpo_list(self.server, machine_creds, self.lp,
|
|
+ machine_creds.get_username())
|
|
+
|
|
+ # Stage the Registry.pol file with test data
|
|
+ parser = GPPolParser()
|
|
+ parser.load_xml(etree.fromstring(auto_enroll_reg_pol.strip()))
|
|
+ ret = stage_file(reg_pol, ndr_pack(parser.pol_file))
|
|
+ self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
|
|
+
|
|
+ # Write the dummy CA entry, Enrollment Services, and Templates Entries
|
|
+ admin_creds = Credentials()
|
|
+ admin_creds.set_username(os.environ.get('DC_USERNAME'))
|
|
+ admin_creds.set_password(os.environ.get('DC_PASSWORD'))
|
|
+ admin_creds.set_realm(os.environ.get('REALM'))
|
|
+ hostname = get_dc_hostname(machine_creds, self.lp)
|
|
+ url = 'ldap://%s' % hostname
|
|
+ ldb = Ldb(url=url, session_info=system_session(),
|
|
+ lp=self.lp, credentials=admin_creds)
|
|
+ # Write the dummy CA
|
|
+ confdn = 'CN=Public Key Services,CN=Services,CN=Configuration,%s' % base_dn
|
|
+ ca_cn = '%s-CA' % hostname.replace('.', '-')
|
|
+ certa_dn = 'CN=%s,CN=Certification Authorities,%s' % (ca_cn, confdn)
|
|
+ ldb.add({'dn': certa_dn,
|
|
+ 'objectClass': 'certificationAuthority',
|
|
+ 'authorityRevocationList': ['XXX'],
|
|
+ 'cACertificate': dummy_certificate(),
|
|
+ 'certificateRevocationList': ['XXX'],
|
|
+ })
|
|
+ # Write the dummy pKIEnrollmentService
|
|
+ enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn)
|
|
+ ldb.add({'dn': enroll_dn,
|
|
+ 'objectClass': 'pKIEnrollmentService',
|
|
+ 'cACertificate': dummy_certificate(),
|
|
+ 'certificateTemplates': ['Machine'],
|
|
+ 'dNSHostName': hostname,
|
|
+ })
|
|
+ # Write the dummy pKICertificateTemplate
|
|
+ template_dn = 'CN=Machine,CN=Certificate Templates,%s' % confdn
|
|
+ ldb.add({'dn': template_dn,
|
|
+ 'objectClass': 'pKICertificateTemplate',
|
|
+ })
|
|
+
|
|
+ with TemporaryDirectory() as dname:
|
|
+ try:
|
|
+ ext.process_group_policy([], gpos, dname, dname)
|
|
+ except Exception as e:
|
|
+ self.fail(str(e))
|
|
+
|
|
+ ca_crt = os.path.join(dname, '%s.crt' % ca_cn)
|
|
+ self.assertTrue(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not requested')
|
|
+ machine_crt = os.path.join(dname, '%s.Machine.crt' % ca_cn)
|
|
+ self.assertTrue(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not requested')
|
|
+ machine_key = os.path.join(dname, '%s.Machine.key' % ca_cn)
|
|
+ self.assertTrue(os.path.exists(machine_key),
|
|
+ 'Machine key was not generated')
|
|
+
|
|
+ # Verify RSOP does not fail
|
|
+ ext.rsop([g for g in gpos if g.name == guid][0])
|
|
+
|
|
+ # Check that a call to gpupdate --rsop also succeeds
|
|
+ ret = rsop(self.lp)
|
|
+ self.assertEqual(ret, 0, 'gpupdate --rsop failed!')
|
|
+
|
|
+ # Remove policy
|
|
+ gp_db = store.get_gplog(machine_creds.get_username())
|
|
+ del_gpos = get_deleted_gpos_list(gp_db, [])
|
|
+ ext.process_group_policy(del_gpos, [], dname)
|
|
+ self.assertFalse(os.path.exists(ca_crt),
|
|
+ 'Root CA certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(machine_crt),
|
|
+ 'Machine certificate was not removed')
|
|
+ self.assertFalse(os.path.exists(machine_key),
|
|
+ 'Machine key was not removed')
|
|
+ out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate()
|
|
+ self.assertNotIn(get_bytes(ca_cn), out, 'CA was not removed')
|
|
+ out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate()
|
|
+ self.assertNotIn(b'Machine', out,
|
|
+ 'Machine certificate not removed')
|
|
+ self.assertNotIn(b'Workstation', out,
|
|
+ 'Workstation certificate not removed')
|
|
+
|
|
+ # Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate
|
|
+ ldb.delete(certa_dn)
|
|
+ ldb.delete(enroll_dn)
|
|
+ ldb.delete(template_dn)
|
|
+
|
|
+ # Unstage the Registry.pol file
|
|
+ unstage_file(reg_pol)
|
|
+
|
|
def test_gp_cert_auto_enroll_ext(self):
|
|
local_path = self.lp.cache_path('gpo_cache')
|
|
guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
|
|
@@ -6777,6 +6889,7 @@ class GPOTests(tests.TestCase):
|
|
machine_creds.set_machine_account()
|
|
|
|
# Initialize the group policy extension
|
|
+ cae.requests = dummy_requests()
|
|
ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds,
|
|
machine_creds.get_username(), store)
|
|
|
|
@@ -7241,6 +7354,7 @@ class GPOTests(tests.TestCase):
|
|
machine_creds.set_machine_account()
|
|
|
|
# Initialize the group policy extension
|
|
+ cae.requests = dummy_requests()
|
|
ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds,
|
|
machine_creds.get_username(), store)
|
|
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
new file mode 100644
|
|
index 00000000000..f1e590bc7d8
|
|
--- /dev/null
|
|
+++ b/selftest/knownfail.d/gpo
|
|
@@ -0,0 +1 @@
|
|
+^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext_without_ndes
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 1a9af36177c7491687c75df151474bb10285f00e Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Thu, 18 Jan 2024 20:23:24 +0200
|
|
Subject: [PATCH 12/63] gpo: Decode base64 root cert before importing
|
|
|
|
The reasoning behind this is described in the previous commit message,
|
|
but essentially this should either be wrapped in certificate blocks and
|
|
imported as PEM, or converted back to binary and imported as DER.
|
|
|
|
I've opted for the latter since it's how it used to work before it
|
|
regressed in 157335ee93e.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15557
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit 3f3ddfa699a33c2c8a59f7fb9ee044bb2a6e0e06)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 5 +++--
|
|
selftest/knownfail.d/gpo | 1 -
|
|
2 files changed, 3 insertions(+), 3 deletions(-)
|
|
delete mode 100644 selftest/knownfail.d/gpo
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 08d1a7348cd..cd5e54f1110 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -217,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:
|
|
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
|
|
deleted file mode 100644
|
|
index f1e590bc7d8..00000000000
|
|
--- a/selftest/knownfail.d/gpo
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_cert_auto_enroll_ext_without_ndes
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From f5fc88f9ae255f4dc135580f0fa4a02f5addc390 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Date: Fri, 19 Jan 2024 11:36:19 +0200
|
|
Subject: [PATCH 13/63] gpo: Do not get templates list on first run
|
|
|
|
This is a visual fix and has no impact on functionality apart from
|
|
cleaner log messages.
|
|
|
|
The point of this is to get the list of supported templates in order to
|
|
compute a diff between the current applied templates and the updated
|
|
list, so we are able to unapply and reapply the policy in case there are
|
|
differences.
|
|
|
|
However this code path is executed on first applies as well, at which
|
|
point the root CA is not yet set up. This causes the
|
|
`get_supported_templates` call to fail, which is not a hard failure but
|
|
still pollutes the logs. In this case it's safe to avoid executing the
|
|
command as the policy will be applied regardless.
|
|
|
|
Signed-off-by: Gabriel Nagy <gabriel.nagy@canonical.com>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Mon Jan 22 16:48:57 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 8579340fc540633c13c017d896034904a8dbd55c)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index cd5e54f1110..559c903e1a2 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -359,7 +359,8 @@ 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 {}
|
|
- templates = ['%s.%s' % (ca['name'], t.decode()) for t in get_supported_templates(ca['hostname'])]
|
|
+ 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)
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e8a6219181f2af87813b53fd09684650c1aa6f90 Mon Sep 17 00:00:00 2001
|
|
From: David Mulder <dmulder@samba.org>
|
|
Date: Fri, 5 Jan 2024 08:47:07 -0700
|
|
Subject: [PATCH 14/63] gp: Skip site GP list if no site is found
|
|
|
|
[MS-GPOL] 3.2.5.1.4 Site Search says if the site
|
|
search returns ERROR_NO_SITENAME, the GP site
|
|
search should be skipped.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15548
|
|
|
|
Signed-off-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Tue Jan 23 11:20:35 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit f05b61b4991e7f51bd184d76a79f8b50114a0ff3)
|
|
---
|
|
python/samba/gp/gpclass.py | 30 ++++++++++++++++++------------
|
|
1 file changed, 18 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gpclass.py b/python/samba/gp/gpclass.py
|
|
index 617ef79350c..babd8f90748 100644
|
|
--- a/python/samba/gp/gpclass.py
|
|
+++ b/python/samba/gp/gpclass.py
|
|
@@ -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",
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From d0d1a890d6f2466691fa4ee663232ee0bd1c3776 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 14:14:30 +0100
|
|
Subject: [PATCH 15/63] python:gp: Avoid path check for cepces-submit
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
find_cepces_submit() uses which(), which returns None if not found.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
(cherry picked from commit 6a9630eff624643fd725219775784e68d967d04c)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 559c903e1a2..7325d5132cf 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -185,7 +185,7 @@ def find_cepces_submit():
|
|
|
|
def get_supported_templates(server):
|
|
cepces_submit = find_cepces_submit()
|
|
- if not cepces_submit or not os.path.exists(cepces_submit):
|
|
+ if not cepces_submit:
|
|
log.error('Failed to find cepces-submit')
|
|
return []
|
|
|
|
@@ -301,7 +301,7 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
# Setup Certificate Auto Enrollment
|
|
getcert = which('getcert')
|
|
cepces_submit = find_cepces_submit()
|
|
- if getcert is not None and os.path.exists(cepces_submit):
|
|
+ if getcert is not None and cepces_submit is not None:
|
|
p = Popen([getcert, 'add-ca', '-c', ca['name'], '-e',
|
|
'%s --server=%s --auth=%s' % (cepces_submit,
|
|
ca['hostname'], auth)],
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7f6c9a4945635c6eb8ada2255bd0febbf0f4e540 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 14:07:47 +0100
|
|
Subject: [PATCH 16/63] python:gp: Improve logging for certificate enrollment
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
(cherry picked from commit 6d5507e05050690cd4c56f3f97f5fb7de0338b87)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 11 ++++++++++-
|
|
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 7325d5132cf..a25a9678587 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -274,6 +274,9 @@ 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']
|
|
+
|
|
+ log.info("Try to get root or server certificates")
|
|
+
|
|
root_certs = getca(ca, url, trust_dir)
|
|
data['files'].extend(root_certs)
|
|
global_trust_dir = find_global_trust_dir()
|
|
@@ -283,6 +286,7 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
try:
|
|
os.symlink(src, dst)
|
|
data['files'].append(dst)
|
|
+ log.info("Created symlink: %s -> %s" % (src, dst))
|
|
except PermissionError:
|
|
log.warn('Failed to symlink root certificate to the'
|
|
' admin trust anchors')
|
|
@@ -295,9 +299,14 @@ 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 = update_ca_command()
|
|
+ log.info("Running %s" % (update))
|
|
if update is not None:
|
|
- Popen([update]).wait()
|
|
+ ret = Popen([update]).wait()
|
|
+ if ret != 0:
|
|
+ log.error('Failed to run %s' % (update))
|
|
+
|
|
# Setup Certificate Auto Enrollment
|
|
getcert = which('getcert')
|
|
cepces_submit = find_cepces_submit()
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 5321d5b5bd24d7659743576f2e12a7dc0a93a828 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 15:04:36 +0100
|
|
Subject: [PATCH 17/63] python:gp: Do not print an error, if CA already exists
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
We will get an exit status for duplicate in future:
|
|
https://www.pagure.io/certmonger/issue/269
|
|
We can't really fix that right now, as older version of certmonger
|
|
don't support the `-v` option.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
(cherry picked from commit 728757cd1ff0465967fcbda100254c9312e87c93)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 8 ++++++--
|
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index a25a9678587..0b23cd688db 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -318,8 +318,12 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
out, err = p.communicate()
|
|
log.debug(out.decode())
|
|
if p.returncode != 0:
|
|
- data = { 'Error': err.decode(), 'CA': ca['name'] }
|
|
- log.error('Failed to add Certificate Authority', data)
|
|
+ if p.returncode == 2:
|
|
+ log.info('The CA [%s] already exists' % ca['name'])
|
|
+ else:
|
|
+ data = {'Error': err.decode(), 'CA': ca['name']}
|
|
+ log.error('Failed to add Certificate Authority', data)
|
|
+
|
|
supported_templates = get_supported_templates(ca['hostname'])
|
|
for template in supported_templates:
|
|
attrs = fetch_template_attrs(ldb, template)
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 6a7a8a4090b8cdb8e71f4ad590260ceeda253ce2 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 15:05:02 +0100
|
|
Subject: [PATCH 18/63] python:gp: Do not print an error if template already
|
|
exists
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
We will get an exit status for duplicate in future:
|
|
https://www.pagure.io/certmonger/issue/269
|
|
We can't really fix that right now, as older version of certmonger
|
|
don't support the `-v` option.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
(cherry picked from commit 98dc44286ea102ef7701ccdea26bbde32b523a7e)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 8 ++++++--
|
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index 0b23cd688db..db681cb6f69 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -338,8 +338,12 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
out, err = p.communicate()
|
|
log.debug(out.decode())
|
|
if p.returncode != 0:
|
|
- data = { 'Error': err.decode(), 'Certificate': nickname }
|
|
- log.error('Failed to request certificate', data)
|
|
+ if p.returncode == 2:
|
|
+ log.info('The template [%s] already exists' % (nickname))
|
|
+ else:
|
|
+ data = {'Error': err.decode(), 'Certificate': nickname}
|
|
+ log.error('Failed to request certificate', data)
|
|
+
|
|
data['files'].extend([keyfile, certfile])
|
|
data['templates'].append(nickname)
|
|
if update is not None:
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 43dc3d5d833bc1db885eb45402decd3225a7c946 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 15:05:24 +0100
|
|
Subject: [PATCH 19/63] python:gp: Log an error if update fails
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
(cherry picked from commit 367756b85a9ac8daaac2326392bcd1373feed3b7)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index db681cb6f69..c8ad2039dc6 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -347,7 +347,9 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'):
|
|
data['files'].extend([keyfile, certfile])
|
|
data['templates'].append(nickname)
|
|
if update is not None:
|
|
- Popen([update]).wait()
|
|
+ ret = Popen([update]).wait()
|
|
+ if ret != 0:
|
|
+ log.error('Failed to run %s' % (update))
|
|
else:
|
|
log.warn('certmonger and cepces must be installed for ' +
|
|
'certificate auto enrollment to work')
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From d8276d6a098d10f405b8f24c4dfb82af4496607c Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jan 2024 15:46:24 +0100
|
|
Subject: [PATCH 20/63] python:gp: Improve working of log messages to avoid
|
|
confusion
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
We should not use the word "Failed". We are totally fine if we can't
|
|
connect to NDES in the meantime. This logs:
|
|
|
|
Try to get root or server certificates.
|
|
Unable to install root certificates (requires NDES).
|
|
Installing the server certificate only.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15559
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: David Mulder <dmulder@samba.org>
|
|
Reviewed-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Mon Jan 29 10:37:29 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 1f823424418e814d9dc0785658e2a7d92643dab2)
|
|
---
|
|
python/samba/gp/gp_cert_auto_enroll_ext.py | 6 ++----
|
|
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
index c8ad2039dc6..2b7f7d22c2b 100644
|
|
--- a/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
+++ b/python/samba/gp/gp_cert_auto_enroll_ext.py
|
|
@@ -209,12 +209,10 @@ def getca(ca, url, trust_dir):
|
|
r = requests.get(url=url, params={'operation': 'GetCACert',
|
|
'message': 'CAIdentifier'})
|
|
except requests.exceptions.ConnectionError:
|
|
- log.warn('Failed to establish a new connection')
|
|
+ log.warn('Could not connect to Network Device Enrollment Service.')
|
|
r = None
|
|
if r is None or r.content == b'' or r.headers['Content-Type'] == 'text/html':
|
|
- log.warn('Failed to fetch the root certificate chain.')
|
|
- log.warn('The Network Device Enrollment Service is either not' +
|
|
- ' installed or not configured.')
|
|
+ log.warn('Unable to fetch root certificates (requires NDES).')
|
|
if 'cACertificate' in ca:
|
|
log.warn('Installing the server certificate only.')
|
|
der_certificate = base64.b64decode(ca['cACertificate'])
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 585357bf0d8889747a2769c2451ee34766087d95 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 29 Jan 2024 17:46:30 +0100
|
|
Subject: [PATCH 21/63] python:gp: Fix logging with gp
|
|
|
|
This allows enable INFO level logging with: `samba-gpupdate -d3`
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15558
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Tue Jan 30 07:18:05 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 145194071b10c4c1857f28fe79c57fd63ffab889)
|
|
---
|
|
python/samba/gp/util/logging.py | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/python/samba/gp/util/logging.py b/python/samba/gp/util/logging.py
|
|
index a74a8707d50..c3de32825db 100644
|
|
--- a/python/samba/gp/util/logging.py
|
|
+++ b/python/samba/gp/util/logging.py
|
|
@@ -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:
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 14ceb0b5f2f954bbabdaf78b8185fc515e3c8294 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Wed, 13 Mar 2024 13:55:41 +0100
|
|
Subject: [PATCH 22/63] docs-xml: Add parameter all_groupmem to idmap_ad
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15605
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit a485d9de2f2d6a9815dcac6addb988a8987e111c)
|
|
---
|
|
docs-xml/manpages/idmap_ad.8.xml | 10 ++++++++++
|
|
1 file changed, 10 insertions(+)
|
|
|
|
diff --git a/docs-xml/manpages/idmap_ad.8.xml b/docs-xml/manpages/idmap_ad.8.xml
|
|
index b364bbfa231..de6d36afe95 100644
|
|
--- a/docs-xml/manpages/idmap_ad.8.xml
|
|
+++ b/docs-xml/manpages/idmap_ad.8.xml
|
|
@@ -100,6 +100,16 @@
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
+ <term>all_groupmem = yes/no</term>
|
|
+ <listitem><para>
|
|
+ If set to <parameter>yes</parameter> winbind will retrieve all
|
|
+ group members for getgrnam(3), getgrgid(3) and getgrent(3) calls,
|
|
+ including those with missing uidNumber.
|
|
+ </para>
|
|
+ <para>Default: no</para>
|
|
+ </listitem>
|
|
+ </varlistentry>
|
|
+ <varlistentry>
|
|
<term>deny ous</term>
|
|
<listitem><para>This parameter is a list of OUs from
|
|
which objects will not be mapped via the ad idmap
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From ac4184c8c3220263cb6f1a46a012533ed1c4e047 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Tue, 12 Mar 2024 13:20:24 +0100
|
|
Subject: [PATCH 23/63] s3:winbindd: Improve performance of lookup_groupmem()
|
|
in idmap_ad
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
The LDAP query of lookup_groupmem() returns all group members from AD
|
|
even those with missing uidNumber. Such group members are useless in
|
|
UNIX environment for idmap_ad backend since there is no uid mapping.
|
|
|
|
'test_user' is member of group "Domanin Users" with 200K members,
|
|
only 20K members have set uidNumber.
|
|
|
|
Without this fix:
|
|
|
|
$ time id test_user
|
|
|
|
real 1m5.946s
|
|
user 0m0.019s
|
|
sys 0m0.012s
|
|
|
|
With this fix:
|
|
|
|
$ time id test_user
|
|
|
|
real 0m3.544s
|
|
user 0m0.004s
|
|
sys 0m0.007s
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15605
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit 5d475d26a3d545f04791a04e85a06b8b192e3fcf)
|
|
---
|
|
source3/winbindd/winbindd_ads.c | 11 +++++++----
|
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
|
|
index d7a665abbc6..e625aa6473f 100644
|
|
--- a/source3/winbindd/winbindd_ads.c
|
|
+++ b/source3/winbindd/winbindd_ads.c
|
|
@@ -1037,7 +1037,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
|
|
}
|
|
|
|
static NTSTATUS add_primary_group_members(
|
|
- ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
|
|
+ ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid, const char *domname,
|
|
char ***all_members, size_t *num_all_members)
|
|
{
|
|
char *filter;
|
|
@@ -1049,10 +1049,13 @@ static NTSTATUS add_primary_group_members(
|
|
char **members;
|
|
size_t num_members;
|
|
ads_control args;
|
|
+ bool all_groupmem = idmap_config_bool(domname, "all_groupmem", false);
|
|
|
|
filter = talloc_asprintf(
|
|
- mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
|
|
- (unsigned)rid);
|
|
+ mem_ctx,
|
|
+ "(&(objectCategory=user)(primaryGroupID=%u)%s)",
|
|
+ (unsigned)rid,
|
|
+ all_groupmem ? "" : "(uidNumber=*)(!(uidNumber=0))");
|
|
if (filter == NULL) {
|
|
goto done;
|
|
}
|
|
@@ -1204,7 +1207,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
|
|
|
|
DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
|
|
|
|
- status = add_primary_group_members(ads, mem_ctx, rid,
|
|
+ status = add_primary_group_members(ads, mem_ctx, rid, domain->name,
|
|
&members, &num_members);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
DEBUG(10, ("%s: add_primary_group_members failed: %s\n",
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From d0e2002efcc37055b35c351a6b936e6ab89fad32 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Mon, 25 Mar 2024 22:38:18 +0100
|
|
Subject: [PATCH 24/63] selftest: Add "winbind expand groups = 1" to
|
|
setup_ad_member_idmap_ad
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15605
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(backported from commit 2dab3a331b5511b4f2253f2b3b4513db7e52ea9a)
|
|
---
|
|
selftest/target/Samba3.pm | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
|
|
index 44ac4a5901a..606c65f8ab1 100755
|
|
--- a/selftest/target/Samba3.pm
|
|
+++ b/selftest/target/Samba3.pm
|
|
@@ -1412,6 +1412,7 @@ sub setup_ad_member_idmap_ad
|
|
idmap config $dcvars->{TRUST_DOMAIN} : backend = ad
|
|
idmap config $dcvars->{TRUST_DOMAIN} : range = 2000000-2999999
|
|
gensec_gssapi:requested_life_time = 5
|
|
+ winbind expand groups = 1
|
|
";
|
|
|
|
my $ret = $self->provision(
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 9625b6aed981aa4e70fe11d9d1acdb54db7591a3 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Thu, 14 Mar 2024 15:24:21 +0100
|
|
Subject: [PATCH 25/63] tests: Add a test for "all_groups=no" to
|
|
test_idmap_ad.sh
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15605
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
Autobuild-User(master): Pavel Filipensky <pfilipensky@samba.org>
|
|
Autobuild-Date(master): Tue Apr 2 13:25:39 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit f8b72aa1f72881989990fabc9f4888968bb81967)
|
|
---
|
|
nsswitch/tests/test_idmap_ad.sh | 22 ++++++++++++++++++++++
|
|
1 file changed, 22 insertions(+)
|
|
|
|
diff --git a/nsswitch/tests/test_idmap_ad.sh b/nsswitch/tests/test_idmap_ad.sh
|
|
index 7ae112ada71..1d4bd395ba9 100755
|
|
--- a/nsswitch/tests/test_idmap_ad.sh
|
|
+++ b/nsswitch/tests/test_idmap_ad.sh
|
|
@@ -94,6 +94,14 @@ gidNumber: 2000001
|
|
unixHomeDirectory: /home/forbidden
|
|
loginShell: /bin/tcsh
|
|
gecos: User in forbidden OU
|
|
+
|
|
+dn: CN=no_posix_id,CN=Users,$BASE_DN
|
|
+changetype: add
|
|
+objectClass: user
|
|
+samaccountName: no_posix_id
|
|
+unixHomeDirectory: /home/no_posix_id
|
|
+loginShell: /bin/sh
|
|
+gecos: User without uidNumber and gidNumber
|
|
EOF
|
|
|
|
#
|
|
@@ -171,6 +179,17 @@ then
|
|
failed=$(($failed + 1))
|
|
fi
|
|
|
|
+#
|
|
+# Test 6: Make sure that with the default "all_groups=no"
|
|
+# the group "domain users" will not show user "no_posix_id"
|
|
+# but will show "SAMBA2008R2/administrator"
|
|
+#
|
|
+
|
|
+dom_users="$DOMAIN/domain users" # Extra step to make sure that all is one word
|
|
+out="$($wbinfo --group-info "$dom_users")"
|
|
+testit_grep_count "no_posix_id1" "no_posix_id" 0 echo "$out" || failed=$(expr $failed + 1)
|
|
+testit_grep "no_posix_id2" "SAMBA2008R2/administrator" echo "$out" || failed=$(expr $failed + 1)
|
|
+
|
|
#
|
|
# Trusted domain test 1: Test uid of Administrator, should be 2500000
|
|
#
|
|
@@ -241,6 +260,9 @@ gidNumber: 2000002
|
|
dn: cn=forbidden,ou=sub,$BASE_DN
|
|
changetype: delete
|
|
|
|
+dn: CN=no_posix_id,CN=Users,$BASE_DN
|
|
+changetype: delete
|
|
+
|
|
dn: ou=sub,$BASE_DN
|
|
changetype: delete
|
|
EOF
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e5890e63c35a4a5af29ae16e6dd734c4a3a304cc Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Tue, 28 May 2024 13:51:53 +0200
|
|
Subject: [PATCH 26/63] s3:libads: Allow get_kdc_ip_string() to lookup the KDCs
|
|
IP
|
|
|
|
Remove the requirement to provide an IP address. We should look up the
|
|
IP of the KDC and use it for the specified realm/workgroup.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15653
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
(cherry picked from commit 28aa0b815baf4668e3df01d52597c40fd430e2fb)
|
|
---
|
|
source3/libads/kerberos.c | 30 +++++++++++++++---------------
|
|
1 file changed, 15 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
|
|
index 50f4a6de3c6..ddf97c11973 100644
|
|
--- a/source3/libads/kerberos.c
|
|
+++ b/source3/libads/kerberos.c
|
|
@@ -437,23 +437,23 @@ static char *get_kdc_ip_string(char *mem_ctx,
|
|
char *kdc_str = NULL;
|
|
char *canon_sockaddr = NULL;
|
|
|
|
- SMB_ASSERT(pss != NULL);
|
|
-
|
|
- canon_sockaddr = print_canonical_sockaddr_with_port(frame, pss);
|
|
- if (canon_sockaddr == NULL) {
|
|
- goto out;
|
|
- }
|
|
+ if (pss != NULL) {
|
|
+ canon_sockaddr = print_canonical_sockaddr_with_port(frame, pss);
|
|
+ if (canon_sockaddr == NULL) {
|
|
+ goto out;
|
|
+ }
|
|
|
|
- kdc_str = talloc_asprintf(frame,
|
|
- "\t\tkdc = %s\n",
|
|
- canon_sockaddr);
|
|
- if (kdc_str == NULL) {
|
|
- goto out;
|
|
- }
|
|
+ kdc_str = talloc_asprintf(frame,
|
|
+ "\t\tkdc = %s\n",
|
|
+ canon_sockaddr);
|
|
+ if (kdc_str == NULL) {
|
|
+ goto out;
|
|
+ }
|
|
|
|
- ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
|
|
- if (!ok) {
|
|
- goto out;
|
|
+ ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
|
|
+ if (!ok) {
|
|
+ goto out;
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 96a1ecd8db249fa03db60259cf76fdef9c1bd749 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Tue, 28 May 2024 13:53:51 +0200
|
|
Subject: [PATCH 27/63] s3:libads: Do not fail if we don't get an IP passed
|
|
down
|
|
|
|
The IP should be optional and we should look it up if not provided.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15653
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
(cherry picked from commit 9dcc52d2a57314ec9ddaae82b3c49da051d1f1d2)
|
|
---
|
|
source3/libads/kerberos.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
|
|
index ddf97c11973..f74d8eb567c 100644
|
|
--- a/source3/libads/kerberos.c
|
|
+++ b/source3/libads/kerberos.c
|
|
@@ -704,7 +704,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
|
|
return false;
|
|
}
|
|
|
|
- if (domain == NULL || pss == NULL) {
|
|
+ if (domain == NULL) {
|
|
return false;
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 4934642b7a7d92c6d81ba25ef6e4b66e3805f708 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Tue, 28 May 2024 13:54:24 +0200
|
|
Subject: [PATCH 28/63] s3:winbind: Fix idmap_ad creating an invalid local
|
|
krb5.conf
|
|
|
|
In case of a trusted domain, we are providing the realm of the primary
|
|
trust but specify the KDC IP of the trusted domain. This leads to
|
|
Kerberos ticket requests to the trusted domain KDC which doesn't know
|
|
about the machine account. However we need a ticket from our primary
|
|
trust KDC.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15653
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
(backported from commit 8989aa47b7493e6b7978c2efc4a40c781e9a2aee)
|
|
---
|
|
source3/winbindd/idmap_ad.c | 11 +++++++++--
|
|
1 file changed, 9 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
|
|
index 5c9fe07db95..b8002825161 100644
|
|
--- a/source3/winbindd/idmap_ad.c
|
|
+++ b/source3/winbindd/idmap_ad.c
|
|
@@ -320,7 +320,10 @@ static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
|
|
struct tldap_context **pld)
|
|
{
|
|
struct netr_DsRGetDCNameInfo *dcinfo;
|
|
- struct sockaddr_storage dcaddr;
|
|
+ struct sockaddr_storage dcaddr = {
|
|
+ .ss_family = AF_UNSPEC,
|
|
+ };
|
|
+ struct sockaddr_storage *pdcaddr = NULL;
|
|
struct cli_credentials *creds;
|
|
struct loadparm_context *lp_ctx;
|
|
struct tldap_context *ld;
|
|
@@ -362,9 +365,13 @@ static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
|
|
* create_local_private_krb5_conf_for_domain() can deal with
|
|
* sitename==NULL
|
|
*/
|
|
+ if (strequal(domname, lp_realm()) || strequal(domname, lp_workgroup()))
|
|
+ {
|
|
+ pdcaddr = &dcaddr;
|
|
+ }
|
|
|
|
ok = create_local_private_krb5_conf_for_domain(
|
|
- lp_realm(), lp_workgroup(), sitename, &dcaddr);
|
|
+ lp_realm(), lp_workgroup(), sitename, pdcaddr);
|
|
TALLOC_FREE(sitename);
|
|
if (!ok) {
|
|
DBG_DEBUG("Could not create private krb5.conf\n");
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From cccc902c64c93db317bf4707d0af5e56b2887286 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Schneider <asn@samba.org>
|
|
Date: Mon, 22 Jul 2024 12:26:55 +0200
|
|
Subject: [PATCH 29/63] s3:notifyd: Use a watcher per db record
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
This fixes a O(n²) performance regression in notifyd. The problem was
|
|
that we had a watcher per notify instance. This changes the code to have
|
|
a watcher per notify db entry.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14430
|
|
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Tue Oct 1 14:22:43 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit af011b987a4ad0d3753d83cc0b8d97ad64ba874a)
|
|
---
|
|
source3/smbd/notifyd/notifyd.c | 214 ++++++++++++++++++-------
|
|
source3/smbd/notifyd/notifyd_db.c | 5 +-
|
|
source3/smbd/notifyd/notifyd_entry.c | 51 ++++--
|
|
source3/smbd/notifyd/notifyd_private.h | 46 ++++--
|
|
4 files changed, 228 insertions(+), 88 deletions(-)
|
|
|
|
diff --git a/source3/smbd/notifyd/notifyd.c b/source3/smbd/notifyd/notifyd.c
|
|
index ca303bd4d51..b368b8390fa 100644
|
|
--- a/source3/smbd/notifyd/notifyd.c
|
|
+++ b/source3/smbd/notifyd/notifyd.c
|
|
@@ -337,6 +337,7 @@ static bool notifyd_apply_rec_change(
|
|
struct messaging_context *msg_ctx)
|
|
{
|
|
struct db_record *rec = NULL;
|
|
+ struct notifyd_watcher watcher = {};
|
|
struct notifyd_instance *instances = NULL;
|
|
size_t num_instances;
|
|
size_t i;
|
|
@@ -344,6 +345,7 @@ static bool notifyd_apply_rec_change(
|
|
TDB_DATA value;
|
|
NTSTATUS status;
|
|
bool ok = false;
|
|
+ bool new_watcher = false;
|
|
|
|
if (pathlen == 0) {
|
|
DBG_WARNING("pathlen==0\n");
|
|
@@ -374,8 +376,12 @@ static bool notifyd_apply_rec_change(
|
|
value = dbwrap_record_get_value(rec);
|
|
|
|
if (value.dsize != 0) {
|
|
- if (!notifyd_parse_entry(value.dptr, value.dsize, NULL,
|
|
- &num_instances)) {
|
|
+ ok = notifyd_parse_entry(value.dptr,
|
|
+ value.dsize,
|
|
+ &watcher,
|
|
+ NULL,
|
|
+ &num_instances);
|
|
+ if (!ok) {
|
|
goto fail;
|
|
}
|
|
}
|
|
@@ -390,8 +396,22 @@ static bool notifyd_apply_rec_change(
|
|
goto fail;
|
|
}
|
|
|
|
- if (value.dsize != 0) {
|
|
- memcpy(instances, value.dptr, value.dsize);
|
|
+ if (num_instances > 0) {
|
|
+ struct notifyd_instance *tmp = NULL;
|
|
+ size_t num_tmp = 0;
|
|
+
|
|
+ ok = notifyd_parse_entry(value.dptr,
|
|
+ value.dsize,
|
|
+ NULL,
|
|
+ &tmp,
|
|
+ &num_tmp);
|
|
+ if (!ok) {
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ memcpy(instances,
|
|
+ tmp,
|
|
+ sizeof(struct notifyd_instance) * num_tmp);
|
|
}
|
|
|
|
for (i=0; i<num_instances; i++) {
|
|
@@ -414,41 +434,106 @@ static bool notifyd_apply_rec_change(
|
|
*instance = (struct notifyd_instance) {
|
|
.client = *client,
|
|
.instance = *chg,
|
|
- .internal_filter = chg->filter,
|
|
- .internal_subdir_filter = chg->subdir_filter
|
|
};
|
|
|
|
num_instances += 1;
|
|
}
|
|
|
|
- if ((instance->instance.filter != 0) ||
|
|
- (instance->instance.subdir_filter != 0)) {
|
|
- int ret;
|
|
+ /*
|
|
+ * Calculate an intersection of the instances filters for the watcher.
|
|
+ */
|
|
+ if (instance->instance.filter > 0) {
|
|
+ uint32_t filter = instance->instance.filter;
|
|
+
|
|
+ if ((watcher.filter & filter) != filter) {
|
|
+ watcher.filter |= filter;
|
|
+
|
|
+ new_watcher = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Calculate an intersection of the instances subdir_filters for the
|
|
+ * watcher.
|
|
+ */
|
|
+ if (instance->instance.subdir_filter > 0) {
|
|
+ uint32_t subdir_filter = instance->instance.subdir_filter;
|
|
|
|
- TALLOC_FREE(instance->sys_watch);
|
|
+ if ((watcher.subdir_filter & subdir_filter) != subdir_filter) {
|
|
+ watcher.subdir_filter |= subdir_filter;
|
|
|
|
- ret = sys_notify_watch(entries, sys_notify_ctx, path,
|
|
- &instance->internal_filter,
|
|
- &instance->internal_subdir_filter,
|
|
- notifyd_sys_callback, msg_ctx,
|
|
- &instance->sys_watch);
|
|
- if (ret != 0) {
|
|
- DBG_WARNING("sys_notify_watch for [%s] returned %s\n",
|
|
- path, strerror(errno));
|
|
+ new_watcher = true;
|
|
}
|
|
}
|
|
|
|
if ((instance->instance.filter == 0) &&
|
|
(instance->instance.subdir_filter == 0)) {
|
|
+ uint32_t tmp_filter = 0;
|
|
+ uint32_t tmp_subdir_filter = 0;
|
|
+
|
|
/* This is a delete request */
|
|
- TALLOC_FREE(instance->sys_watch);
|
|
*instance = instances[num_instances-1];
|
|
num_instances -= 1;
|
|
+
|
|
+ for (i = 0; i < num_instances; i++) {
|
|
+ struct notifyd_instance *tmp = &instances[i];
|
|
+
|
|
+ tmp_filter |= tmp->instance.filter;
|
|
+ tmp_subdir_filter |= tmp->instance.subdir_filter;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * If the filter has changed, register a new watcher with the
|
|
+ * changed filter.
|
|
+ */
|
|
+ if (watcher.filter != tmp_filter ||
|
|
+ watcher.subdir_filter != tmp_subdir_filter)
|
|
+ {
|
|
+ watcher.filter = tmp_filter;
|
|
+ watcher.subdir_filter = tmp_subdir_filter;
|
|
+
|
|
+ new_watcher = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (new_watcher) {
|
|
+ /*
|
|
+ * In case we removed all notify instances, we want to remove
|
|
+ * the watcher. We won't register a new one, if no filters are
|
|
+ * set anymore.
|
|
+ */
|
|
+
|
|
+ TALLOC_FREE(watcher.sys_watch);
|
|
+
|
|
+ watcher.sys_filter = watcher.filter;
|
|
+ watcher.sys_subdir_filter = watcher.subdir_filter;
|
|
+
|
|
+ /*
|
|
+ * Only register a watcher if we have filter.
|
|
+ */
|
|
+ if (watcher.filter != 0 || watcher.subdir_filter != 0) {
|
|
+ int ret = sys_notify_watch(entries,
|
|
+ sys_notify_ctx,
|
|
+ path,
|
|
+ &watcher.sys_filter,
|
|
+ &watcher.sys_subdir_filter,
|
|
+ notifyd_sys_callback,
|
|
+ msg_ctx,
|
|
+ &watcher.sys_watch);
|
|
+ if (ret != 0) {
|
|
+ DBG_WARNING("sys_notify_watch for [%s] "
|
|
+ "returned %s\n",
|
|
+ path,
|
|
+ strerror(errno));
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
DBG_DEBUG("%s has %zu instances\n", path, num_instances);
|
|
|
|
if (num_instances == 0) {
|
|
+ TALLOC_FREE(watcher.sys_watch);
|
|
+
|
|
status = dbwrap_record_delete(rec);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
DBG_WARNING("dbwrap_record_delete returned %s\n",
|
|
@@ -456,13 +541,21 @@ static bool notifyd_apply_rec_change(
|
|
goto fail;
|
|
}
|
|
} else {
|
|
- value = make_tdb_data(
|
|
- (uint8_t *)instances,
|
|
- sizeof(struct notifyd_instance) * num_instances);
|
|
+ struct TDB_DATA iov[2] = {
|
|
+ {
|
|
+ .dptr = (uint8_t *)&watcher,
|
|
+ .dsize = sizeof(struct notifyd_watcher),
|
|
+ },
|
|
+ {
|
|
+ .dptr = (uint8_t *)instances,
|
|
+ .dsize = sizeof(struct notifyd_instance) *
|
|
+ num_instances,
|
|
+ },
|
|
+ };
|
|
|
|
- status = dbwrap_record_store(rec, value, 0);
|
|
+ status = dbwrap_record_storev(rec, iov, ARRAY_SIZE(iov), 0);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- DBG_WARNING("dbwrap_record_store returned %s\n",
|
|
+ DBG_WARNING("dbwrap_record_storev returned %s\n",
|
|
nt_errstr(status));
|
|
goto fail;
|
|
}
|
|
@@ -706,12 +799,18 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data,
|
|
.when = tstate->msg->when };
|
|
struct iovec iov[2];
|
|
size_t path_len = key.dsize;
|
|
+ struct notifyd_watcher watcher = {};
|
|
struct notifyd_instance *instances = NULL;
|
|
size_t num_instances = 0;
|
|
size_t i;
|
|
+ bool ok;
|
|
|
|
- if (!notifyd_parse_entry(data.dptr, data.dsize, &instances,
|
|
- &num_instances)) {
|
|
+ ok = notifyd_parse_entry(data.dptr,
|
|
+ data.dsize,
|
|
+ &watcher,
|
|
+ &instances,
|
|
+ &num_instances);
|
|
+ if (!ok) {
|
|
DBG_DEBUG("Could not parse notifyd_entry\n");
|
|
return;
|
|
}
|
|
@@ -734,9 +833,11 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data,
|
|
|
|
if (tstate->covered_by_sys_notify) {
|
|
if (tstate->recursive) {
|
|
- i_filter = instance->internal_subdir_filter;
|
|
+ i_filter = watcher.sys_subdir_filter &
|
|
+ instance->instance.subdir_filter;
|
|
} else {
|
|
- i_filter = instance->internal_filter;
|
|
+ i_filter = watcher.sys_filter &
|
|
+ instance->instance.filter;
|
|
}
|
|
} else {
|
|
if (tstate->recursive) {
|
|
@@ -1142,46 +1243,39 @@ static int notifyd_add_proxy_syswatches(struct db_record *rec,
|
|
struct db_context *db = dbwrap_record_get_db(rec);
|
|
TDB_DATA key = dbwrap_record_get_key(rec);
|
|
TDB_DATA value = dbwrap_record_get_value(rec);
|
|
- struct notifyd_instance *instances = NULL;
|
|
- size_t num_instances = 0;
|
|
- size_t i;
|
|
+ struct notifyd_watcher watcher = {};
|
|
char path[key.dsize+1];
|
|
bool ok;
|
|
+ int ret;
|
|
|
|
memcpy(path, key.dptr, key.dsize);
|
|
path[key.dsize] = '\0';
|
|
|
|
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
|
|
- &num_instances);
|
|
+ /* This is a remote database, we just need the watcher. */
|
|
+ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL);
|
|
if (!ok) {
|
|
DBG_WARNING("Could not parse notifyd entry for %s\n", path);
|
|
return 0;
|
|
}
|
|
|
|
- for (i=0; i<num_instances; i++) {
|
|
- struct notifyd_instance *instance = &instances[i];
|
|
- uint32_t filter = instance->instance.filter;
|
|
- uint32_t subdir_filter = instance->instance.subdir_filter;
|
|
- int ret;
|
|
+ watcher.sys_watch = NULL;
|
|
+ watcher.sys_filter = watcher.filter;
|
|
+ watcher.sys_subdir_filter = watcher.subdir_filter;
|
|
|
|
- /*
|
|
- * This is a remote database. Pointers that we were
|
|
- * given don't make sense locally. Initialize to NULL
|
|
- * in case sys_notify_watch fails.
|
|
- */
|
|
- instances[i].sys_watch = NULL;
|
|
-
|
|
- ret = state->sys_notify_watch(
|
|
- db, state->sys_notify_ctx, path,
|
|
- &filter, &subdir_filter,
|
|
- notifyd_sys_callback, state->msg_ctx,
|
|
- &instance->sys_watch);
|
|
- if (ret != 0) {
|
|
- DBG_WARNING("inotify_watch returned %s\n",
|
|
- strerror(errno));
|
|
- }
|
|
+ ret = state->sys_notify_watch(db,
|
|
+ state->sys_notify_ctx,
|
|
+ path,
|
|
+ &watcher.filter,
|
|
+ &watcher.subdir_filter,
|
|
+ notifyd_sys_callback,
|
|
+ state->msg_ctx,
|
|
+ &watcher.sys_watch);
|
|
+ if (ret != 0) {
|
|
+ DBG_WARNING("inotify_watch returned %s\n", strerror(errno));
|
|
}
|
|
|
|
+ memcpy(value.dptr, &watcher, sizeof(struct notifyd_watcher));
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1189,21 +1283,17 @@ static int notifyd_db_del_syswatches(struct db_record *rec, void *private_data)
|
|
{
|
|
TDB_DATA key = dbwrap_record_get_key(rec);
|
|
TDB_DATA value = dbwrap_record_get_value(rec);
|
|
- struct notifyd_instance *instances = NULL;
|
|
- size_t num_instances = 0;
|
|
- size_t i;
|
|
+ struct notifyd_watcher watcher = {};
|
|
bool ok;
|
|
|
|
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
|
|
- &num_instances);
|
|
+ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL);
|
|
if (!ok) {
|
|
DBG_WARNING("Could not parse notifyd entry for %.*s\n",
|
|
(int)key.dsize, (char *)key.dptr);
|
|
return 0;
|
|
}
|
|
- for (i=0; i<num_instances; i++) {
|
|
- TALLOC_FREE(instances[i].sys_watch);
|
|
- }
|
|
+ TALLOC_FREE(watcher.sys_watch);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/source3/smbd/notifyd/notifyd_db.c b/source3/smbd/notifyd/notifyd_db.c
|
|
index 18228619e9a..7dc3cd58081 100644
|
|
--- a/source3/smbd/notifyd/notifyd_db.c
|
|
+++ b/source3/smbd/notifyd/notifyd_db.c
|
|
@@ -40,7 +40,10 @@ static bool notifyd_parse_db_parser(TDB_DATA key, TDB_DATA value,
|
|
memcpy(path, key.dptr, key.dsize);
|
|
path[key.dsize] = 0;
|
|
|
|
- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances,
|
|
+ ok = notifyd_parse_entry(value.dptr,
|
|
+ value.dsize,
|
|
+ NULL,
|
|
+ &instances,
|
|
&num_instances);
|
|
if (!ok) {
|
|
DBG_DEBUG("Could not parse entry for path %s\n", path);
|
|
diff --git a/source3/smbd/notifyd/notifyd_entry.c b/source3/smbd/notifyd/notifyd_entry.c
|
|
index 539010de03a..f3b0e908136 100644
|
|
--- a/source3/smbd/notifyd/notifyd_entry.c
|
|
+++ b/source3/smbd/notifyd/notifyd_entry.c
|
|
@@ -21,22 +21,51 @@
|
|
* Parse an entry in the notifyd_context->entries database
|
|
*/
|
|
|
|
-bool notifyd_parse_entry(
|
|
- uint8_t *buf,
|
|
- size_t buflen,
|
|
- struct notifyd_instance **instances,
|
|
- size_t *num_instances)
|
|
+/**
|
|
+ * @brief Parse a notifyd database entry.
|
|
+ *
|
|
+ * The memory we pass down needs to be aligned. If it isn't aligned we can run
|
|
+ * into obscure errors as we just point into the data buffer.
|
|
+ *
|
|
+ * @param data The data to parse
|
|
+ * @param data_len The length of the data to parse
|
|
+ * @param watcher A pointer to store the watcher data or NULL.
|
|
+ * @param instances A pointer to store the array of notify instances or NULL.
|
|
+ * @param pnum_instances The number of elements in the array. If you just want
|
|
+ * the number of elements pass NULL for the watcher and instances pointers.
|
|
+ *
|
|
+ * @return true on success, false if an error occurred.
|
|
+ */
|
|
+bool notifyd_parse_entry(uint8_t *data,
|
|
+ size_t data_len,
|
|
+ struct notifyd_watcher *watcher,
|
|
+ struct notifyd_instance **instances,
|
|
+ size_t *pnum_instances)
|
|
{
|
|
- if ((buflen % sizeof(struct notifyd_instance)) != 0) {
|
|
- DBG_WARNING("invalid buffer size: %zu\n", buflen);
|
|
+ size_t ilen;
|
|
+
|
|
+ if (data_len < sizeof(struct notifyd_watcher)) {
|
|
return false;
|
|
}
|
|
|
|
- if (instances != NULL) {
|
|
- *instances = (struct notifyd_instance *)buf;
|
|
+ if (watcher != NULL) {
|
|
+ *watcher = *((struct notifyd_watcher *)(uintptr_t)data);
|
|
}
|
|
- if (num_instances != NULL) {
|
|
- *num_instances = buflen / sizeof(struct notifyd_instance);
|
|
+
|
|
+ ilen = data_len - sizeof(struct notifyd_watcher);
|
|
+ if ((ilen % sizeof(struct notifyd_instance)) != 0) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (pnum_instances != NULL) {
|
|
+ *pnum_instances = ilen / sizeof(struct notifyd_instance);
|
|
}
|
|
+ if (instances != NULL) {
|
|
+ /* The (uintptr_t) cast removes a warning from -Wcast-align. */
|
|
+ *instances =
|
|
+ (struct notifyd_instance *)(uintptr_t)
|
|
+ (data + sizeof(struct notifyd_watcher));
|
|
+ }
|
|
+
|
|
return true;
|
|
}
|
|
diff --git a/source3/smbd/notifyd/notifyd_private.h b/source3/smbd/notifyd/notifyd_private.h
|
|
index 36c08f47c54..db8e6e1c005 100644
|
|
--- a/source3/smbd/notifyd/notifyd_private.h
|
|
+++ b/source3/smbd/notifyd/notifyd_private.h
|
|
@@ -20,30 +20,48 @@
|
|
#include "lib/util/server_id.h"
|
|
#include "notifyd.h"
|
|
|
|
+
|
|
/*
|
|
- * notifyd's representation of a notify instance
|
|
+ * Representation of a watcher for a path
|
|
+ *
|
|
+ * This will be stored in the db.
|
|
*/
|
|
-struct notifyd_instance {
|
|
- struct server_id client;
|
|
- struct notify_instance instance;
|
|
-
|
|
- void *sys_watch; /* inotify/fam/etc handle */
|
|
+struct notifyd_watcher {
|
|
+ /*
|
|
+ * This is an intersections of the filter the watcher is listening for.
|
|
+ */
|
|
+ uint32_t filter;
|
|
+ uint32_t subdir_filter;
|
|
|
|
/*
|
|
- * Filters after sys_watch took responsibility of some bits
|
|
+ * Those are inout variables passed to the sys_watcher. The sys_watcher
|
|
+ * will remove the bits it can't handle.
|
|
*/
|
|
- uint32_t internal_filter;
|
|
- uint32_t internal_subdir_filter;
|
|
+ uint32_t sys_filter;
|
|
+ uint32_t sys_subdir_filter;
|
|
+
|
|
+ /* The handle for inotify/fam etc. */
|
|
+ void *sys_watch;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Representation of a notifyd instance
|
|
+ *
|
|
+ * This will be stored in the db.
|
|
+ */
|
|
+struct notifyd_instance {
|
|
+ struct server_id client;
|
|
+ struct notify_instance instance;
|
|
};
|
|
|
|
/*
|
|
* Parse an entry in the notifyd_context->entries database
|
|
*/
|
|
|
|
-bool notifyd_parse_entry(
|
|
- uint8_t *buf,
|
|
- size_t buflen,
|
|
- struct notifyd_instance **instances,
|
|
- size_t *num_instances);
|
|
+bool notifyd_parse_entry(uint8_t *data,
|
|
+ size_t data_len,
|
|
+ struct notifyd_watcher *watcher,
|
|
+ struct notifyd_instance **instances,
|
|
+ size_t *num_instances);
|
|
|
|
#endif
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From b04cb93ee52aac0ce7213d0581d69e852df52d4a Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Mon, 5 Feb 2024 15:03:48 +0100
|
|
Subject: [PATCH 30/63] smbd: simplify handling of failing fstat() after
|
|
unlinking file
|
|
|
|
close_remove_share_mode() already called vfs_stat_fsp(), so we can skip the
|
|
fstat() triggered in fd_close() by fsp->fsp_flags.fstat_before_close being true.
|
|
|
|
This avoids getting an EACCESS error when doing an fstat() on the removed file
|
|
which seems to happen with some FUSE filesystems.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15527
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Jeremy Allison <jra@samba.org>
|
|
(cherry picked from commit 6e6324cff29089a636823786183222a73fe7cb28)
|
|
---
|
|
source3/smbd/close.c | 1 +
|
|
source3/smbd/open.c | 15 +--------------
|
|
2 files changed, 2 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
|
|
index af5e78daa10..e16cb2d3485 100644
|
|
--- a/source3/smbd/close.c
|
|
+++ b/source3/smbd/close.c
|
|
@@ -603,6 +603,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
|
|
*/
|
|
|
|
fsp->fsp_flags.delete_on_close = false;
|
|
+ fsp->fsp_flags.fstat_before_close = false;
|
|
lck_state.reset_delete_on_close = true;
|
|
|
|
done:
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index 3581c4b9173..93c12e00eb0 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -997,20 +997,7 @@ NTSTATUS fd_close(files_struct *fsp)
|
|
if (fsp->fsp_flags.fstat_before_close) {
|
|
status = vfs_stat_fsp(fsp);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- /*
|
|
- * If this is a stream and delete-on-close was set, the
|
|
- * backing object (an xattr from streams_xattr) might
|
|
- * already be deleted so fstat() fails with
|
|
- * NT_STATUS_NOT_FOUND. So if fsp refers to a stream we
|
|
- * ignore the error and only bail for normal files where
|
|
- * an fstat() should still work. NB. We cannot use
|
|
- * fsp_is_alternate_stream(fsp) for this as the base_fsp
|
|
- * has already been closed at this point and so the value
|
|
- * fsp_is_alternate_stream() checks for is already NULL.
|
|
- */
|
|
- if (fsp->fsp_name->stream_name == NULL) {
|
|
- return status;
|
|
- }
|
|
+ return status;
|
|
}
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 29f0c0fb2f1cb0cfc4c615d31e82048b46a2cb0d Mon Sep 17 00:00:00 2001
|
|
From: Noel Power <noel.power@suse.com>
|
|
Date: Tue, 20 Feb 2024 09:26:29 +0000
|
|
Subject: [PATCH 31/63] s3/smbd: If we fail to close file_handle ensure we
|
|
should reset the fd
|
|
|
|
if fsp_flags.fstat_before_close == true then close_file_smb will call
|
|
vfs_stat which can fail. If it does fail then the fd associated
|
|
with the file handle will still be set (and we will hit an assert
|
|
is the file handle destructor) when calling file_free.
|
|
We need to set fd to -1 to avoid that. To achieve that we capture and
|
|
return the vfs_stat_fsp failure status while still processing the rest
|
|
of the fd_close logic.
|
|
|
|
[2024/02/20 09:23:48.454671, 0, pid=9744] ../../source3/smbd/smb2_close.c:226(smbd_smb2_close)
|
|
smbd_smb2_close: close_file[]: NT_STATUS_ACCESS_DENIED
|
|
[2024/02/20 09:23:48.454757, 0, pid=9744] ../../source3/smbd/fd_handle.c:40(fd_handle_destructor)
|
|
PANIC: assert failed at ../../source3/smbd/fd_handle.c(40): (fh->fd == -1) || (fh->fd == AT_FDCWD)
|
|
[2024/02/20 09:23:48.454781, 0, pid=9744] ../../lib/util/fault.c:178(smb_panic_log)
|
|
===============================================================
|
|
[2024/02/20 09:23:48.454804, 0, pid=9744] ../../lib/util/fault.c:185(smb_panic_log)
|
|
INTERNAL ERROR: assert failed: (fh->fd == -1) || (fh->fd == AT_FDCWD) in smbd (smbd[192.168.10) (client [192.168.100.15]) pid 9744 (4.21.0pre1-DEVELOPERBUILD)
|
|
[2024/02/20 09:23:48.454844, 0, pid=9744] ../../lib/util/fault.c:190(smb_panic_log)
|
|
If you are running a recent Samba version, and if you think this problem is not yet fixed in the latest versions, please consider reporting this bug, see https://wiki.samba.org/index.php/Bug_Reporting
|
|
[2024/02/20 09:23:48.454869, 0, pid=9744] ../../lib/util/fault.c:191(smb_panic_log)
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15527
|
|
Signed-off-by: Noel Power <noel.power@suse.com>
|
|
Reviewed-by: Jeremy Allison <jra@samba.org>
|
|
|
|
Autobuild-User(master): Noel Power <npower@samba.org>
|
|
Autobuild-Date(master): Wed Mar 13 10:34:45 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 6ee3f809a54d7b833ff798e68a93ada00a215d4d)
|
|
---
|
|
source3/smbd/open.c | 14 ++++++++------
|
|
1 file changed, 8 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index 93c12e00eb0..74be444fef5 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -987,7 +987,7 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp,
|
|
|
|
NTSTATUS fd_close(files_struct *fsp)
|
|
{
|
|
- NTSTATUS status;
|
|
+ NTSTATUS stat_status = NT_STATUS_OK;
|
|
int ret;
|
|
|
|
if (fsp == fsp->conn->cwd_fsp) {
|
|
@@ -995,10 +995,12 @@ NTSTATUS fd_close(files_struct *fsp)
|
|
}
|
|
|
|
if (fsp->fsp_flags.fstat_before_close) {
|
|
- status = vfs_stat_fsp(fsp);
|
|
- if (!NT_STATUS_IS_OK(status)) {
|
|
- return status;
|
|
- }
|
|
+ /*
|
|
+ * capture status, if failure
|
|
+ * continue close processing
|
|
+ * and return status
|
|
+ */
|
|
+ stat_status = vfs_stat_fsp(fsp);
|
|
}
|
|
|
|
if (fsp->dptr) {
|
|
@@ -1020,7 +1022,7 @@ NTSTATUS fd_close(files_struct *fsp)
|
|
if (ret == -1) {
|
|
return map_nt_error_from_unix(errno);
|
|
}
|
|
- return NT_STATUS_OK;
|
|
+ return stat_status;
|
|
}
|
|
|
|
/****************************************************************************
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From ed138c4d679e8291de18162e1cac65cc9da33b4d Mon Sep 17 00:00:00 2001
|
|
From: Jeremy Allison <jra@samba.org>
|
|
Date: Wed, 15 Jan 2025 10:21:19 -0800
|
|
Subject: [PATCH 32/63] auth: Add missing talloc_free() in error code path.
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15782
|
|
|
|
Signed-off-by: Jeremy Allison <jra@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
|
|
Autobuild-User(master): Günther Deschner <gd@samba.org>
|
|
Autobuild-Date(master): Thu Jan 16 14:32:39 UTC 2025 on atb-devel-224
|
|
|
|
(cherry picked from commit c514ce8dcadcbbf0d86f3038d2be0f9253a76b75)
|
|
---
|
|
auth/kerberos/kerberos_pac.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/auth/kerberos/kerberos_pac.c b/auth/kerberos/kerberos_pac.c
|
|
index b914075d85c..196654b36bd 100644
|
|
--- a/auth/kerberos/kerberos_pac.c
|
|
+++ b/auth/kerberos/kerberos_pac.c
|
|
@@ -351,6 +351,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
if (ret) {
|
|
DEBUG(5, ("PAC Decode: Failed to verify the service "
|
|
"signature: %s\n", error_message(ret)));
|
|
+ talloc_free(tmp_ctx);
|
|
return NT_STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From f8a7d7a3e8c3be3c7742c874239766b34c25ef3e Mon Sep 17 00:00:00 2001
|
|
From: Jeremy Allison <jra@samba.org>
|
|
Date: Thu, 16 Jan 2025 16:12:31 -0800
|
|
Subject: [PATCH 33/63] auth: Cleanup exit code paths in kerberos_decode_pac().
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
One more memory leak missed and now fixed. tmp_ctx
|
|
must be freed once the pac data is talloc_move'd.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15782
|
|
|
|
Signed-off-by: Jeremy Allison <jra@samba.org>
|
|
Reviewed-by: Jennifer Sutton <jennifersutton@catalyst.net.nz>
|
|
Reviewed-by: Christian Ambach <ambi@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
|
|
Autobuild-User(master): Günther Deschner <gd@samba.org>
|
|
Autobuild-Date(master): Fri Jan 17 12:01:47 UTC 2025 on atb-devel-224
|
|
|
|
(cherry picked from commit f9eb0b248da0689c82656f3e482161c45749afb6)
|
|
---
|
|
auth/kerberos/kerberos_pac.c | 88 ++++++++++++++++++------------------
|
|
1 file changed, 43 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/auth/kerberos/kerberos_pac.c b/auth/kerberos/kerberos_pac.c
|
|
index 196654b36bd..abb096bde1b 100644
|
|
--- a/auth/kerberos/kerberos_pac.c
|
|
+++ b/auth/kerberos/kerberos_pac.c
|
|
@@ -128,7 +128,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
time_t tgs_authtime,
|
|
struct PAC_DATA **pac_data_out)
|
|
{
|
|
- NTSTATUS status;
|
|
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
|
|
enum ndr_err_code ndr_err;
|
|
krb5_error_code ret;
|
|
DATA_BLOB modified_pac_blob;
|
|
@@ -164,8 +164,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
kdc_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
|
|
srv_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
|
|
if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_NO_MEMORY;
|
|
+ status = NT_STATUS_NO_MEMORY;
|
|
+ goto out;
|
|
}
|
|
|
|
ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
|
|
@@ -174,15 +174,14 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't parse the PAC: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
if (pac_data->num_buffers < 4) {
|
|
/* we need logon_ingo, service_key and kdc_key */
|
|
DEBUG(0,("less than 4 PAC buffers\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
ndr_err = ndr_pull_struct_blob(
|
|
@@ -192,15 +191,14 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't parse the PAC: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
if (pac_data_raw->num_buffers < 4) {
|
|
/* we need logon_ingo, service_key and kdc_key */
|
|
DEBUG(0,("less than 4 PAC buffers\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
if (pac_data->num_buffers != pac_data_raw->num_buffers) {
|
|
@@ -208,8 +206,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
|
|
"PAC_DATA_RAW has %d\n", pac_data->num_buffers,
|
|
pac_data_raw->num_buffers));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
for (i=0; i < pac_data->num_buffers; i++) {
|
|
@@ -220,8 +218,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
|
|
"%d while PAC_DATA_RAW has %d\n", i,
|
|
data_buf->type, raw_buf->type));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
switch (data_buf->type) {
|
|
case PAC_TYPE_LOGON_INFO:
|
|
@@ -254,26 +252,26 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
|
|
if (!logon_info) {
|
|
DEBUG(0,("PAC no logon_info\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!logon_name) {
|
|
DEBUG(0,("PAC no logon_name\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!srv_sig_ptr || !srv_sig_blob) {
|
|
DEBUG(0,("PAC no srv_key\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!kdc_sig_ptr || !kdc_sig_blob) {
|
|
DEBUG(0,("PAC no kdc_key\n"));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
/* Find and zero out the signatures,
|
|
@@ -288,8 +286,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't parse the KDC signature: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
ndr_err = ndr_pull_struct_blob(
|
|
@@ -299,8 +296,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't parse the SRV signature: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
/* Now zero the decoded structure */
|
|
@@ -317,8 +313,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't repack the KDC signature: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
ndr_err = ndr_push_struct_blob(
|
|
srv_sig_blob, pac_data_raw, srv_sig_wipe,
|
|
@@ -327,8 +322,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't repack the SRV signature: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
/* push out the whole structure, but now with zero'ed signatures */
|
|
@@ -339,8 +333,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
status = ndr_map_error2ntstatus(ndr_err);
|
|
DEBUG(0,("can't repack the RAW PAC: %s\n",
|
|
nt_errstr(status)));
|
|
- talloc_free(tmp_ctx);
|
|
- return status;
|
|
+ goto out;
|
|
}
|
|
|
|
if (service_keyblock) {
|
|
@@ -351,8 +344,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
if (ret) {
|
|
DEBUG(5, ("PAC Decode: Failed to verify the service "
|
|
"signature: %s\n", error_message(ret)));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_ACCESS_DENIED;
|
|
+ status = NT_STATUS_ACCESS_DENIED;
|
|
+ goto out;
|
|
}
|
|
|
|
if (krbtgt_keyblock) {
|
|
@@ -362,8 +355,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
if (ret) {
|
|
DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
|
|
smb_get_krb5_error_message(context, ret, tmp_ctx)));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_ACCESS_DENIED;
|
|
+ status = NT_STATUS_ACCESS_DENIED;
|
|
+ goto out;
|
|
}
|
|
}
|
|
}
|
|
@@ -379,8 +372,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
nt_time_string(tmp_ctx, logon_name->logon_time)));
|
|
DEBUG(2, ("PAC Decode: Ticket: %s\n",
|
|
nt_time_string(tmp_ctx, tgs_authtime_nttime)));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_ACCESS_DENIED;
|
|
+ status = NT_STATUS_ACCESS_DENIED;
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
@@ -392,8 +385,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
if (ret) {
|
|
DEBUG(2, ("Could not unparse name from ticket to match with name from PAC: [%s]:%s\n",
|
|
logon_name->account_name, error_message(ret)));
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
+ status = NT_STATUS_INVALID_PARAMETER;
|
|
+ goto out;
|
|
}
|
|
|
|
bool_ret = strcmp(client_principal_string, logon_name->account_name) == 0;
|
|
@@ -404,8 +397,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
logon_name->account_name,
|
|
client_principal_string));
|
|
SAFE_FREE(client_principal_string);
|
|
- talloc_free(tmp_ctx);
|
|
- return NT_STATUS_ACCESS_DENIED;
|
|
+ status = NT_STATUS_ACCESS_DENIED;
|
|
+ goto out;
|
|
}
|
|
SAFE_FREE(client_principal_string);
|
|
|
|
@@ -426,10 +419,15 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
|
|
}
|
|
|
|
if (pac_data_out) {
|
|
- *pac_data_out = talloc_steal(mem_ctx, pac_data);
|
|
+ *pac_data_out = talloc_move(mem_ctx, &pac_data);
|
|
}
|
|
|
|
- return NT_STATUS_OK;
|
|
+ status = NT_STATUS_OK;
|
|
+
|
|
+ out:
|
|
+
|
|
+ TALLOC_FREE(tmp_ctx);
|
|
+ return status;
|
|
}
|
|
|
|
NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 9fd06d5c331f5babaf417cc7339d12854a79fe4b Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Thu, 15 Feb 2024 17:29:46 +0100
|
|
Subject: [PATCH 34/63] s3:libsmb/dsgetdcname: use
|
|
NETLOGON_NT_VERSION_AVOID_NT4EMUL
|
|
|
|
In 2024 we always want an active directory response...
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15620
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
(cherry picked from commit 2b66663c75cdb3bc1b6bc5b1736dd9d35b094b42)
|
|
---
|
|
source3/libsmb/dsgetdcname.c | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
|
|
index 280ccd585b0..6fcaa26810c 100644
|
|
--- a/source3/libsmb/dsgetdcname.c
|
|
+++ b/source3/libsmb/dsgetdcname.c
|
|
@@ -930,6 +930,11 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
|
|
name_type = NBT_NAME_PDC;
|
|
}
|
|
|
|
+ /*
|
|
+ * It's 2024 we always want an AD style response!
|
|
+ */
|
|
+ nt_version |= NETLOGON_NT_VERSION_AVOID_NT4EMUL;
|
|
+
|
|
nt_version |= map_ds_flags_to_nt_version(flags);
|
|
|
|
snprintf(my_acct_name,
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 58e28d056f2df0906ee77ccfb9b56e8a764b38b4 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Tue, 7 May 2024 14:53:24 +0000
|
|
Subject: [PATCH 35/63] s3:libsmb: allow store_cldap_reply() to work with a
|
|
ipv6 response
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15642
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
|
|
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
|
|
Autobuild-Date(master): Fri May 10 01:35:18 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 712ffbffc03c7dcd551c1e22815ebe7c0b9b45d2)
|
|
---
|
|
source3/libsmb/dsgetdcname.c | 24 +++++++++++++++++++++++-
|
|
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
|
|
index 6fcaa26810c..da173e7bbb0 100644
|
|
--- a/source3/libsmb/dsgetdcname.c
|
|
+++ b/source3/libsmb/dsgetdcname.c
|
|
@@ -196,7 +196,29 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
|
|
/* FIXME */
|
|
r->sockaddr_size = 0x10; /* the w32 winsock addr size */
|
|
r->sockaddr.sockaddr_family = 2; /* AF_INET */
|
|
- r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
|
|
+ if (is_ipaddress_v4(addr)) {
|
|
+ r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
|
|
+ if (r->sockaddr.pdc_ip == NULL) {
|
|
+ return NT_STATUS_NO_MEMORY;
|
|
+ }
|
|
+ } else {
|
|
+ /*
|
|
+ * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX will
|
|
+ * fail with an ipv6 address.
|
|
+ *
|
|
+ * This matches windows behaviour in the CLDAP
|
|
+ * response when NETLOGON_NT_VERSION_5EX_WITH_IP
|
|
+ * is used.
|
|
+ *
|
|
+ * Windows returns the ipv4 address of the ipv6
|
|
+ * server interface and falls back to 127.0.0.1
|
|
+ * if there's no ipv4 address.
|
|
+ */
|
|
+ r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, "127.0.0.1");
|
|
+ if (r->sockaddr.pdc_ip == NULL) {
|
|
+ return NT_STATUS_NO_MEMORY;
|
|
+ }
|
|
+ }
|
|
|
|
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
|
|
(ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e4d5269b2359c670acdf0cba81248f148ae68c17 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Fri, 11 Oct 2024 13:32:22 +0000
|
|
Subject: [PATCH 36/63] s3:libsmb: let discover_dc_netbios() return
|
|
DOMAIN_CONTROLLER_NOT_FOUND
|
|
|
|
We may get NT_STATUS_NOT_FOUND when the name can't be resolved
|
|
and NT_STATUS_INVALID_ADDRESS if the system doesn't have ipv4
|
|
addresses...
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit e47ce1d10b13d8ef165c70984e6e490f4c2a64c2)
|
|
---
|
|
source3/libsmb/dsgetdcname.c | 14 +++++++++++++-
|
|
1 file changed, 13 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
|
|
index da173e7bbb0..8278959dd7d 100644
|
|
--- a/source3/libsmb/dsgetdcname.c
|
|
+++ b/source3/libsmb/dsgetdcname.c
|
|
@@ -483,7 +483,19 @@ static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
|
|
&count,
|
|
resolve_order);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
|
|
+ NTSTATUS raw_status = status;
|
|
+
|
|
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
|
+ status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
|
|
+ }
|
|
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_ADDRESS)) {
|
|
+ status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
|
|
+ }
|
|
+
|
|
+ DBG_DEBUG("failed to find DC for %s: %s => %s\n",
|
|
+ domain_name,
|
|
+ nt_errstr(raw_status),
|
|
+ nt_errstr(status));
|
|
return status;
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From d90d2b0e985913247f43192cb94eec0efb3e9046 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
|
|
Date: Wed, 2 Jul 2025 21:59:48 +0200
|
|
Subject: [PATCH 37/63] s3-winbindd: Fix internal winbind dsgetdcname calls
|
|
w.r.t. domain name
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
when winbind calls to dsgetdcname internally, make sure to
|
|
prefer the DNS domain name if we have it. Makes DNS lookups much more
|
|
likely to succeed.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15876
|
|
|
|
Guenther
|
|
|
|
Signed-off-by: Guenther Deschner <gd@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Ralph Boehme <slow@samba.org>
|
|
|
|
Autobuild-User(master): Ralph Böhme <slow@samba.org>
|
|
Autobuild-Date(master): Mon Jul 7 10:44:37 UTC 2025 on atb-devel-224
|
|
|
|
(cherry picked from commit 2560c9b3224816ffd371a62103f65b3aca301ad5)
|
|
---
|
|
source3/winbindd/wb_queryuser.c | 17 +++++++++++++----
|
|
source3/winbindd/wb_sids2xids.c | 17 +++++++++++++----
|
|
source3/winbindd/wb_xids2sids.c | 12 +++++++++---
|
|
source3/winbindd/winbindd_dual.c | 6 +++++-
|
|
source3/winbindd/winbindd_proto.h | 1 +
|
|
source3/winbindd/winbindd_util.c | 19 +++++++++++++++++++
|
|
6 files changed, 60 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c
|
|
index c2758f1b76a..db8e946ba71 100644
|
|
--- a/source3/winbindd/wb_queryuser.c
|
|
+++ b/source3/winbindd/wb_queryuser.c
|
|
@@ -289,10 +289,19 @@ static void wb_queryuser_done(struct tevent_req *subreq)
|
|
|
|
if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) &&
|
|
!state->tried_dclookup) {
|
|
- D_DEBUG("GetNssInfo got DOMAIN_CONTROLLER_NOT_FOUND, calling wb_dsgetdcname_send()\n");
|
|
- subreq = wb_dsgetdcname_send(
|
|
- state, state->ev, state->info->domain_name, NULL, NULL,
|
|
- DS_RETURN_DNS_NAME);
|
|
+ const char *domain_name = find_dns_domain_name(
|
|
+ state->info->domain_name);
|
|
+
|
|
+ D_DEBUG("GetNssInfo got DOMAIN_CONTROLLER_NOT_FOUND, calling "
|
|
+ "wb_dsgetdcname_send(%s)\n",
|
|
+ domain_name);
|
|
+
|
|
+ subreq = wb_dsgetdcname_send(state,
|
|
+ state->ev,
|
|
+ domain_name,
|
|
+ NULL,
|
|
+ NULL,
|
|
+ DS_RETURN_DNS_NAME);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return;
|
|
}
|
|
diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
|
|
index f0f6c23fc20..03e5e7e0258 100644
|
|
--- a/source3/winbindd/wb_sids2xids.c
|
|
+++ b/source3/winbindd/wb_sids2xids.c
|
|
@@ -612,13 +612,22 @@ static void wb_sids2xids_done(struct tevent_req *subreq)
|
|
!state->tried_dclookup) {
|
|
|
|
struct lsa_DomainInfo *d;
|
|
+ const char *domain_name = NULL;
|
|
|
|
- D_DEBUG("Domain controller not found. Calling wb_dsgetdcname_send() to get it.\n");
|
|
d = &state->idmap_doms.domains[state->dom_index];
|
|
|
|
- subreq = wb_dsgetdcname_send(
|
|
- state, state->ev, d->name.string, NULL, NULL,
|
|
- DS_RETURN_DNS_NAME);
|
|
+ domain_name = find_dns_domain_name(d->name.string);
|
|
+
|
|
+ D_DEBUG("Domain controller not found. Calling "
|
|
+ "wb_dsgetdcname_send(%s) to get it.\n",
|
|
+ domain_name);
|
|
+
|
|
+ subreq = wb_dsgetdcname_send(state,
|
|
+ state->ev,
|
|
+ domain_name,
|
|
+ NULL,
|
|
+ NULL,
|
|
+ DS_RETURN_DNS_NAME);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return;
|
|
}
|
|
diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c
|
|
index 86bd7f9deab..6fcf524d94f 100644
|
|
--- a/source3/winbindd/wb_xids2sids.c
|
|
+++ b/source3/winbindd/wb_xids2sids.c
|
|
@@ -143,9 +143,15 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq)
|
|
if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) &&
|
|
!state->tried_dclookup) {
|
|
|
|
- subreq = wb_dsgetdcname_send(
|
|
- state, state->ev, state->dom_map->name, NULL, NULL,
|
|
- DS_RETURN_DNS_NAME);
|
|
+ const char *domain_name = find_dns_domain_name(
|
|
+ state->dom_map->name);
|
|
+
|
|
+ subreq = wb_dsgetdcname_send(state,
|
|
+ state->ev,
|
|
+ domain_name,
|
|
+ NULL,
|
|
+ NULL,
|
|
+ DS_RETURN_DNS_NAME);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return;
|
|
}
|
|
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
|
|
index 36562ab10b8..02a10e41537 100644
|
|
--- a/source3/winbindd/winbindd_dual.c
|
|
+++ b/source3/winbindd/winbindd_dual.c
|
|
@@ -532,6 +532,7 @@ static void wb_domain_request_trigger(struct tevent_req *req,
|
|
struct wb_domain_request_state *state = tevent_req_data(
|
|
req, struct wb_domain_request_state);
|
|
struct winbindd_domain *domain = state->domain;
|
|
+ const char *domain_name = NULL;
|
|
struct tevent_req *subreq = NULL;
|
|
size_t shortest_queue_length;
|
|
|
|
@@ -604,8 +605,11 @@ static void wb_domain_request_trigger(struct tevent_req *req,
|
|
* which is indicated by DS_RETURN_DNS_NAME.
|
|
* For NT4 domains we still get the netbios name.
|
|
*/
|
|
+
|
|
+ domain_name = find_dns_domain_name(state->domain->name);
|
|
+
|
|
subreq = wb_dsgetdcname_send(state, state->ev,
|
|
- state->domain->name,
|
|
+ domain_name,
|
|
NULL, /* domain_guid */
|
|
NULL, /* site_name */
|
|
DS_RETURN_DNS_NAME); /* flags */
|
|
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
|
|
index 9b10f2c061a..4f7dc8a15d6 100644
|
|
--- a/source3/winbindd/winbindd_proto.h
|
|
+++ b/source3/winbindd/winbindd_proto.h
|
|
@@ -567,6 +567,7 @@ bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
|
|
struct dom_sid **sids, uint32_t *num_sids);
|
|
bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
|
|
struct unixid **pxids, uint32_t *pnum_xids);
|
|
+const char *find_dns_domain_name(const char *domain_name);
|
|
|
|
/* The following definitions come from winbindd/winbindd_wins.c */
|
|
|
|
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
|
|
index fe93528787d..eca4116d0c8 100644
|
|
--- a/source3/winbindd/winbindd_util.c
|
|
+++ b/source3/winbindd/winbindd_util.c
|
|
@@ -2181,3 +2181,22 @@ fail:
|
|
TALLOC_FREE(xids);
|
|
return false;
|
|
}
|
|
+
|
|
+/**
|
|
+ * Helper to extract the DNS Domain Name from a struct winbindd_domain
|
|
+ */
|
|
+const char *find_dns_domain_name(const char *domain_name)
|
|
+{
|
|
+ struct winbindd_domain *wbdom = NULL;
|
|
+
|
|
+ wbdom = find_domain_from_name(domain_name);
|
|
+ if (wbdom == NULL) {
|
|
+ return domain_name;
|
|
+ }
|
|
+
|
|
+ if (wbdom->active_directory && wbdom->alt_name != NULL) {
|
|
+ return wbdom->alt_name;
|
|
+ }
|
|
+
|
|
+ return wbdom->name;
|
|
+}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7da6072ce95bca445368f6d0453247c8f92fcdf2 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Fri, 9 May 2025 09:38:41 +0200
|
|
Subject: [PATCH 38/63] s3:winbindd: avoid using any netlogon call to get a dc
|
|
name
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15876
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
Reviewed-by: Ralph Boehme <slow@samba.org>
|
|
(backported from commit f86a4bf6848ade2db7229d182576db3320c3ece7)
|
|
---
|
|
source3/winbindd/winbindd_cm.c | 145 ---------------------------
|
|
source3/winbindd/winbindd_dual_srv.c | 105 +------------------
|
|
2 files changed, 5 insertions(+), 245 deletions(-)
|
|
|
|
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
|
|
index 2ebfb0f6dd8..195259daa43 100644
|
|
--- a/source3/winbindd/winbindd_cm.c
|
|
+++ b/source3/winbindd/winbindd_cm.c
|
|
@@ -475,135 +475,6 @@ static bool cm_is_ipc_credentials(struct cli_credentials *creds)
|
|
return ret;
|
|
}
|
|
|
|
-static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
|
|
- fstring dcname,
|
|
- struct sockaddr_storage *dc_ss,
|
|
- uint32_t request_flags)
|
|
-{
|
|
- struct winbindd_domain *our_domain = NULL;
|
|
- struct rpc_pipe_client *netlogon_pipe = NULL;
|
|
- NTSTATUS result;
|
|
- WERROR werr;
|
|
- TALLOC_CTX *mem_ctx;
|
|
- unsigned int orig_timeout;
|
|
- const char *tmp = NULL;
|
|
- const char *p;
|
|
- struct dcerpc_binding_handle *b;
|
|
-
|
|
- /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
|
|
- * moment.... */
|
|
-
|
|
- if (IS_DC) {
|
|
- return False;
|
|
- }
|
|
-
|
|
- if (domain->primary) {
|
|
- return False;
|
|
- }
|
|
-
|
|
- our_domain = find_our_domain();
|
|
-
|
|
- if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
|
|
- return False;
|
|
- }
|
|
-
|
|
- result = cm_connect_netlogon(our_domain, &netlogon_pipe);
|
|
- if (!NT_STATUS_IS_OK(result)) {
|
|
- talloc_destroy(mem_ctx);
|
|
- return False;
|
|
- }
|
|
-
|
|
- b = netlogon_pipe->binding_handle;
|
|
-
|
|
- /* This call can take a long time - allow the server to time out.
|
|
- 35 seconds should do it. */
|
|
-
|
|
- orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
|
|
-
|
|
- if (our_domain->active_directory) {
|
|
- struct netr_DsRGetDCNameInfo *domain_info = NULL;
|
|
-
|
|
- /*
|
|
- * TODO request flags are not respected in the server
|
|
- * (and in some cases, like REQUIRE_PDC, causes an error)
|
|
- */
|
|
- result = dcerpc_netr_DsRGetDCName(b,
|
|
- mem_ctx,
|
|
- our_domain->dcname,
|
|
- domain->name,
|
|
- NULL,
|
|
- NULL,
|
|
- request_flags|DS_RETURN_DNS_NAME,
|
|
- &domain_info,
|
|
- &werr);
|
|
- if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
|
|
- tmp = talloc_strdup(
|
|
- mem_ctx, domain_info->dc_unc);
|
|
- if (tmp == NULL) {
|
|
- DEBUG(0, ("talloc_strdup failed\n"));
|
|
- talloc_destroy(mem_ctx);
|
|
- return false;
|
|
- }
|
|
- if (domain->alt_name == NULL) {
|
|
- domain->alt_name = talloc_strdup(domain,
|
|
- domain_info->domain_name);
|
|
- if (domain->alt_name == NULL) {
|
|
- DEBUG(0, ("talloc_strdup failed\n"));
|
|
- talloc_destroy(mem_ctx);
|
|
- return false;
|
|
- }
|
|
- }
|
|
- if (domain->forest_name == NULL) {
|
|
- domain->forest_name = talloc_strdup(domain,
|
|
- domain_info->forest_name);
|
|
- if (domain->forest_name == NULL) {
|
|
- DEBUG(0, ("talloc_strdup failed\n"));
|
|
- talloc_destroy(mem_ctx);
|
|
- return false;
|
|
- }
|
|
- }
|
|
- }
|
|
- } else {
|
|
- result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
|
|
- our_domain->dcname,
|
|
- domain->name,
|
|
- &tmp,
|
|
- &werr);
|
|
- }
|
|
-
|
|
- /* And restore our original timeout. */
|
|
- rpccli_set_timeout(netlogon_pipe, orig_timeout);
|
|
-
|
|
- if (!NT_STATUS_IS_OK(result)) {
|
|
- DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
|
|
- nt_errstr(result)));
|
|
- talloc_destroy(mem_ctx);
|
|
- return false;
|
|
- }
|
|
-
|
|
- if (!W_ERROR_IS_OK(werr)) {
|
|
- DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
|
|
- win_errstr(werr)));
|
|
- talloc_destroy(mem_ctx);
|
|
- return false;
|
|
- }
|
|
-
|
|
- /* dcerpc_netr_GetAnyDCName gives us a name with \\ */
|
|
- p = strip_hostname(tmp);
|
|
-
|
|
- fstrcpy(dcname, p);
|
|
-
|
|
- talloc_destroy(mem_ctx);
|
|
-
|
|
- DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
|
|
-
|
|
- if (!resolve_name(dcname, dc_ss, 0x20, true)) {
|
|
- return False;
|
|
- }
|
|
-
|
|
- return True;
|
|
-}
|
|
-
|
|
/**
|
|
* Helper function to assemble trust password and account name
|
|
*/
|
|
@@ -1279,24 +1150,8 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
|
|
struct samba_sockaddr *sa_list = NULL;
|
|
size_t salist_size = 0;
|
|
size_t i;
|
|
- bool is_our_domain;
|
|
enum security_types sec = (enum security_types)lp_security();
|
|
|
|
- is_our_domain = strequal(domain->name, lp_workgroup());
|
|
-
|
|
- /* If not our domain, get the preferred DC, by asking our primary DC */
|
|
- if ( !is_our_domain
|
|
- && get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
|
|
- && add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
|
|
- num_dcs) )
|
|
- {
|
|
- char addr[INET6_ADDRSTRLEN];
|
|
- print_sockaddr(addr, sizeof(addr), &ss);
|
|
- DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
|
|
- dcname, addr));
|
|
- return True;
|
|
- }
|
|
-
|
|
if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
|
|
char *sitename = NULL;
|
|
|
|
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
|
|
index f0fd18a8fa6..47c68257b12 100644
|
|
--- a/source3/winbindd/winbindd_dual_srv.c
|
|
+++ b/source3/winbindd/winbindd_dual_srv.c
|
|
@@ -662,106 +662,11 @@ NTSTATUS _wbint_QueryUserRidList(struct pipes_struct *p,
|
|
|
|
NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
|
|
{
|
|
- struct winbindd_domain *domain = wb_child_domain();
|
|
- struct rpc_pipe_client *netlogon_pipe;
|
|
- struct netr_DsRGetDCNameInfo *dc_info;
|
|
- NTSTATUS status;
|
|
- WERROR werr;
|
|
- unsigned int orig_timeout;
|
|
- struct dcerpc_binding_handle *b;
|
|
- bool retry = false;
|
|
- bool try_dsrgetdcname = false;
|
|
-
|
|
- if (domain == NULL) {
|
|
- return dsgetdcname(p->mem_ctx, global_messaging_context(),
|
|
- r->in.domain_name, r->in.domain_guid,
|
|
- r->in.site_name ? r->in.site_name : "",
|
|
- r->in.flags,
|
|
- r->out.dc_info);
|
|
- }
|
|
-
|
|
- if (domain->active_directory) {
|
|
- try_dsrgetdcname = true;
|
|
- }
|
|
-
|
|
-reconnect:
|
|
- status = cm_connect_netlogon(domain, &netlogon_pipe);
|
|
-
|
|
- reset_cm_connection_on_error(domain, NULL, status);
|
|
- if (!NT_STATUS_IS_OK(status)) {
|
|
- DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
|
|
- return status;
|
|
- }
|
|
-
|
|
- b = netlogon_pipe->binding_handle;
|
|
-
|
|
- /* This call can take a long time - allow the server to time out.
|
|
- 35 seconds should do it. */
|
|
-
|
|
- orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
|
|
-
|
|
- if (try_dsrgetdcname) {
|
|
- status = dcerpc_netr_DsRGetDCName(b,
|
|
- p->mem_ctx, domain->dcname,
|
|
- r->in.domain_name, NULL, r->in.domain_guid,
|
|
- r->in.flags, r->out.dc_info, &werr);
|
|
- if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
|
|
- goto done;
|
|
- }
|
|
- if (!retry &&
|
|
- reset_cm_connection_on_error(domain, NULL, status))
|
|
- {
|
|
- retry = true;
|
|
- goto reconnect;
|
|
- }
|
|
- try_dsrgetdcname = false;
|
|
- retry = false;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Fallback to less capable methods
|
|
- */
|
|
-
|
|
- dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
|
|
- if (dc_info == NULL) {
|
|
- status = NT_STATUS_NO_MEMORY;
|
|
- goto done;
|
|
- }
|
|
-
|
|
- if (r->in.flags & DS_PDC_REQUIRED) {
|
|
- status = dcerpc_netr_GetDcName(b,
|
|
- p->mem_ctx, domain->dcname,
|
|
- r->in.domain_name, &dc_info->dc_unc, &werr);
|
|
- } else {
|
|
- status = dcerpc_netr_GetAnyDCName(b,
|
|
- p->mem_ctx, domain->dcname,
|
|
- r->in.domain_name, &dc_info->dc_unc, &werr);
|
|
- }
|
|
-
|
|
- if (!retry && reset_cm_connection_on_error(domain, b, status)) {
|
|
- retry = true;
|
|
- goto reconnect;
|
|
- }
|
|
- if (!NT_STATUS_IS_OK(status)) {
|
|
- DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
|
|
- nt_errstr(status)));
|
|
- goto done;
|
|
- }
|
|
- if (!W_ERROR_IS_OK(werr)) {
|
|
- DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
|
|
- win_errstr(werr)));
|
|
- status = werror_to_ntstatus(werr);
|
|
- goto done;
|
|
- }
|
|
-
|
|
- *r->out.dc_info = dc_info;
|
|
- status = NT_STATUS_OK;
|
|
-
|
|
-done:
|
|
- /* And restore our original timeout. */
|
|
- rpccli_set_timeout(netlogon_pipe, orig_timeout);
|
|
-
|
|
- return status;
|
|
+ return dsgetdcname(p->mem_ctx, global_messaging_context(),
|
|
+ r->in.domain_name, r->in.domain_guid,
|
|
+ r->in.site_name ? r->in.site_name : "",
|
|
+ r->in.flags,
|
|
+ r->out.dc_info);
|
|
}
|
|
|
|
NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From ad54ceadacfbcf0d9c96ad773e50db96003e2c08 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Wed, 23 Jul 2025 15:09:21 +0200
|
|
Subject: [PATCH 39/63] s3:winbindd: Resolve dc name using CLDAP also for
|
|
ROLE_IPA_DC
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
server role ROLE_IPA_DC (introduced in e2d5b4d) needs special handling
|
|
in dcip_check_name(). We should resolve the DC name using:
|
|
- CLDAP in dcip_check_name_ads()
|
|
instead of:
|
|
- NETBIOS in nbt_getdc() that fails if Windows is not providing netbios.
|
|
|
|
The impacted environment has:
|
|
|
|
domain->alt_name = example.com
|
|
domain->active_directory = 1
|
|
security = USER
|
|
server role = ROLE_IPA_DC
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15891
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Signed-off-by: Andreas Schneider <asn@samba.org>
|
|
Pair-programmed-with: Andreas Schneider <asn@samba.org>
|
|
|
|
Reviewed-by: Alexander Bokovoy <ab@samba.org>
|
|
(cherry picked from commit 4921c3304e5e0480e5bb80a757b3f04b3b92c3b1)
|
|
(cherry picked from commit fe8eafc289dfbb6f2b6c706f2a8a68186807d4f8)
|
|
---
|
|
source3/winbindd/winbindd_cm.c | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
|
|
index 195259daa43..86dbf68f033 100644
|
|
--- a/source3/winbindd/winbindd_cm.c
|
|
+++ b/source3/winbindd/winbindd_cm.c
|
|
@@ -1075,7 +1075,9 @@ static bool dcip_check_name(TALLOC_CTX *mem_ctx,
|
|
|
|
if ((lp_security() == SEC_ADS) && (domain->alt_name != NULL)) {
|
|
is_ad_domain = true;
|
|
- } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
|
|
+ } else if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC ||
|
|
+ lp_server_role() == ROLE_IPA_DC)
|
|
+ {
|
|
is_ad_domain = domain->active_directory;
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From b73efffbb02903427af2c2cc57171d4848ca11f8 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Mon, 4 Aug 2025 08:35:29 +0200
|
|
Subject: [PATCH 40/63] docs-xml: Make smb.conf 'server role' value consistent
|
|
with ROLE_IPA_DC in libparam
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15891
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Alexander Bokovoy <ab@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit d88268102ade07fab345e04109818d97d8843a14)
|
|
(cherry picked from commit d14fa6eb96a9f296d386ff4864e4f016440f2ac8)
|
|
---
|
|
docs-xml/smbdotconf/security/serverrole.xml | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/docs-xml/smbdotconf/security/serverrole.xml b/docs-xml/smbdotconf/security/serverrole.xml
|
|
index 4ea4e4751ee..40244e125ce 100644
|
|
--- a/docs-xml/smbdotconf/security/serverrole.xml
|
|
+++ b/docs-xml/smbdotconf/security/serverrole.xml
|
|
@@ -78,7 +78,7 @@
|
|
url="http://wiki.samba.org/index.php/Samba4/HOWTO">Samba4
|
|
HOWTO</ulink></para>
|
|
|
|
- <para><anchor id="IPA-DC"/><emphasis>SERVER ROLE = IPA DOMAIN CONTROLLER</emphasis></para>
|
|
+ <para><anchor id="IPA-DC"/><emphasis>SERVER ROLE = IPA PRIMARY DOMAIN CONTROLLER</emphasis></para>
|
|
|
|
<para>This mode of operation runs Samba in a hybrid mode for IPA
|
|
domain controller, providing forest trust to Active Directory.
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 832a4e31630fd441f8ab4325439f90d561cb8fa4 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Mon, 4 Aug 2025 23:26:02 +0200
|
|
Subject: [PATCH 41/63] s3:netlogon: IPA DC is the PDC as well - allow
|
|
ROLE_IPA_DC in _netr_DsRGetForestTrustInformation()
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15891
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Alexander Bokovoy <ab@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(cherry picked from commit 1dbafcc4e4ff8f39af5ca737b30e9821413dd1f2)
|
|
(cherry picked from commit 00adb3104e745babb2c330fa9c9e324805395edb)
|
|
---
|
|
source3/rpc_server/netlogon/srv_netlog_nt.c | 5 ++++-
|
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
|
|
index c5a4b0ef30c..7957d3ab34d 100644
|
|
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
|
|
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
|
|
@@ -2613,7 +2613,10 @@ WERROR _netr_DsRGetForestTrustInformation(struct pipes_struct *p,
|
|
return WERR_INVALID_FLAGS;
|
|
}
|
|
|
|
- if ((r->in.flags & DS_GFTI_UPDATE_TDO) && (lp_server_role() != ROLE_DOMAIN_PDC)) {
|
|
+ if ((r->in.flags & DS_GFTI_UPDATE_TDO) &&
|
|
+ (lp_server_role() != ROLE_DOMAIN_PDC) &&
|
|
+ (lp_server_role() != ROLE_IPA_DC))
|
|
+ {
|
|
p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
|
|
return WERR_NERR_NOTPRIMARY;
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 8d5638581dfc539c8524d7a507e8cc8977e827a2 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
|
Date: Mon, 4 Aug 2025 23:28:24 +0200
|
|
Subject: [PATCH 42/63] s3:utils: Allow ROLE_IPA_DC to allow to use Kerberos in
|
|
gensec
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15891
|
|
|
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
|
Reviewed-by: Alexander Bokovoy <ab@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
Autobuild-Date(master): Tue Aug 5 14:51:51 UTC 2025 on atb-devel-224
|
|
|
|
(cherry picked from commit a4dff82e45308db3ccabac2a55c03d52f04d7b4d)
|
|
|
|
Autobuild-User(v4-22-test): Jule Anger <janger@samba.org>
|
|
Autobuild-Date(v4-22-test): Mon Aug 11 07:53:47 UTC 2025 on atb-devel-224
|
|
|
|
(cherry picked from commit 3364797676624aa9367076a69b2daf73870429ba)
|
|
---
|
|
source3/utils/ntlm_auth.c | 6 +++++-
|
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
|
|
index cff3c53845f..2968ca47734 100644
|
|
--- a/source3/utils/ntlm_auth.c
|
|
+++ b/source3/utils/ntlm_auth.c
|
|
@@ -1341,7 +1341,11 @@ static NTSTATUS ntlm_auth_prepare_gensec_server(TALLOC_CTX *mem_ctx,
|
|
|
|
cli_credentials_set_conf(server_credentials, lp_ctx);
|
|
|
|
- if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) {
|
|
+ if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC ||
|
|
+ lp_server_role() == ROLE_IPA_DC ||
|
|
+ lp_security() == SEC_ADS ||
|
|
+ USE_KERBEROS_KEYTAB)
|
|
+ {
|
|
cli_credentials_set_kerberos_state(server_credentials,
|
|
CRED_USE_KERBEROS_DESIRED,
|
|
CRED_SPECIFIED);
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 3ef02a381cdc83549506e159ebc457730c06c547 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 22 Jul 2025 19:22:31 +0200
|
|
Subject: [PATCH 43/63] libads: fix get_kdc_ip_string()
|
|
|
|
Correctly handle the interaction between optionally passed in DC via
|
|
pss and DC lookup.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15876
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 23f100f67c0586a940e91e9e1e6f42b804401322)
|
|
---
|
|
source3/libads/kerberos.c | 11 ++++++++---
|
|
1 file changed, 8 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
|
|
index f74d8eb567c..f324321c87b 100644
|
|
--- a/source3/libads/kerberos.c
|
|
+++ b/source3/libads/kerberos.c
|
|
@@ -523,10 +523,12 @@ static char *get_kdc_ip_string(char *mem_ctx,
|
|
DBG_DEBUG("%zu additional KDCs to test\n", num_dcs);
|
|
if (num_dcs == 0) {
|
|
/*
|
|
- * We do not have additional KDCs, but we have the one passed
|
|
- * in via `pss`. So just use that one and leave.
|
|
+ * We do not have additional KDCs, but if we have one passed
|
|
+ * in via `pss` just use that one, otherwise fail
|
|
*/
|
|
- result = talloc_move(mem_ctx, &kdc_str);
|
|
+ if (pss != NULL) {
|
|
+ result = talloc_move(mem_ctx, &kdc_str);
|
|
+ }
|
|
goto out;
|
|
}
|
|
|
|
@@ -567,6 +569,9 @@ static char *get_kdc_ip_string(char *mem_ctx,
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
DEBUG(10,("get_kdc_ip_string: cldap_multi_netlogon failed: "
|
|
"%s\n", nt_errstr(status)));
|
|
+ if (pss != NULL) {
|
|
+ result = talloc_move(mem_ctx, &kdc_str);
|
|
+ }
|
|
goto out;
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From b0dbc167f85deabff2af5b18bc201e8db0d3b97d Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 22 Jul 2025 19:16:14 +0200
|
|
Subject: [PATCH 44/63] winbindd: use find_domain_from_name_noinit() in
|
|
find_dns_domain_name()
|
|
|
|
Avoid triggering a connection to a DC of a trusted domain.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15876
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 9ad2e59a464bb472da2071c61a254547b6497625)
|
|
---
|
|
source3/winbindd/winbindd_util.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
|
|
index eca4116d0c8..3a7a9114988 100644
|
|
--- a/source3/winbindd/winbindd_util.c
|
|
+++ b/source3/winbindd/winbindd_util.c
|
|
@@ -2189,7 +2189,7 @@ const char *find_dns_domain_name(const char *domain_name)
|
|
{
|
|
struct winbindd_domain *wbdom = NULL;
|
|
|
|
- wbdom = find_domain_from_name(domain_name);
|
|
+ wbdom = find_domain_from_name_noinit(domain_name);
|
|
if (wbdom == NULL) {
|
|
return domain_name;
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 1961f54ce07f7dc3cfcae5c00b96b39109f08b3a Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 19 Dec 2023 11:11:55 +0100
|
|
Subject: [PATCH 45/63] vfs_default: allow disabling /proc/fds and
|
|
RESOLVE_NO_SYMLINK at compile time
|
|
|
|
This will be used in CI to have a gitlab runner without all modern Linux
|
|
features we make use of as part of path processing:
|
|
|
|
- O_PATH
|
|
- openat2() with RESOLVE_NO_SYMLINKS
|
|
- somehow safely reopen an O_PATH file handle
|
|
|
|
That gives what a classix UNIX like AIX or Solaris offers feature wise.
|
|
|
|
Other OSes support other combinations of those features, but we leave the
|
|
exersize of possibly adding more runners supporting those combinations to the
|
|
reader.
|
|
|
|
The following list shows which features are available and used by Samba on a few
|
|
OSes:
|
|
|
|
| O_PATH | RESOLVE_NO_SYMLINKS | Safe reopen | CI covered
|
|
--------|----------------|---------------------|----------------------------
|
|
| Supported Used | Supported Used | Supported Used |
|
|
============================================================================
|
|
Linux | + + | + + | + + | +
|
|
FreeBSD | + + | + [1] - | + [2] - | -
|
|
AIX | - - | - - | - - | +
|
|
|
|
[1] via open() flag O_RESOLVE_BENEATH
|
|
[2] via open() flag O_EMPTY_PATH
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
(cherry picked from commit 5c2f96442a25a1725809a28b3719afbc0bd01830)
|
|
---
|
|
source3/modules/vfs_default.c | 6 ++++++
|
|
1 file changed, 6 insertions(+)
|
|
|
|
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
|
|
index 1d4b9b1a840..8d78831492f 100644
|
|
--- a/source3/modules/vfs_default.c
|
|
+++ b/source3/modules/vfs_default.c
|
|
@@ -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 */
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 26de62a2a968dd5b73af296251b26112cdd533e5 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 19 Dec 2023 11:12:49 +0100
|
|
Subject: [PATCH 46/63] CI: disable /proc/fds and RESOLVE_NO_SYMLINK in
|
|
samba-no-opath-build runner
|
|
|
|
This is a more sensible combination of missing Linux specific features:
|
|
|
|
- O_PATH
|
|
- openat2() with RESOLVE_NO_SYMLINKS
|
|
- somehow safely reopen an O_PATH file handle
|
|
|
|
Currently only O_PATH is disabled for these jobs, but that doesn't really match
|
|
and know OS.
|
|
|
|
The following list shows which features are available and used by Samba on a few
|
|
OSes:
|
|
|
|
| O_PATH | RESOLVE_NO_SYMLINKS | Safe reopen | CI covered
|
|
--------|----------------|---------------------|----------------------------
|
|
| Supported Used | Supported Used | Supported Used |
|
|
============================================================================
|
|
Linux | + + | + + | + + | +
|
|
FreeBSD | + + | + [1] - | + [2] - | -
|
|
AIX | - - | - - | - - | +
|
|
|
|
So by also disabling RESOLVE_NO_SYMLINKS and Safe Reopen, we cover classic UNIX
|
|
systems like AIX.
|
|
|
|
[1] via open() flag O_RESOLVE_BENEATH
|
|
[2] via open() flag O_EMPTY_PATH
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
(cherry picked from commit 62cbe145c7e500c4759ed2005c78bd5056c87f43)
|
|
---
|
|
script/autobuild.py | 2 +-
|
|
selftest/skip.opath-required | 6 ++++++
|
|
2 files changed, 7 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/script/autobuild.py b/script/autobuild.py
|
|
index e074c39d3c0..85043032d73 100755
|
|
--- a/script/autobuild.py
|
|
+++ b/script/autobuild.py
|
|
@@ -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 ."),
|
|
diff --git a/selftest/skip.opath-required b/selftest/skip.opath-required
|
|
index c3a13f5ec6e..67764a0b027 100644
|
|
--- a/selftest/skip.opath-required
|
|
+++ b/selftest/skip.opath-required
|
|
@@ -14,3 +14,9 @@
|
|
# 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.test_symlink_traversal.*\(fileserver\)
|
|
+^samba3.blackbox.shadow_copy_torture.*\(fileserver\)
|
|
+^samba3.blackbox.virus_scanner.*\(fileserver:local\)
|
|
+^samba3.blackbox.shadow_copy2.*\(fileserver.*\)
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 2c27aae5a4c8d7368dc142fb2be36919296d2a02 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 2 Jan 2024 12:49:14 +0100
|
|
Subject: [PATCH 47/63] smbd: pass symlink target path to
|
|
safe_symlink_target_path()
|
|
|
|
Moves processing the symlink error response to the caller
|
|
filename_convert_dirfsp(). Prepares for using this in
|
|
non_widelink_open(), where it will replace symlink_target_below_conn()
|
|
with the same functionality.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
(back-ported from commit 0515dded4ddb49e5570ae7df51126af1a2d643de)
|
|
---
|
|
source3/include/proto.h | 5 +++
|
|
source3/smbd/filename.c | 72 +++++++++++++++++++----------------------
|
|
2 files changed, 38 insertions(+), 39 deletions(-)
|
|
|
|
diff --git a/source3/include/proto.h b/source3/include/proto.h
|
|
index 8eed81d8f2e..13240033bf1 100644
|
|
--- a/source3/include/proto.h
|
|
+++ b/source3/include/proto.h
|
|
@@ -719,6 +719,11 @@ 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 *target,
|
|
+ size_t unparsed,
|
|
+ char **_relative);
|
|
NTSTATUS filename_convert_dirfsp(
|
|
TALLOC_CTX *ctx,
|
|
connection_struct *conn,
|
|
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
|
|
index 8693dcf1153..45fb90381e2 100644
|
|
--- a/source3/smbd/filename.c
|
|
+++ b/source3/smbd/filename.c
|
|
@@ -942,44 +942,34 @@ static char *symlink_target_path(
|
|
return ret;
|
|
}
|
|
|
|
-static NTSTATUS safe_symlink_target_path(
|
|
- TALLOC_CTX *mem_ctx,
|
|
- const char *connectpath,
|
|
- const char *name_in,
|
|
- const char *substitute,
|
|
- size_t unparsed,
|
|
- char **_name_out)
|
|
+NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
|
|
+ const char *connectpath,
|
|
+ const char *target,
|
|
+ size_t unparsed,
|
|
+ char **_relative)
|
|
{
|
|
- char *target = NULL;
|
|
char *abs_target = NULL;
|
|
char *abs_target_canon = NULL;
|
|
const char *relative = NULL;
|
|
- char *name_out = NULL;
|
|
- NTSTATUS status = NT_STATUS_NO_MEMORY;
|
|
bool in_share;
|
|
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
|
|
|
|
- target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
|
|
- if (target == NULL) {
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- DBG_DEBUG("name_in: %s, substitute: %s, unparsed: %zu, target=%s\n",
|
|
- name_in,
|
|
- substitute,
|
|
- unparsed,
|
|
- target);
|
|
+ DBG_DEBUG("connectpath [%s] target [%s] unparsed [%zu]\n",
|
|
+ connectpath, target, unparsed);
|
|
|
|
if (target[0] == '/') {
|
|
- abs_target = target;
|
|
+ abs_target = talloc_strdup(mem_ctx, target);
|
|
} else {
|
|
- abs_target = talloc_asprintf(
|
|
- target, "%s/%s", connectpath, target);
|
|
- if (abs_target == NULL) {
|
|
- goto fail;
|
|
- }
|
|
+ abs_target = talloc_asprintf(mem_ctx,
|
|
+ "%s/%s",
|
|
+ connectpath,
|
|
+ target);
|
|
+ }
|
|
+ if (abs_target == NULL) {
|
|
+ goto fail;
|
|
}
|
|
|
|
- abs_target_canon = canonicalize_absolute_path(target, abs_target);
|
|
+ abs_target_canon = canonicalize_absolute_path(abs_target, abs_target);
|
|
if (abs_target_canon == NULL) {
|
|
goto fail;
|
|
}
|
|
@@ -994,15 +984,14 @@ static NTSTATUS safe_symlink_target_path(
|
|
goto fail;
|
|
}
|
|
|
|
- name_out = talloc_strdup(mem_ctx, relative);
|
|
- if (name_out == NULL) {
|
|
+ *_relative = talloc_strdup(mem_ctx, relative);
|
|
+ if (*_relative == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
status = NT_STATUS_OK;
|
|
- *_name_out = name_out;
|
|
fail:
|
|
- TALLOC_FREE(target);
|
|
+ TALLOC_FREE(abs_target);
|
|
return status;
|
|
}
|
|
|
|
@@ -1438,6 +1427,7 @@ NTSTATUS filename_convert_dirfsp(
|
|
size_t unparsed = 0;
|
|
NTSTATUS status;
|
|
char *target = NULL;
|
|
+ char *safe_target = NULL;
|
|
size_t symlink_redirects = 0;
|
|
|
|
next:
|
|
@@ -1476,17 +1466,21 @@ next:
|
|
* resolve all symlinks locally.
|
|
*/
|
|
|
|
- status = safe_symlink_target_path(
|
|
- mem_ctx,
|
|
- conn->connectpath,
|
|
- name_in,
|
|
- substitute,
|
|
- unparsed,
|
|
- &target);
|
|
+ target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
|
|
+ if (target == NULL) {
|
|
+ return NT_STATUS_NO_MEMORY;
|
|
+ }
|
|
+
|
|
+ status = safe_symlink_target_path(mem_ctx,
|
|
+ conn->connectpath,
|
|
+ target,
|
|
+ unparsed,
|
|
+ &safe_target);
|
|
+ TALLOC_FREE(target);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
- name_in = target;
|
|
+ name_in = safe_target;
|
|
|
|
symlink_redirects += 1;
|
|
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 99d7e841d4e18f760c137530bbed0dea6115311a Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 2 Jan 2024 13:25:25 +0100
|
|
Subject: [PATCH 48/63] smbd: add a directory argument to
|
|
safe_symlink_target_path()
|
|
|
|
Existing caller passes NULL, no change in behaviour. Prepares for
|
|
replacing symlink_target_below_conn() in open.c.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
(cherry picked from commit fc80c72d658a41fe4d93b24b793b52c91b350175)
|
|
---
|
|
source3/include/proto.h | 1 +
|
|
source3/smbd/filename.c | 15 ++++++++++++++-
|
|
2 files changed, 15 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/source3/include/proto.h b/source3/include/proto.h
|
|
index 13240033bf1..15c5839caf8 100644
|
|
--- a/source3/include/proto.h
|
|
+++ b/source3/include/proto.h
|
|
@@ -721,6 +721,7 @@ struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
|
|
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);
|
|
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
|
|
index 45fb90381e2..55a49e0ba93 100644
|
|
--- a/source3/smbd/filename.c
|
|
+++ b/source3/smbd/filename.c
|
|
@@ -944,6 +944,7 @@ static char *symlink_target_path(
|
|
|
|
NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
|
|
const char *connectpath,
|
|
+ const char *dir,
|
|
const char *target,
|
|
size_t unparsed,
|
|
char **_relative)
|
|
@@ -959,10 +960,21 @@ NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
|
|
|
|
if (target[0] == '/') {
|
|
abs_target = talloc_strdup(mem_ctx, target);
|
|
- } else {
|
|
+ } else if (dir == NULL) {
|
|
+ abs_target = talloc_asprintf(mem_ctx,
|
|
+ "%s/%s",
|
|
+ connectpath,
|
|
+ target);
|
|
+ } else if (dir[0] == '/') {
|
|
abs_target = talloc_asprintf(mem_ctx,
|
|
"%s/%s",
|
|
+ dir,
|
|
+ target);
|
|
+ } else {
|
|
+ abs_target = talloc_asprintf(mem_ctx,
|
|
+ "%s/%s/%s",
|
|
connectpath,
|
|
+ dir,
|
|
target);
|
|
}
|
|
if (abs_target == NULL) {
|
|
@@ -1473,6 +1485,7 @@ next:
|
|
|
|
status = safe_symlink_target_path(mem_ctx,
|
|
conn->connectpath,
|
|
+ NULL,
|
|
target,
|
|
unparsed,
|
|
&safe_target);
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 5041a6fa5cdfd21bf697249d900ea5c107d355a2 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 2 Jan 2024 14:34:26 +0100
|
|
Subject: [PATCH 49/63] smbd: use safe_symlink_target_path() in
|
|
symlink_target_below_conn()
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
(cherry picked from commit 1965fc77b3852a0593e13897af08f5304a1ce3a2)
|
|
---
|
|
selftest/skip.opath-required | 2 -
|
|
source3/smbd/open.c | 73 +++++++-----------------------------
|
|
2 files changed, 14 insertions(+), 61 deletions(-)
|
|
|
|
diff --git a/selftest/skip.opath-required b/selftest/skip.opath-required
|
|
index 67764a0b027..9c6ba481cdf 100644
|
|
--- a/selftest/skip.opath-required
|
|
+++ b/selftest/skip.opath-required
|
|
@@ -16,7 +16,5 @@
|
|
^samba.tests.smb1posix
|
|
|
|
# These don't work without /proc/fd support
|
|
-^samba3.blackbox.test_symlink_traversal.*\(fileserver\)
|
|
^samba3.blackbox.shadow_copy_torture.*\(fileserver\)
|
|
^samba3.blackbox.virus_scanner.*\(fileserver:local\)
|
|
-^samba3.blackbox.shadow_copy2.*\(fileserver.*\)
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index 74be444fef5..6582bd60245 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -571,7 +571,6 @@ out:
|
|
static NTSTATUS symlink_target_below_conn(
|
|
TALLOC_CTX *mem_ctx,
|
|
const char *connection_path,
|
|
- size_t connection_path_len,
|
|
struct files_struct *fsp,
|
|
struct files_struct *dirfsp,
|
|
struct smb_filename *symlink_name,
|
|
@@ -579,9 +578,7 @@ static NTSTATUS symlink_target_below_conn(
|
|
{
|
|
char *target = NULL;
|
|
char *absolute = NULL;
|
|
- const char *relative = NULL;
|
|
NTSTATUS status;
|
|
- bool ok;
|
|
|
|
if (fsp_get_pathref_fd(fsp) != -1) {
|
|
/*
|
|
@@ -594,69 +591,28 @@ static NTSTATUS symlink_target_below_conn(
|
|
talloc_tos(), dirfsp, symlink_name, &target);
|
|
}
|
|
|
|
+ status = safe_symlink_target_path(talloc_tos(),
|
|
+ connection_path,
|
|
+ dirfsp->fsp_name->base_name,
|
|
+ target,
|
|
+ 0,
|
|
+ &absolute);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- DBG_DEBUG("readlink_talloc failed: %s\n", nt_errstr(status));
|
|
+ DBG_DEBUG("safe_symlink_target_path() failed: %s\n",
|
|
+ nt_errstr(status));
|
|
return status;
|
|
}
|
|
|
|
- if (target[0] != '/') {
|
|
- char *tmp = talloc_asprintf(
|
|
- talloc_tos(),
|
|
- "%s/%s/%s",
|
|
- connection_path,
|
|
- dirfsp->fsp_name->base_name,
|
|
- target);
|
|
-
|
|
- TALLOC_FREE(target);
|
|
-
|
|
- if (tmp == NULL) {
|
|
- return NT_STATUS_NO_MEMORY;
|
|
- }
|
|
- target = tmp;
|
|
- }
|
|
-
|
|
- DBG_DEBUG("redirecting to %s\n", target);
|
|
-
|
|
- absolute = canonicalize_absolute_path(talloc_tos(), target);
|
|
- TALLOC_FREE(target);
|
|
-
|
|
- if (absolute == NULL) {
|
|
- return NT_STATUS_NO_MEMORY;
|
|
- }
|
|
-
|
|
- /*
|
|
- * We're doing the "below connection_path" here because it's
|
|
- * cheap. It might be that we get a symlink out of the share,
|
|
- * pointing to yet another symlink getting us back into the
|
|
- * share. If we need that, we would have to remove the check
|
|
- * here.
|
|
- */
|
|
- ok = subdir_of(
|
|
- connection_path,
|
|
- connection_path_len,
|
|
- absolute,
|
|
- &relative);
|
|
- if (!ok) {
|
|
- DBG_NOTICE("Bad access attempt: %s is a symlink "
|
|
- "outside the share path\n"
|
|
- "conn_rootdir =%s\n"
|
|
- "resolved_name=%s\n",
|
|
- symlink_name->base_name,
|
|
- connection_path,
|
|
- absolute);
|
|
- TALLOC_FREE(absolute);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
- }
|
|
-
|
|
- if (relative[0] == '\0') {
|
|
+ if (absolute[0] == '\0') {
|
|
/*
|
|
* special case symlink to share root: "." is our
|
|
* share root filename
|
|
*/
|
|
- absolute[0] = '.';
|
|
- absolute[1] = '\0';
|
|
- } else {
|
|
- memmove(absolute, relative, strlen(relative)+1);
|
|
+ TALLOC_FREE(absolute);
|
|
+ absolute = talloc_strdup(talloc_tos(), ".");
|
|
+ if (absolute == NULL) {
|
|
+ return NT_STATUS_NO_MEMORY;
|
|
+ }
|
|
}
|
|
|
|
*_target = absolute;
|
|
@@ -834,7 +790,6 @@ again:
|
|
status = symlink_target_below_conn(
|
|
talloc_tos(),
|
|
connpath,
|
|
- connpath_len,
|
|
fsp,
|
|
discard_const_p(files_struct, dirfsp),
|
|
smb_fname_rel,
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From f2fc99f0c7d441115a486413f345c0226a00b38b Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Mon, 18 Dec 2023 12:35:58 +0100
|
|
Subject: [PATCH 50/63] smbd: use dirfsp and atname in open_directory()
|
|
|
|
On systems without /proc/fd support this avoid the expensive chdir()
|
|
logic in non_widelink_open(). open_file_ntcreate() already passes
|
|
dirfsp and atname to reopen_from_fsp(), it was just missed in the
|
|
conversion.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
|
|
Reviewed-by: Volker Lendecke <vl@samba.org>
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
|
|
Autobuild-User(master): Volker Lendecke <vl@samba.org>
|
|
Autobuild-Date(master): Mon Jan 22 12:00:56 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 2713023250f15cf9971d88620cab9dd4afd0dc73)
|
|
|
|
Autobuild-User(v4-19-test): Jule Anger <janger@samba.org>
|
|
Autobuild-Date(v4-19-test): Mon Jan 29 11:59:41 UTC 2024 on atb-devel-224
|
|
---
|
|
source3/smbd/open.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index 6582bd60245..b9849f82396 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -4865,8 +4865,8 @@ static NTSTATUS open_directory(connection_struct *conn,
|
|
|
|
if (access_mask & need_fd_access) {
|
|
status = reopen_from_fsp(
|
|
- fsp->conn->cwd_fsp,
|
|
- fsp->fsp_name,
|
|
+ parent_dir_fname->fsp,
|
|
+ smb_fname_atname,
|
|
fsp,
|
|
O_RDONLY | O_DIRECTORY,
|
|
0,
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 7d102268ebbebf6fc723a43485a82f72069d00ee Mon Sep 17 00:00:00 2001
|
|
From: Volker Lendecke <vl@samba.org>
|
|
Date: Fri, 16 Dec 2022 16:35:00 +0100
|
|
Subject: [PATCH 51/63] smbd: Return open_symlink_err from
|
|
filename_convert_dirfsp_nosymlink()
|
|
|
|
Don't lose information returned from openat_pathref_fsp_nosymlink()
|
|
|
|
Signed-off-by: Volker Lendecke <vl@samba.org>
|
|
Reviewed-by: Ralph Boehme <slow@samba.org>
|
|
(backported from commit c81d1d3fe4e3aeb2761dc539e8fb87d2ad862e5f)
|
|
Related to: https://bugzilla.samba.org/show_bug.cgi?id=15549
|
|
---
|
|
source3/smbd/filename.c | 77 +++++++++++++++++------------------------
|
|
1 file changed, 32 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
|
|
index 55a49e0ba93..9fd85af992a 100644
|
|
--- a/source3/smbd/filename.c
|
|
+++ b/source3/smbd/filename.c
|
|
@@ -944,37 +944,35 @@ static char *symlink_target_path(
|
|
|
|
NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
|
|
const char *connectpath,
|
|
- const char *dir,
|
|
- const char *target,
|
|
+ const char *name_in,
|
|
+ const char *substitute,
|
|
size_t unparsed,
|
|
char **_relative)
|
|
{
|
|
+ char *target = NULL;
|
|
char *abs_target = NULL;
|
|
char *abs_target_canon = NULL;
|
|
const char *relative = NULL;
|
|
bool in_share;
|
|
NTSTATUS status = NT_STATUS_NO_MEMORY;
|
|
|
|
+ target = symlink_target_path(mem_ctx,
|
|
+ name_in,
|
|
+ substitute,
|
|
+ unparsed);
|
|
+ if (target == NULL) {
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
DBG_DEBUG("connectpath [%s] target [%s] unparsed [%zu]\n",
|
|
connectpath, target, unparsed);
|
|
|
|
if (target[0] == '/') {
|
|
- abs_target = talloc_strdup(mem_ctx, target);
|
|
- } else if (dir == NULL) {
|
|
- abs_target = talloc_asprintf(mem_ctx,
|
|
- "%s/%s",
|
|
- connectpath,
|
|
- target);
|
|
- } else if (dir[0] == '/') {
|
|
- abs_target = talloc_asprintf(mem_ctx,
|
|
- "%s/%s",
|
|
- dir,
|
|
- target);
|
|
+ abs_target = target;
|
|
} else {
|
|
- abs_target = talloc_asprintf(mem_ctx,
|
|
- "%s/%s/%s",
|
|
+ abs_target = talloc_asprintf(target,
|
|
+ "%s/%s",
|
|
connectpath,
|
|
- dir,
|
|
target);
|
|
}
|
|
if (abs_target == NULL) {
|
|
@@ -1019,8 +1017,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
|
|
NTTIME twrp,
|
|
struct files_struct **_dirfsp,
|
|
struct smb_filename **_smb_fname,
|
|
- char **_substitute,
|
|
- size_t *_unparsed)
|
|
+ struct open_symlink_err **_symlink_err)
|
|
{
|
|
struct smb_filename *smb_dirname = NULL;
|
|
struct smb_filename *smb_fname_rel = NULL;
|
|
@@ -1142,11 +1139,8 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
|
|
|
|
SMB_ASSERT(name_in_len >= dirname_len);
|
|
|
|
- *_substitute = talloc_move(
|
|
- mem_ctx,
|
|
- &symlink_err->reparse->substitute_name);
|
|
- *_unparsed = symlink_err->unparsed +
|
|
- (name_in_len - dirname_len);
|
|
+ symlink_err->unparsed += (name_in_len - dirname_len);
|
|
+ *_symlink_err = symlink_err;
|
|
|
|
goto fail;
|
|
}
|
|
@@ -1435,10 +1429,9 @@ NTSTATUS filename_convert_dirfsp(
|
|
struct files_struct **_dirfsp,
|
|
struct smb_filename **_smb_fname)
|
|
{
|
|
- char *substitute = NULL;
|
|
- size_t unparsed = 0;
|
|
+ struct open_symlink_err *symlink_err = NULL;
|
|
NTSTATUS status;
|
|
- char *target = NULL;
|
|
+ char *substitute = NULL;
|
|
char *safe_target = NULL;
|
|
size_t symlink_redirects = 0;
|
|
|
|
@@ -1447,16 +1440,14 @@ next:
|
|
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
|
}
|
|
|
|
- status = filename_convert_dirfsp_nosymlink(
|
|
- mem_ctx,
|
|
- conn,
|
|
- name_in,
|
|
- ucf_flags,
|
|
- twrp,
|
|
- _dirfsp,
|
|
- _smb_fname,
|
|
- &substitute,
|
|
- &unparsed);
|
|
+ status = filename_convert_dirfsp_nosymlink(mem_ctx,
|
|
+ conn,
|
|
+ name_in,
|
|
+ ucf_flags,
|
|
+ twrp,
|
|
+ _dirfsp,
|
|
+ _smb_fname,
|
|
+ &symlink_err);
|
|
|
|
if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
|
|
return status;
|
|
@@ -1477,19 +1468,15 @@ next:
|
|
* UCF_POSIX_PATHNAMES set to cause the client to
|
|
* resolve all symlinks locally.
|
|
*/
|
|
-
|
|
- target = symlink_target_path(mem_ctx, name_in, substitute, unparsed);
|
|
- if (target == NULL) {
|
|
- return NT_STATUS_NO_MEMORY;
|
|
- }
|
|
+ substitute = symlink_err->reparse->substitute_name;
|
|
|
|
status = safe_symlink_target_path(mem_ctx,
|
|
conn->connectpath,
|
|
- NULL,
|
|
- target,
|
|
- unparsed,
|
|
+ name_in,
|
|
+ substitute,
|
|
+ symlink_err->unparsed,
|
|
&safe_target);
|
|
- TALLOC_FREE(target);
|
|
+ TALLOC_FREE(symlink_err);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From edaabc3d53fddd9e2fa6168c8bf01ebfbf229657 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Thu, 25 Apr 2024 15:24:57 +0200
|
|
Subject: [PATCH 52/63] s3/lib: add next helper variable in server_id_watch_*
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit d76edcd48437715c7541b5b1e6a56245c25f460b)
|
|
---
|
|
source3/lib/server_id_watch.c | 14 ++++++++++----
|
|
1 file changed, 10 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/source3/lib/server_id_watch.c b/source3/lib/server_id_watch.c
|
|
index f0189e0e896..50b35f27b3e 100644
|
|
--- a/source3/lib/server_id_watch.c
|
|
+++ b/source3/lib/server_id_watch.c
|
|
@@ -27,6 +27,7 @@
|
|
struct server_id_watch_state {
|
|
struct tevent_context *ev;
|
|
struct server_id pid;
|
|
+ struct timeval start;
|
|
};
|
|
|
|
static void server_id_watch_waited(struct tevent_req *subreq);
|
|
@@ -37,6 +38,7 @@ struct tevent_req *server_id_watch_send(TALLOC_CTX *mem_ctx,
|
|
{
|
|
struct tevent_req *req, *subreq;
|
|
struct server_id_watch_state *state;
|
|
+ struct timeval next;
|
|
|
|
req = tevent_req_create(mem_ctx, &state, struct server_id_watch_state);
|
|
if (req == NULL) {
|
|
@@ -44,14 +46,15 @@ struct tevent_req *server_id_watch_send(TALLOC_CTX *mem_ctx,
|
|
}
|
|
state->ev = ev;
|
|
state->pid = pid;
|
|
+ state->start = tevent_timeval_current();
|
|
|
|
if (!serverid_exists(&state->pid)) {
|
|
tevent_req_done(req);
|
|
return tevent_req_post(req, ev);
|
|
}
|
|
|
|
- subreq = tevent_wakeup_send(
|
|
- state, ev, tevent_timeval_current_ofs(0, 500000));
|
|
+ next = tevent_timeval_add(&state->start, 0, 500000);
|
|
+ subreq = tevent_wakeup_send(state, ev, next);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return tevent_req_post(req, ev);
|
|
}
|
|
@@ -66,6 +69,8 @@ static void server_id_watch_waited(struct tevent_req *subreq)
|
|
subreq, struct tevent_req);
|
|
struct server_id_watch_state *state = tevent_req_data(
|
|
req, struct server_id_watch_state);
|
|
+ struct timeval now;
|
|
+ struct timeval next;
|
|
bool ok;
|
|
|
|
ok = tevent_wakeup_recv(subreq);
|
|
@@ -80,8 +85,9 @@ static void server_id_watch_waited(struct tevent_req *subreq)
|
|
return;
|
|
}
|
|
|
|
- subreq = tevent_wakeup_send(
|
|
- state, state->ev, tevent_timeval_current_ofs(0, 500000));
|
|
+ now = tevent_timeval_current();
|
|
+ next = tevent_timeval_add(&now, 0, 500000);
|
|
+ subreq = tevent_wakeup_send(state, state->ev, next);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return;
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From c25f1811c2ccaa2d5cc8005597fb9979aa1102ee Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Thu, 4 Apr 2024 12:31:05 +0200
|
|
Subject: [PATCH 53/63] s3/lib: add option "serverid watch:debug = yes" to
|
|
print kernel stack of hanging process
|
|
|
|
We only do if sys_have_proc_fds() returns true, so it's most likely
|
|
linux...
|
|
|
|
Enabled by default with log level 10...
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 5c57e840527432c4b1a7ec94894939022a9e9622)
|
|
---
|
|
source3/lib/server_id_watch.c | 62 +++++++++++++++++++++++++++++++++--
|
|
1 file changed, 59 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/source3/lib/server_id_watch.c b/source3/lib/server_id_watch.c
|
|
index 50b35f27b3e..c372ec8c431 100644
|
|
--- a/source3/lib/server_id_watch.c
|
|
+++ b/source3/lib/server_id_watch.c
|
|
@@ -17,17 +17,18 @@
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
-#include "replace.h"
|
|
-#include <tevent.h>
|
|
-#include <talloc.h>
|
|
+#include "includes.h"
|
|
#include "serverid.h"
|
|
#include "server_id_watch.h"
|
|
+#include "lib/util/server_id.h"
|
|
#include "lib/util/tevent_unix.h"
|
|
|
|
struct server_id_watch_state {
|
|
struct tevent_context *ev;
|
|
struct server_id pid;
|
|
struct timeval start;
|
|
+ struct timeval warn;
|
|
+ bool debug;
|
|
};
|
|
|
|
static void server_id_watch_waited(struct tevent_req *subreq);
|
|
@@ -47,6 +48,12 @@ struct tevent_req *server_id_watch_send(TALLOC_CTX *mem_ctx,
|
|
state->ev = ev;
|
|
state->pid = pid;
|
|
state->start = tevent_timeval_current();
|
|
+ state->warn = tevent_timeval_add(&state->start, 10, 0);
|
|
+
|
|
+ state->debug = lp_parm_bool(GLOBAL_SECTION_SNUM,
|
|
+ "serverid watch",
|
|
+ "debug",
|
|
+ CHECK_DEBUGLVL(DBGLVL_DEBUG));
|
|
|
|
if (!serverid_exists(&state->pid)) {
|
|
tevent_req_done(req);
|
|
@@ -86,6 +93,55 @@ static void server_id_watch_waited(struct tevent_req *subreq)
|
|
}
|
|
|
|
now = tevent_timeval_current();
|
|
+
|
|
+ if (!state->debug) {
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ if (timeval_compare(&state->warn, &now) == -1) {
|
|
+ double duration = timeval_elapsed2(&state->start, &now);
|
|
+ char proc_path[64] = { 0, };
|
|
+ char *kstack = NULL;
|
|
+ struct server_id_buf buf;
|
|
+ const char *pid = server_id_str_buf(state->pid, &buf);
|
|
+ int ret;
|
|
+
|
|
+ state->warn = tevent_timeval_add(&now, 10, 0);
|
|
+
|
|
+ if (!procid_is_local(&state->pid) || !sys_have_proc_fds()) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n",
|
|
+ pid, duration);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ ret = snprintf(proc_path,
|
|
+ ARRAY_SIZE(proc_path),
|
|
+ "/proc/%" PRIu64 "/stack",
|
|
+ state->pid.pid);
|
|
+ if (ret < 0) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "snprintf failed\n",
|
|
+ pid, duration);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ become_root();
|
|
+ kstack = file_load(proc_path, NULL, 0, state);
|
|
+ unbecome_root();
|
|
+ if (kstack == NULL) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "file_load [%s] failed\n",
|
|
+ pid, duration, proc_path);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "%s:\n%s",
|
|
+ pid, duration, proc_path, kstack);
|
|
+ TALLOC_FREE(kstack);
|
|
+ }
|
|
+
|
|
+next:
|
|
next = tevent_timeval_add(&now, 0, 500000);
|
|
subreq = tevent_wakeup_send(state, state->ev, next);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 23dbf8f0317810d65e716a3c9b947c7a6549cb46 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Thu, 25 Apr 2024 15:17:08 +0200
|
|
Subject: [PATCH 54/63] s3/lib: add option "serverid watch:debug script"
|
|
|
|
This takes just PID and NODE:PID on a cluster.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 7add7dbf1aee13b4d9ab70d1a5312c8ff30d9e00)
|
|
---
|
|
source3/lib/server_id_watch.c | 52 +++++++++++++++++++++++++++++++++++
|
|
1 file changed, 52 insertions(+)
|
|
|
|
diff --git a/source3/lib/server_id_watch.c b/source3/lib/server_id_watch.c
|
|
index c372ec8c431..8ddf9c6b1c8 100644
|
|
--- a/source3/lib/server_id_watch.c
|
|
+++ b/source3/lib/server_id_watch.c
|
|
@@ -100,6 +100,7 @@ static void server_id_watch_waited(struct tevent_req *subreq)
|
|
|
|
if (timeval_compare(&state->warn, &now) == -1) {
|
|
double duration = timeval_elapsed2(&state->start, &now);
|
|
+ const char *cmd = NULL;
|
|
char proc_path[64] = { 0, };
|
|
char *kstack = NULL;
|
|
struct server_id_buf buf;
|
|
@@ -108,6 +109,57 @@ static void server_id_watch_waited(struct tevent_req *subreq)
|
|
|
|
state->warn = tevent_timeval_add(&now, 10, 0);
|
|
|
|
+ cmd = lp_parm_const_string(GLOBAL_SECTION_SNUM,
|
|
+ "serverid watch",
|
|
+ "debug script",
|
|
+ NULL);
|
|
+ if (cmd != NULL) {
|
|
+ char *cmdstr = NULL;
|
|
+ char *output = NULL;
|
|
+ int fd;
|
|
+
|
|
+ /*
|
|
+ * Note in a cluster setup pid will be
|
|
+ * a NOTE:PID like '1:3978365'
|
|
+ *
|
|
+ * Without clustering it is just '3978365'
|
|
+ */
|
|
+ cmdstr = talloc_asprintf(state, "%s %s", cmd, pid);
|
|
+ if (cmdstr == NULL) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "talloc_asprintf failed\n",
|
|
+ pid, duration);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ become_root();
|
|
+ ret = smbrun(cmdstr, &fd, NULL);
|
|
+ unbecome_root();
|
|
+ if (ret != 0) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "smbrun('%s') failed\n",
|
|
+ pid, duration, cmdstr);
|
|
+ TALLOC_FREE(cmdstr);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ output = fd_load(fd, NULL, 0, state);
|
|
+ close(fd);
|
|
+ if (output == NULL) {
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "fd_load() of smbrun('%s') failed\n",
|
|
+ pid, duration, cmdstr);
|
|
+ TALLOC_FREE(cmdstr);
|
|
+ goto next;
|
|
+ }
|
|
+ DBG_ERR("Process %s hanging for %f seconds?\n"
|
|
+ "%s returned:\n%s",
|
|
+ pid, duration, cmdstr, output);
|
|
+ TALLOC_FREE(cmdstr);
|
|
+ TALLOC_FREE(output);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
if (!procid_is_local(&state->pid) || !sys_have_proc_fds()) {
|
|
DBG_ERR("Process %s hanging for %f seconds?\n",
|
|
pid, duration);
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 59975168627e4bfbd2e75a611cb8cb13019a7df3 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Fri, 5 Apr 2024 12:15:28 +0200
|
|
Subject: [PATCH 55/63] smbd: log share_mode_watch_recv() errors as errors
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit b45e78871aadca6ae33475bee890736838f44219)
|
|
---
|
|
source3/smbd/open.c | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index b9849f82396..da129119c7f 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -2969,8 +2969,9 @@ static void defer_open_done(struct tevent_req *req)
|
|
status = share_mode_watch_recv(req, NULL, NULL);
|
|
TALLOC_FREE(req);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- DEBUG(5, ("dbwrap_watched_watch_recv returned %s\n",
|
|
- nt_errstr(status)));
|
|
+ DBG_ERR("share_mode_watch_recv() returned %s, "
|
|
+ "rescheduling mid %" PRIu64 "\n",
|
|
+ nt_errstr(status), state->mid);
|
|
/*
|
|
* Even if it failed, retry anyway. TODO: We need a way to
|
|
* tell a re-scheduled open about that error.
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e619b72fe1b9c36963c452c1d102009b28e8e289 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Thu, 4 Apr 2024 19:18:19 +0200
|
|
Subject: [PATCH 56/63] smbd: add option "smbd lease break:debug hung procs"
|
|
|
|
By enabling this a process sending a lease break message to another process
|
|
holding a lease will start watching that process and if that process didn't
|
|
process the lease break within 10 seconds (cf server_id_watch_waited()), we log
|
|
a kernel stack backtrace of that process.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit d8613d7ee23c4e990285a387eb9ac2eeefff9749)
|
|
---
|
|
source3/smbd/open.c | 110 ++++++++++++++++++++++++++++++++++++++++----
|
|
1 file changed, 102 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
|
|
index da129119c7f..4cc5190f690 100644
|
|
--- a/source3/smbd/open.c
|
|
+++ b/source3/smbd/open.c
|
|
@@ -38,6 +38,7 @@
|
|
#include "serverid.h"
|
|
#include "messages.h"
|
|
#include "source3/lib/dbwrap/dbwrap_watch.h"
|
|
+#include "source3/lib/server_id_watch.h"
|
|
#include "locking/leases_db.h"
|
|
#include "librpc/gen_ndr/ndr_leases_db.h"
|
|
#include "lib/util/time_basic.h"
|
|
@@ -2472,6 +2473,10 @@ static int map_lease_type_to_oplock(uint32_t lease_type)
|
|
return result;
|
|
}
|
|
|
|
+struct blocker_debug_state {
|
|
+ size_t num_blockers;
|
|
+};
|
|
+
|
|
struct delay_for_oplock_state {
|
|
struct files_struct *fsp;
|
|
const struct smb2_lease *lease;
|
|
@@ -2483,8 +2488,22 @@ struct delay_for_oplock_state {
|
|
bool have_other_lease;
|
|
uint32_t total_lease_types;
|
|
bool delay;
|
|
+ struct blocker_debug_state *blocker_debug_state;
|
|
};
|
|
|
|
+static int blocker_debug_state_destructor(struct blocker_debug_state *state)
|
|
+{
|
|
+ if (state->num_blockers == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ DBG_DEBUG("blocker_debug_state [%p] num_blockers [%zu]\n",
|
|
+ state, state->num_blockers);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void delay_for_oplock_fn_watch_done(struct tevent_req *subreq);
|
|
+
|
|
static bool delay_for_oplock_fn(
|
|
struct share_mode_entry *e,
|
|
bool *modified,
|
|
@@ -2497,6 +2516,8 @@ static bool delay_for_oplock_fn(
|
|
uint32_t e_lease_type = SMB2_LEASE_NONE;
|
|
uint32_t break_to;
|
|
bool lease_is_breaking = false;
|
|
+ struct tevent_req *subreq = NULL;
|
|
+ struct server_id_buf idbuf = {};
|
|
|
|
if (e_is_lease) {
|
|
NTSTATUS status;
|
|
@@ -2636,9 +2657,56 @@ static bool delay_for_oplock_fn(
|
|
state->delay = true;
|
|
}
|
|
|
|
+ if (!state->delay) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (state->blocker_debug_state == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ subreq = server_id_watch_send(state->blocker_debug_state,
|
|
+ fsp->conn->sconn->ev_ctx,
|
|
+ e->pid);
|
|
+ if (subreq == NULL) {
|
|
+ DBG_ERR("server_id_watch_send(%s) returned NULL\n",
|
|
+ server_id_str_buf(e->pid, &idbuf));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ tevent_req_set_callback(subreq,
|
|
+ delay_for_oplock_fn_watch_done,
|
|
+ state->blocker_debug_state);
|
|
+
|
|
+ state->blocker_debug_state->num_blockers++;
|
|
+
|
|
+ DBG_DEBUG("Starting to watch pid [%s] state [%p] num_blockers [%zu]\n",
|
|
+ server_id_str_buf(e->pid, &idbuf),
|
|
+ state->blocker_debug_state,
|
|
+ state->blocker_debug_state->num_blockers);
|
|
+
|
|
return false;
|
|
};
|
|
|
|
+static void delay_for_oplock_fn_watch_done(struct tevent_req *subreq)
|
|
+{
|
|
+ struct blocker_debug_state *blocker_debug_state = tevent_req_callback_data(
|
|
+ subreq, struct blocker_debug_state);
|
|
+ struct server_id pid = {};
|
|
+ struct server_id_buf idbuf = {};
|
|
+ int ret;
|
|
+
|
|
+ ret = server_id_watch_recv(subreq, &pid);
|
|
+ if (ret != 0) {
|
|
+ DBG_ERR("server_id_watch_recv failed %s\n", strerror(ret));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ DBG_DEBUG("state [%p] server_id_watch_recv() returned pid [%s] exited\n",
|
|
+ blocker_debug_state,
|
|
+ server_id_str_buf(pid, &idbuf));
|
|
+}
|
|
+
|
|
static NTSTATUS delay_for_oplock(files_struct *fsp,
|
|
int oplock_request,
|
|
const struct smb2_lease *lease,
|
|
@@ -2647,7 +2715,8 @@ static NTSTATUS delay_for_oplock(files_struct *fsp,
|
|
uint32_t create_disposition,
|
|
bool first_open_attempt,
|
|
int *poplock_type,
|
|
- uint32_t *pgranted)
|
|
+ uint32_t *pgranted,
|
|
+ struct blocker_debug_state **blocker_debug_state)
|
|
{
|
|
struct delay_for_oplock_state state = {
|
|
.fsp = fsp,
|
|
@@ -2693,6 +2762,22 @@ static NTSTATUS delay_for_oplock(files_struct *fsp,
|
|
goto grant;
|
|
}
|
|
|
|
+ if (lp_parm_bool(GLOBAL_SECTION_SNUM,
|
|
+ "smbd lease break",
|
|
+ "debug hung procs",
|
|
+ false))
|
|
+ {
|
|
+ state.blocker_debug_state = talloc_zero(fsp,
|
|
+ struct blocker_debug_state);
|
|
+ if (state.blocker_debug_state == NULL) {
|
|
+ return NT_STATUS_NO_MEMORY;
|
|
+ }
|
|
+ talloc_steal(talloc_tos(), state.blocker_debug_state);
|
|
+
|
|
+ talloc_set_destructor(state.blocker_debug_state,
|
|
+ blocker_debug_state_destructor);
|
|
+ }
|
|
+
|
|
state.delay_mask = have_sharing_violation ?
|
|
SMB2_LEASE_HANDLE : SMB2_LEASE_WRITE;
|
|
|
|
@@ -2714,6 +2799,7 @@ static NTSTATUS delay_for_oplock(files_struct *fsp,
|
|
}
|
|
|
|
if (state.delay) {
|
|
+ *blocker_debug_state = state.blocker_debug_state;
|
|
return NT_STATUS_RETRY;
|
|
}
|
|
|
|
@@ -2827,7 +2913,8 @@ static NTSTATUS handle_share_mode_lease(
|
|
const struct smb2_lease *lease,
|
|
bool first_open_attempt,
|
|
int *poplock_type,
|
|
- uint32_t *pgranted)
|
|
+ uint32_t *pgranted,
|
|
+ struct blocker_debug_state **blocker_debug_state)
|
|
{
|
|
bool sharing_violation = false;
|
|
NTSTATUS status;
|
|
@@ -2868,7 +2955,8 @@ static NTSTATUS handle_share_mode_lease(
|
|
create_disposition,
|
|
first_open_attempt,
|
|
poplock_type,
|
|
- pgranted);
|
|
+ pgranted,
|
|
+ blocker_debug_state);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
@@ -2903,7 +2991,8 @@ static void defer_open_done(struct tevent_req *req);
|
|
static void defer_open(struct share_mode_lock *lck,
|
|
struct timeval timeout,
|
|
struct smb_request *req,
|
|
- struct file_id id)
|
|
+ struct file_id id,
|
|
+ struct blocker_debug_state **blocker_debug_state)
|
|
{
|
|
struct deferred_open_record *open_rec = NULL;
|
|
struct timeval abs_timeout;
|
|
@@ -2947,6 +3036,8 @@ static void defer_open(struct share_mode_lock *lck,
|
|
}
|
|
tevent_req_set_callback(watch_req, defer_open_done, watch_state);
|
|
|
|
+ talloc_move(watch_req, blocker_debug_state);
|
|
+
|
|
ok = tevent_req_set_endtime(watch_req, req->sconn->ev_ctx, abs_timeout);
|
|
if (!ok) {
|
|
exit_server("tevent_req_set_endtime failed");
|
|
@@ -3229,7 +3320,8 @@ static bool open_match_attributes(connection_struct *conn,
|
|
|
|
static void schedule_defer_open(struct share_mode_lock *lck,
|
|
struct file_id id,
|
|
- struct smb_request *req)
|
|
+ struct smb_request *req,
|
|
+ struct blocker_debug_state **blocker_debug_state)
|
|
{
|
|
/* This is a relative time, added to the absolute
|
|
request_time value to get the absolute timeout time.
|
|
@@ -3253,7 +3345,7 @@ static void schedule_defer_open(struct share_mode_lock *lck,
|
|
return;
|
|
}
|
|
|
|
- defer_open(lck, timeout, req, id);
|
|
+ defer_open(lck, timeout, req, id, blocker_debug_state);
|
|
}
|
|
|
|
/****************************************************************************
|
|
@@ -3315,6 +3407,7 @@ static NTSTATUS check_and_store_share_mode(
|
|
int oplock_type = NO_OPLOCK;
|
|
uint32_t granted_lease = 0;
|
|
const struct smb2_lease_key *lease_key = NULL;
|
|
+ struct blocker_debug_state *blocker_debug_state = NULL;
|
|
bool delete_on_close;
|
|
bool ok;
|
|
|
|
@@ -3337,9 +3430,10 @@ static NTSTATUS check_and_store_share_mode(
|
|
lease,
|
|
first_open_attempt,
|
|
&oplock_type,
|
|
- &granted_lease);
|
|
+ &granted_lease,
|
|
+ &blocker_debug_state);
|
|
if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
|
|
- schedule_defer_open(lck, fsp->file_id, req);
|
|
+ schedule_defer_open(lck, fsp->file_id, req, &blocker_debug_state);
|
|
return NT_STATUS_SHARING_VIOLATION;
|
|
}
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From e6a0d821ba28839728371ca94bb364dd6865b5dd Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Wed, 20 Mar 2024 14:27:27 +0100
|
|
Subject: [PATCH 57/63] smbd: move trace_state variable behind tv variable
|
|
|
|
Next commit adds timestamp variables to trace_state that want to be initialized
|
|
with the current time, so moving behind tv we can then just reuse tv for that.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 679e12aee2f0c283a6f9b9c6008c549a6ca9633e)
|
|
---
|
|
source3/smbd/smb2_process.c | 8 ++++----
|
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/source3/smbd/smb2_process.c b/source3/smbd/smb2_process.c
|
|
index fbbe4ef3992..188eaa14839 100644
|
|
--- a/source3/smbd/smb2_process.c
|
|
+++ b/source3/smbd/smb2_process.c
|
|
@@ -1783,10 +1783,6 @@ void smbd_process(struct tevent_context *ev_ctx,
|
|
int sock_fd,
|
|
bool interactive)
|
|
{
|
|
- struct smbd_tevent_trace_state trace_state = {
|
|
- .ev = ev_ctx,
|
|
- .frame = talloc_stackframe(),
|
|
- };
|
|
const struct loadparm_substitution *lp_sub =
|
|
loadparm_s3_global_substitution();
|
|
struct smbXsrv_client *client = NULL;
|
|
@@ -1797,6 +1793,10 @@ void smbd_process(struct tevent_context *ev_ctx,
|
|
int ret;
|
|
NTSTATUS status;
|
|
struct timeval tv = timeval_current();
|
|
+ struct smbd_tevent_trace_state trace_state = {
|
|
+ .ev = ev_ctx,
|
|
+ .frame = talloc_stackframe(),
|
|
+ };
|
|
NTTIME now = timeval_to_nttime(&tv);
|
|
char *chroot_dir = NULL;
|
|
int rc;
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 15276d7645255ddddf2a3bf6b7a429e3d40ec9b7 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Wed, 20 Mar 2024 14:28:43 +0100
|
|
Subject: [PATCH 58/63] smbd: add option "smbd:debug events" for tevent
|
|
handling duration threshold warnings
|
|
|
|
Can be used to enable printing an error message if tevent event handlers ran
|
|
longer then three seconds. Also logs a message with a loglevel of 3 if there
|
|
were no events at hall.
|
|
|
|
Enabled by default with 'log level = 10' or
|
|
'smbd profiling level = on'...
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 90d776cb18395ed804f0ab4fd13ef571fc0ad827)
|
|
---
|
|
source3/smbd/smb2_process.c | 64 +++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 64 insertions(+)
|
|
|
|
diff --git a/source3/smbd/smb2_process.c b/source3/smbd/smb2_process.c
|
|
index 188eaa14839..dbe91132f7f 100644
|
|
--- a/source3/smbd/smb2_process.c
|
|
+++ b/source3/smbd/smb2_process.c
|
|
@@ -1692,8 +1692,36 @@ struct smbd_tevent_trace_state {
|
|
struct tevent_context *ev;
|
|
TALLOC_CTX *frame;
|
|
SMBPROFILE_BASIC_ASYNC_STATE(profile_idle);
|
|
+ struct timeval before_wait_tv;
|
|
+ struct timeval after_wait_tv;
|
|
};
|
|
|
|
+static inline void smbd_tevent_trace_callback_before_wait(
|
|
+ struct smbd_tevent_trace_state *state)
|
|
+{
|
|
+ struct timeval now = timeval_current();
|
|
+ struct timeval diff;
|
|
+
|
|
+ diff = tevent_timeval_until(&state->after_wait_tv, &now);
|
|
+ if (diff.tv_sec > 3) {
|
|
+ DBG_ERR("Handling event took %ld seconds!\n", (long)diff.tv_sec);
|
|
+ }
|
|
+ state->before_wait_tv = now;
|
|
+}
|
|
+
|
|
+static inline void smbd_tevent_trace_callback_after_wait(
|
|
+ struct smbd_tevent_trace_state *state)
|
|
+{
|
|
+ struct timeval now = timeval_current();
|
|
+ struct timeval diff;
|
|
+
|
|
+ diff = tevent_timeval_until(&state->before_wait_tv, &now);
|
|
+ if (diff.tv_sec > 30) {
|
|
+ DBG_NOTICE("No event for %ld seconds!\n", (long)diff.tv_sec);
|
|
+ }
|
|
+ state->after_wait_tv = now;
|
|
+}
|
|
+
|
|
static inline void smbd_tevent_trace_callback_before_loop_once(
|
|
struct smbd_tevent_trace_state *state)
|
|
{
|
|
@@ -1729,6 +1757,30 @@ static void smbd_tevent_trace_callback(enum tevent_trace_point point,
|
|
errno = 0;
|
|
}
|
|
|
|
+static void smbd_tevent_trace_callback_debug(enum tevent_trace_point point,
|
|
+ void *private_data)
|
|
+{
|
|
+ struct smbd_tevent_trace_state *state =
|
|
+ (struct smbd_tevent_trace_state *)private_data;
|
|
+
|
|
+ switch (point) {
|
|
+ case TEVENT_TRACE_BEFORE_WAIT:
|
|
+ smbd_tevent_trace_callback_before_wait(state);
|
|
+ break;
|
|
+ case TEVENT_TRACE_AFTER_WAIT:
|
|
+ smbd_tevent_trace_callback_after_wait(state);
|
|
+ break;
|
|
+ case TEVENT_TRACE_BEFORE_LOOP_ONCE:
|
|
+ smbd_tevent_trace_callback_before_loop_once(state);
|
|
+ break;
|
|
+ case TEVENT_TRACE_AFTER_LOOP_ONCE:
|
|
+ smbd_tevent_trace_callback_after_loop_once(state);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ errno = 0;
|
|
+}
|
|
+
|
|
static void smbd_tevent_trace_callback_profile(enum tevent_trace_point point,
|
|
void *private_data)
|
|
{
|
|
@@ -1737,6 +1789,7 @@ static void smbd_tevent_trace_callback_profile(enum tevent_trace_point point,
|
|
|
|
switch (point) {
|
|
case TEVENT_TRACE_BEFORE_WAIT:
|
|
+ smbd_tevent_trace_callback_before_wait(state);
|
|
if (!smbprofile_dump_pending()) {
|
|
/*
|
|
* If there's no dump pending
|
|
@@ -1749,6 +1802,7 @@ static void smbd_tevent_trace_callback_profile(enum tevent_trace_point point,
|
|
SMBPROFILE_BASIC_ASYNC_START(idle, profile_p, state->profile_idle);
|
|
break;
|
|
case TEVENT_TRACE_AFTER_WAIT:
|
|
+ smbd_tevent_trace_callback_after_wait(state);
|
|
SMBPROFILE_BASIC_ASYNC_END(state->profile_idle);
|
|
if (!smbprofile_dump_pending()) {
|
|
/*
|
|
@@ -1796,7 +1850,13 @@ void smbd_process(struct tevent_context *ev_ctx,
|
|
struct smbd_tevent_trace_state trace_state = {
|
|
.ev = ev_ctx,
|
|
.frame = talloc_stackframe(),
|
|
+ .before_wait_tv = tv,
|
|
+ .after_wait_tv = tv,
|
|
};
|
|
+ bool debug = lp_parm_bool(GLOBAL_SECTION_SNUM,
|
|
+ "smbd",
|
|
+ "debug events",
|
|
+ CHECK_DEBUGLVL(DBGLVL_DEBUG));
|
|
NTTIME now = timeval_to_nttime(&tv);
|
|
char *chroot_dir = NULL;
|
|
int rc;
|
|
@@ -2041,6 +2101,10 @@ void smbd_process(struct tevent_context *ev_ctx,
|
|
tevent_set_trace_callback(ev_ctx,
|
|
smbd_tevent_trace_callback_profile,
|
|
&trace_state);
|
|
+ } else if (debug) {
|
|
+ tevent_set_trace_callback(ev_ctx,
|
|
+ smbd_tevent_trace_callback_debug,
|
|
+ &trace_state);
|
|
} else {
|
|
tevent_set_trace_callback(ev_ctx,
|
|
smbd_tevent_trace_callback,
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 4631b9d60a874db10dbdd52406d0094a7dbd1356 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Mon, 26 Aug 2024 14:11:02 +0200
|
|
Subject: [PATCH 59/63] vfs_error_inject: add 'error_inject:durable_reconnect =
|
|
st_ex_nlink'
|
|
|
|
This allows to simulate durable reconnect failures because the stat
|
|
information of the file changed.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 692ed832dfff61ad1c9b646b5c8d6f85f25efb99)
|
|
---
|
|
source3/modules/vfs_error_inject.c | 76 ++++++++++++++++++++++++++++++
|
|
1 file changed, 76 insertions(+)
|
|
|
|
diff --git a/source3/modules/vfs_error_inject.c b/source3/modules/vfs_error_inject.c
|
|
index 529504fd8d5..dcf0de0a2d9 100644
|
|
--- a/source3/modules/vfs_error_inject.c
|
|
+++ b/source3/modules/vfs_error_inject.c
|
|
@@ -19,6 +19,7 @@
|
|
|
|
#include "includes.h"
|
|
#include "smbd/smbd.h"
|
|
+#include "librpc/gen_ndr/ndr_open_files.h"
|
|
|
|
#undef DBGC_CLASS
|
|
#define DBGC_CLASS DBGC_VFS
|
|
@@ -204,11 +205,86 @@ static int vfs_error_inject_unlinkat(struct vfs_handle_struct *handle,
|
|
return -1;
|
|
}
|
|
|
|
+static NTSTATUS vfs_error_inject_durable_reconnect(struct vfs_handle_struct *handle,
|
|
+ struct smb_request *smb1req,
|
|
+ struct smbXsrv_open *op,
|
|
+ const DATA_BLOB old_cookie,
|
|
+ TALLOC_CTX *mem_ctx,
|
|
+ struct files_struct **fsp,
|
|
+ DATA_BLOB *new_cookie)
|
|
+{
|
|
+ const char *vfs_func = "durable_reconnect";
|
|
+ const char *err_str = NULL;
|
|
+ NTSTATUS status;
|
|
+ enum ndr_err_code ndr_err;
|
|
+ struct vfs_default_durable_cookie cookie;
|
|
+ DATA_BLOB modified_cookie = data_blob_null;
|
|
+
|
|
+ err_str = lp_parm_const_string(SNUM(handle->conn),
|
|
+ "error_inject",
|
|
+ vfs_func,
|
|
+ NULL);
|
|
+ if (err_str == NULL) {
|
|
+ return SMB_VFS_NEXT_DURABLE_RECONNECT(handle,
|
|
+ smb1req,
|
|
+ op,
|
|
+ old_cookie,
|
|
+ mem_ctx,
|
|
+ fsp,
|
|
+ new_cookie);
|
|
+ }
|
|
+
|
|
+ ndr_err = ndr_pull_struct_blob(&old_cookie, talloc_tos(), &cookie,
|
|
+ (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie);
|
|
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
+ status = ndr_map_error2ntstatus(ndr_err);
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ if (strcmp(cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) {
|
|
+ return NT_STATUS_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ if (cookie.version != VFS_DEFAULT_DURABLE_COOKIE_VERSION) {
|
|
+ return NT_STATUS_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ if (strequal(err_str, "st_ex_nlink")) {
|
|
+ cookie.stat_info.st_ex_nlink += 1;
|
|
+ } else {
|
|
+ DBG_ERR("Unknown error inject %s requested "
|
|
+ "for vfs function %s\n", err_str, vfs_func);
|
|
+ return SMB_VFS_NEXT_DURABLE_RECONNECT(handle,
|
|
+ smb1req,
|
|
+ op,
|
|
+ old_cookie,
|
|
+ mem_ctx,
|
|
+ fsp,
|
|
+ new_cookie);
|
|
+ }
|
|
+
|
|
+ ndr_err = ndr_push_struct_blob(&modified_cookie, talloc_tos(), &cookie,
|
|
+ (ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie);
|
|
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
+ status = ndr_map_error2ntstatus(ndr_err);
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return SMB_VFS_NEXT_DURABLE_RECONNECT(handle,
|
|
+ smb1req,
|
|
+ op,
|
|
+ modified_cookie,
|
|
+ mem_ctx,
|
|
+ fsp,
|
|
+ new_cookie);
|
|
+}
|
|
+
|
|
static struct vfs_fn_pointers vfs_error_inject_fns = {
|
|
.chdir_fn = vfs_error_inject_chdir,
|
|
.pwrite_fn = vfs_error_inject_pwrite,
|
|
.openat_fn = vfs_error_inject_openat,
|
|
.unlinkat_fn = vfs_error_inject_unlinkat,
|
|
+ .durable_reconnect_fn = vfs_error_inject_durable_reconnect,
|
|
};
|
|
|
|
static_decl_vfs;
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From c8e88652163cc56b1f9fb0926a140c81e6b7ec94 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Mon, 26 Aug 2024 14:42:02 +0200
|
|
Subject: [PATCH 60/63] s4:torture/smb2: add
|
|
smb2.durable-v2-regressions.durable_v2_reconnect_bug15624
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit ef4ef04e7f83b1029446ff8b5fc5fdf4ab33edbd)
|
|
---
|
|
selftest/skip | 1 +
|
|
source4/torture/smb2/durable_v2_open.c | 118 +++++++++++++++++++++++++
|
|
source4/torture/smb2/smb2.c | 2 +
|
|
3 files changed, 121 insertions(+)
|
|
|
|
diff --git a/selftest/skip b/selftest/skip
|
|
index e808367c00d..056c54ea287 100644
|
|
--- a/selftest/skip
|
|
+++ b/selftest/skip
|
|
@@ -149,3 +149,4 @@ bench # don't run benchmarks in our selftest
|
|
^samba.tests.reparsepoints.*
|
|
^samba.tests.smb2symlink.*
|
|
^samba3.blackbox.open-eintr.*
|
|
+smb2.durable-v2-regressions # Only used in blackbox tests
|
|
diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
|
|
index 9b9af11124c..7447dd287a4 100644
|
|
--- a/source4/torture/smb2/durable_v2_open.c
|
|
+++ b/source4/torture/smb2/durable_v2_open.c
|
|
@@ -2355,6 +2355,112 @@ done:
|
|
return ret;
|
|
}
|
|
|
|
+/**
|
|
+ * basic test for doing a durable open
|
|
+ * tcp disconnect, reconnect, do a durable reopen (succeeds)
|
|
+ */
|
|
+static bool test_durable_v2_reconnect_bug15624(struct torture_context *tctx,
|
|
+ struct smb2_tree *tree,
|
|
+ struct smb2_tree *tree2)
|
|
+{
|
|
+ NTSTATUS status;
|
|
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
|
|
+ char fname[256];
|
|
+ struct smb2_handle _h;
|
|
+ struct smb2_handle *h = NULL;
|
|
+ struct smb2_create io;
|
|
+ struct GUID create_guid = GUID_random();
|
|
+ struct smbcli_options options;
|
|
+ uint64_t previous_session_id;
|
|
+ uint8_t b = 0;
|
|
+ bool ret = true;
|
|
+ bool ok;
|
|
+
|
|
+ if (!torture_setting_bool(tctx, "bug15624", false)) {
|
|
+ torture_comment(tctx,
|
|
+ "share requires:\n"
|
|
+ "'vfs objects = error_inject'\n"
|
|
+ "'error_inject:durable_reconnect=st_ex_nlink'\n"
|
|
+ "test requires:\n"
|
|
+ "'--option=torture:bug15624=yes'\n");
|
|
+ torture_skip(tctx, "'--option=torture:bug15624=yes' missing");
|
|
+ }
|
|
+
|
|
+ options = tree->session->transport->options;
|
|
+ previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
|
|
+
|
|
+ /* Choose a random name in case the state is left a little funky. */
|
|
+ snprintf(fname,
|
|
+ sizeof(fname),
|
|
+ "durable_v2_reconnect_bug15624_%s.dat",
|
|
+ generate_random_str(tctx, 8));
|
|
+
|
|
+ smb2_util_unlink(tree, fname);
|
|
+
|
|
+ smb2_oplock_create_share(&io, fname,
|
|
+ smb2_util_share_access(""),
|
|
+ smb2_util_oplock_level("b"));
|
|
+ io.in.durable_open = false;
|
|
+ io.in.durable_open_v2 = true;
|
|
+ io.in.persistent_open = false;
|
|
+ io.in.create_guid = create_guid;
|
|
+ io.in.timeout = 0;
|
|
+
|
|
+ status = smb2_create(tree, mem_ctx, &io);
|
|
+ CHECK_STATUS(status, NT_STATUS_OK);
|
|
+
|
|
+ _h = io.out.file.handle;
|
|
+ h = &_h;
|
|
+ CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
|
|
+ CHECK_VAL(io.out.durable_open_v2, true);
|
|
+
|
|
+ status = smb2_util_write(tree, *h, &b, 0, 1);
|
|
+ CHECK_STATUS(status, NT_STATUS_OK);
|
|
+
|
|
+ /* disconnect, leaving the durable open */
|
|
+ TALLOC_FREE(tree);
|
|
+ h = NULL;
|
|
+
|
|
+ ok = torture_smb2_connection_ext(tctx, previous_session_id,
|
|
+ &options, &tree);
|
|
+ torture_assert_goto(tctx, ok, ret, done, "couldn't reconnect, bailing\n");
|
|
+
|
|
+ ZERO_STRUCT(io);
|
|
+ io.in.fname = fname;
|
|
+ io.in.durable_open_v2 = false;
|
|
+ io.in.durable_handle_v2 = &_h;
|
|
+ io.in.create_guid = create_guid;
|
|
+
|
|
+ /*
|
|
+ * This assumes 'error_inject:durable_reconnect = st_ex_nlink'
|
|
+ * will cause the durable reconnect to fail...
|
|
+ * in order to have a regression test for the dead lock.
|
|
+ */
|
|
+ status = smb2_create(tree, mem_ctx, &io);
|
|
+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
|
|
+
|
|
+ /*
|
|
+ * With the regression this will fail with
|
|
+ * a timeout...
|
|
+ */
|
|
+ status = smb2_util_unlink(tree2, fname);
|
|
+ CHECK_STATUS(status, NT_STATUS_OK);
|
|
+
|
|
+done:
|
|
+ if (h != NULL) {
|
|
+ smb2_util_close(tree, *h);
|
|
+ }
|
|
+ TALLOC_FREE(tree);
|
|
+
|
|
+ smb2_util_unlink(tree2, fname);
|
|
+
|
|
+ TALLOC_FREE(tree2);
|
|
+
|
|
+ talloc_free(mem_ctx);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
struct torture_suite *torture_smb2_durable_v2_delay_init(TALLOC_CTX *ctx)
|
|
{
|
|
struct torture_suite *suite =
|
|
@@ -2369,3 +2475,15 @@ struct torture_suite *torture_smb2_durable_v2_delay_init(TALLOC_CTX *ctx)
|
|
|
|
return suite;
|
|
}
|
|
+
|
|
+struct torture_suite *torture_smb2_durable_v2_regressions_init(TALLOC_CTX *ctx)
|
|
+{
|
|
+ struct torture_suite *suite =
|
|
+ torture_suite_create(ctx, "durable-v2-regressions");
|
|
+
|
|
+ torture_suite_add_2smb2_test(suite,
|
|
+ "durable_v2_reconnect_bug15624",
|
|
+ test_durable_v2_reconnect_bug15624);
|
|
+
|
|
+ return suite;
|
|
+}
|
|
diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c
|
|
index 5b6477e47bc..9cf7f5da78b 100644
|
|
--- a/source4/torture/smb2/smb2.c
|
|
+++ b/source4/torture/smb2/smb2.c
|
|
@@ -170,6 +170,8 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx)
|
|
torture_smb2_durable_v2_open_init(suite));
|
|
torture_suite_add_suite(suite,
|
|
torture_smb2_durable_v2_delay_init(suite));
|
|
+ torture_suite_add_suite(suite,
|
|
+ torture_smb2_durable_v2_regressions_init(suite));
|
|
torture_suite_add_suite(suite, torture_smb2_dir_init(suite));
|
|
torture_suite_add_suite(suite, torture_smb2_lease_init(suite));
|
|
torture_suite_add_suite(suite, torture_smb2_compound_init(suite));
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From 56a3aaf95c44052b19b61115686c71d5b7dbab4a Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Mon, 26 Aug 2024 14:42:12 +0200
|
|
Subject: [PATCH 61/63] s3:tests: let test_durable_handle_reconnect.sh run
|
|
smb2.durable-v2-regressions.durable_v2_reconnect_bug15624
|
|
|
|
This demonstrates the dead lock after a durable reconnect failed
|
|
because the stat info changed, the file can't be accessed anymore
|
|
as we leak the incomplete share mode entry in a still running
|
|
process.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit 14875448ca06a3a28800343a3a326f1a66bccec0)
|
|
---
|
|
.../samba3.blackbox.durable_v2_delay | 1 +
|
|
.../tests/test_durable_handle_reconnect.sh | 18 ++++++++++++++++++
|
|
2 files changed, 19 insertions(+)
|
|
create mode 100644 selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
|
|
diff --git a/selftest/knownfail.d/samba3.blackbox.durable_v2_delay b/selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
new file mode 100644
|
|
index 00000000000..88e29960797
|
|
--- /dev/null
|
|
+++ b/selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
@@ -0,0 +1 @@
|
|
+^samba3.blackbox.durable_v2_delay.durable-v2-regressions.durable_v2_reconnect_bug15624
|
|
diff --git a/source3/script/tests/test_durable_handle_reconnect.sh b/source3/script/tests/test_durable_handle_reconnect.sh
|
|
index 0ab32974824..fd5c156956f 100755
|
|
--- a/source3/script/tests/test_durable_handle_reconnect.sh
|
|
+++ b/source3/script/tests/test_durable_handle_reconnect.sh
|
|
@@ -33,4 +33,22 @@ testit "durable_v2_delay.durable_v2_reconnect_delay_msec" $VALGRIND \
|
|
|
|
rm $delay_inject_conf
|
|
|
|
+error_inject_conf=$(dirname $SMB_CONF_PATH)/error_inject.conf
|
|
+
|
|
+cat > $error_inject_conf << _EOF
|
|
+ kernel share modes = no
|
|
+ kernel oplocks = no
|
|
+ posix locking = no
|
|
+ error_inject:durable_reconnect = st_ex_nlink
|
|
+_EOF
|
|
+
|
|
+testit "durable-v2-regressions.durable_v2_reconnect_bug15624" \
|
|
+ $VALGRIND $BINDIR/smbtorture //$SERVER_IP/error_inject \
|
|
+ -U$USERNAME%$PASSWORD \
|
|
+ --option=torture:bug15624=yes \
|
|
+ smb2.durable-v2-regressions.durable_v2_reconnect_bug15624 ||
|
|
+ failed=$(expr $failed + 1)
|
|
+
|
|
+rm $error_inject_conf
|
|
+
|
|
testok $0 $failed
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From d8f01885145ecfce15f2507fdcc625442db1738c Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 9 Apr 2024 14:52:44 +0200
|
|
Subject: [PATCH 62/63] smbd: consolidate DH reconnect failure code
|
|
|
|
No change in behaviour, except that we now
|
|
also call fd_close() if vfs_default_durable_cookie()
|
|
failed.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
(cherry picked from commit a91457f97c98fcec1ed062514c364271af1df669)
|
|
---
|
|
source3/smbd/durable.c | 142 ++++++++++++++---------------------------
|
|
1 file changed, 47 insertions(+), 95 deletions(-)
|
|
|
|
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
|
|
index b21c223b2e4..50075ddd3f7 100644
|
|
--- a/source3/smbd/durable.c
|
|
+++ b/source3/smbd/durable.c
|
|
@@ -624,22 +624,22 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
ok = share_mode_forall_entries(lck, durable_reconnect_fn, &e);
|
|
if (!ok) {
|
|
DBG_WARNING("share_mode_forall_entries failed\n");
|
|
- TALLOC_FREE(lck);
|
|
- return NT_STATUS_INTERNAL_DB_ERROR;
|
|
+ status = NT_STATUS_INTERNAL_DB_ERROR;
|
|
+ goto fail;
|
|
}
|
|
|
|
if (e.pid.pid == 0) {
|
|
DBG_WARNING("Did not find a unique valid share mode entry\n");
|
|
- TALLOC_FREE(lck);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
if (!server_id_is_disconnected(&e.pid)) {
|
|
DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
|
|
"reconnect for handle that was not marked "
|
|
"disconnected (e.g. smbd or cluster node died)\n"));
|
|
- TALLOC_FREE(lck);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
if (e.share_file_id != op->global->open_persistent_id) {
|
|
@@ -648,8 +648,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
"(e.g. another client had opened the file)\n",
|
|
e.share_file_id,
|
|
op->global->open_persistent_id);
|
|
- TALLOC_FREE(lck);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
if ((e.access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) &&
|
|
@@ -658,8 +658,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
|
|
"share[%s] is not writeable anymore\n",
|
|
lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
|
|
- TALLOC_FREE(lck);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
/*
|
|
@@ -670,8 +670,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
DEBUG(0, ("vfs_default_durable_reconnect: failed to create "
|
|
"new fsp: %s\n", nt_errstr(status)));
|
|
- TALLOC_FREE(lck);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
fh_set_private_options(fsp->fh, e.private_options);
|
|
@@ -714,9 +713,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
*/
|
|
if (!GUID_equal(fsp_client_guid(fsp),
|
|
&e.client_guid)) {
|
|
- TALLOC_FREE(lck);
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
status = leases_db_get(
|
|
@@ -730,9 +728,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
&lease_version, /* lease_version */
|
|
&epoch); /* epoch */
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- TALLOC_FREE(lck);
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
fsp->lease = find_fsp_lease(
|
|
@@ -742,9 +738,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
lease_version,
|
|
epoch);
|
|
if (fsp->lease == NULL) {
|
|
- TALLOC_FREE(lck);
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_NO_MEMORY;
|
|
+ status = NT_STATUS_NO_MEMORY;
|
|
+ goto fail;
|
|
}
|
|
}
|
|
|
|
@@ -760,12 +755,10 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
|
|
status = fsp_set_smb_fname(fsp, smb_fname);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- TALLOC_FREE(lck);
|
|
- file_free(smb1req, fsp);
|
|
DEBUG(0, ("vfs_default_durable_reconnect: "
|
|
"fsp_set_smb_fname failed: %s\n",
|
|
nt_errstr(status)));
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
op->compat = fsp;
|
|
@@ -780,11 +773,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
fh_get_gen_id(fsp->fh));
|
|
if (!ok) {
|
|
DBG_DEBUG("Could not set new share_mode_entry values\n");
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_INTERNAL_ERROR;
|
|
+ status = NT_STATUS_INTERNAL_ERROR;
|
|
+ goto fail;
|
|
}
|
|
|
|
ok = brl_reconnect_disconnected(fsp);
|
|
@@ -793,11 +783,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
DEBUG(1, ("vfs_default_durable_reconnect: "
|
|
"failed to reopen brlocks: %s\n",
|
|
nt_errstr(status)));
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
/*
|
|
@@ -813,13 +799,9 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
|
|
status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, &how);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- TALLOC_FREE(lck);
|
|
DEBUG(1, ("vfs_default_durable_reconnect: failed to open "
|
|
"file: %s\n", nt_errstr(status)));
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
/*
|
|
@@ -833,48 +815,22 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
|
|
ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
|
|
if (ret == -1) {
|
|
- NTSTATUS close_status;
|
|
status = map_nt_error_from_unix_common(errno);
|
|
DEBUG(1, ("Unable to fstat stream: %s => %s\n",
|
|
smb_fname_str_dbg(smb_fname),
|
|
nt_errstr(status)));
|
|
- close_status = fd_close(fsp);
|
|
- if (!NT_STATUS_IS_OK(close_status)) {
|
|
- DBG_ERR("fd_close failed (%s) - leaking file "
|
|
- "descriptor\n", nt_errstr(close_status));
|
|
- }
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
if (!S_ISREG(fsp->fsp_name->st.st_ex_mode)) {
|
|
- NTSTATUS close_status = fd_close(fsp);
|
|
- if (!NT_STATUS_IS_OK(close_status)) {
|
|
- DBG_ERR("fd_close failed (%s) - leaking file "
|
|
- "descriptor\n", nt_errstr(close_status));
|
|
- }
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
|
|
if (!file_id_equal(&cookie.id, &file_id)) {
|
|
- NTSTATUS close_status = fd_close(fsp);
|
|
- if (!NT_STATUS_IS_OK(close_status)) {
|
|
- DBG_ERR("fd_close failed (%s) - leaking file "
|
|
- "descriptor\n", nt_errstr(close_status));
|
|
- }
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
(void)fdos_mode(fsp);
|
|
@@ -883,42 +839,21 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
&fsp->fsp_name->st,
|
|
fsp_str_dbg(fsp));
|
|
if (!ok) {
|
|
- NTSTATUS close_status = fd_close(fsp);
|
|
- if (!NT_STATUS_IS_OK(close_status)) {
|
|
- DBG_ERR("fd_close failed (%s) - leaking file "
|
|
- "descriptor\n", nt_errstr(close_status));
|
|
- }
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
+ goto fail;
|
|
}
|
|
|
|
status = set_file_oplock(fsp);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- NTSTATUS close_status = fd_close(fsp);
|
|
- if (!NT_STATUS_IS_OK(close_status)) {
|
|
- DBG_ERR("fd_close failed (%s) - leaking file "
|
|
- "descriptor\n", nt_errstr(close_status));
|
|
- }
|
|
- TALLOC_FREE(lck);
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
status = vfs_default_durable_cookie(fsp, mem_ctx, &new_cookie_blob);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
- TALLOC_FREE(lck);
|
|
DEBUG(1, ("vfs_default_durable_reconnect: "
|
|
"vfs_default_durable_cookie - %s\n",
|
|
nt_errstr(status)));
|
|
- op->compat = NULL;
|
|
- fsp->op = NULL;
|
|
- file_free(smb1req, fsp);
|
|
- return status;
|
|
+ goto fail;
|
|
}
|
|
|
|
smb1req->chain_fsp = fsp;
|
|
@@ -935,4 +870,21 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
*new_cookie = new_cookie_blob;
|
|
|
|
return NT_STATUS_OK;
|
|
+
|
|
+fail:
|
|
+ if (fsp != NULL && fsp_get_pathref_fd(fsp) != -1) {
|
|
+ NTSTATUS close_status;
|
|
+ close_status = fd_close(fsp);
|
|
+ if (!NT_STATUS_IS_OK(close_status)) {
|
|
+ DBG_ERR("fd_close failed (%s), leaking fd\n",
|
|
+ nt_errstr(close_status));
|
|
+ }
|
|
+ }
|
|
+ TALLOC_FREE(lck);
|
|
+ if (fsp != NULL) {
|
|
+ op->compat = NULL;
|
|
+ fsp->op = NULL;
|
|
+ file_free(smb1req, fsp);
|
|
+ }
|
|
+ return status;
|
|
}
|
|
--
|
|
2.51.0
|
|
|
|
|
|
From b248ddd3dd7193ba44c9ad86488dd180a25e3774 Mon Sep 17 00:00:00 2001
|
|
From: Ralph Boehme <slow@samba.org>
|
|
Date: Tue, 9 Apr 2024 14:53:32 +0200
|
|
Subject: [PATCH 63/63] smbd: remove just created sharemode entry in the error
|
|
codepaths
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Without this we leave stale sharemode entries around that can lead to all sorts
|
|
of havoc.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624
|
|
|
|
Signed-off-by: Ralph Boehme <slow@samba.org>
|
|
Reviewed-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Guenther Deschner <gd@samba.org>
|
|
|
|
Autobuild-User(master): Günther Deschner <gd@samba.org>
|
|
Autobuild-Date(master): Thu Sep 19 19:36:19 UTC 2024 on atb-devel-224
|
|
|
|
(cherry picked from commit 2ff3b9bc0d254a63a913ff9084de3d794fee27d0)
|
|
---
|
|
selftest/knownfail.d/samba3.blackbox.durable_v2_delay | 1 -
|
|
source3/smbd/durable.c | 8 ++++++++
|
|
2 files changed, 8 insertions(+), 1 deletion(-)
|
|
delete mode 100644 selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
|
|
diff --git a/selftest/knownfail.d/samba3.blackbox.durable_v2_delay b/selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
deleted file mode 100644
|
|
index 88e29960797..00000000000
|
|
--- a/selftest/knownfail.d/samba3.blackbox.durable_v2_delay
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-^samba3.blackbox.durable_v2_delay.durable-v2-regressions.durable_v2_reconnect_bug15624
|
|
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
|
|
index 50075ddd3f7..98d0d403e30 100644
|
|
--- a/source3/smbd/durable.c
|
|
+++ b/source3/smbd/durable.c
|
|
@@ -538,6 +538,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
enum ndr_err_code ndr_err;
|
|
struct vfs_default_durable_cookie cookie;
|
|
DATA_BLOB new_cookie_blob = data_blob_null;
|
|
+ bool have_share_mode_entry = false;
|
|
|
|
*result = NULL;
|
|
*new_cookie = data_blob_null;
|
|
@@ -776,6 +777,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
status = NT_STATUS_INTERNAL_ERROR;
|
|
goto fail;
|
|
}
|
|
+ have_share_mode_entry = true;
|
|
|
|
ok = brl_reconnect_disconnected(fsp);
|
|
if (!ok) {
|
|
@@ -872,6 +874,12 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
|
|
return NT_STATUS_OK;
|
|
|
|
fail:
|
|
+ if (fsp != NULL && have_share_mode_entry) {
|
|
+ /*
|
|
+ * Something is screwed up, delete the sharemode entry.
|
|
+ */
|
|
+ del_share_mode(lck, fsp);
|
|
+ }
|
|
if (fsp != NULL && fsp_get_pathref_fd(fsp) != -1) {
|
|
NTSTATUS close_status;
|
|
close_status = fd_close(fsp);
|
|
--
|
|
2.51.0
|
|
|