summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.gitlab-ci-coverage-runners.yml8
-rw-r--r--.gitlab-ci-default-runners.yml44
-rw-r--r--.gitlab-ci-main.yml9
-rw-r--r--VERSION2
-rw-r--r--WHATSNEW.txt86
-rw-r--r--auth/credentials/credentials.c5
-rw-r--r--auth/credentials/credentials.h1
-rw-r--r--auth/credentials/credentials_secrets.c31
-rw-r--r--auth/credentials/tests/test_creds.c37
-rw-r--r--auth/gensec/gensec_start.c2
-rw-r--r--bootstrap/.gitlab-ci.yml6
-rw-r--r--bootstrap/config.py3
-rwxr-xr-xbootstrap/generated-dists/centos8s/bootstrap.sh3
-rw-r--r--bootstrap/sha1sum.txt2
-rw-r--r--buildtools/wafsamba/samba_pidl.py4
-rw-r--r--buildtools/wafsamba/samba_third_party.py4
-rw-r--r--buildtools/wafsamba/samba_version.py5
-rw-r--r--ctdb/doc/ctdb_mutex_ceph_rados_helper.7.xml4
-rw-r--r--ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c50
-rw-r--r--debian/TODO37
-rwxr-xr-xdebian/addshare.py46
-rw-r--r--debian/changelog267
-rw-r--r--debian/control167
-rw-r--r--debian/dirs5
-rw-r--r--debian/libldb2.symbols1
-rw-r--r--debian/not-installed3
-rwxr-xr-x[-rw-r--r--]debian/panic-action0
-rw-r--r--debian/patches/make-python-optional.diff25
-rw-r--r--debian/patches/series2
-rw-r--r--debian/patches/tilde-in-version.diff23
-rwxr-xr-xdebian/python3-ldb.symbols.in1
-rw-r--r--debian/python3-samba.install5
-rwxr-xr-xdebian/rules75
-rwxr-xr-x[-rw-r--r--]debian/samba-ad-dc.init (renamed from debian/samba.samba-ad-dc.init)0
-rw-r--r--debian/samba-ad-dc.install6
-rw-r--r--debian/samba-ad-dc.lintian-overrides5
-rw-r--r--debian/samba-ad-dc.postinst16
-rw-r--r--debian/samba-ad-dc.preinst16
-rw-r--r--debian/samba-ad-dc.service (renamed from debian/samba.samba-ad-dc.service)1
-rw-r--r--debian/samba-common-bin.NEWS9
-rw-r--r--debian/samba-common-bin.dirs1
-rw-r--r--debian/samba-common-bin.install11
-rw-r--r--debian/samba-common-bin.lintian-override2
-rw-r--r--debian/samba-common.install3
-rwxr-xr-xdebian/samba-log-parser5
-rw-r--r--debian/samba-vfs-ceph.install4
-rw-r--r--debian/samba-vfs-ceph.lintian-overrides1
-rw-r--r--debian/samba-vfs-glusterfs.install4
-rw-r--r--debian/samba-vfs-glusterfs.lintian-overrides1
-rw-r--r--debian/samba-vfs-modules.NEWS15
-rw-r--r--debian/samba-vfs-modules.install3
-rw-r--r--debian/samba-vfs-modules.lintian-overrides7
-rw-r--r--debian/samba.NEWS10
-rw-r--r--debian/samba.dirs2
-rwxr-xr-xdebian/samba.install16
-rw-r--r--debian/samba.lintian-overrides6
-rw-r--r--debian/samba.nmbd.service1
-rw-r--r--debian/samba.postinst17
-rw-r--r--debian/samba.smbd.service1
-rwxr-xr-xdebian/setoption.py47
-rw-r--r--debian/source_samba.py170
-rw-r--r--debian/tests/control4
-rw-r--r--debian/winbind.service1
-rw-r--r--examples/winexe/wscript21
-rw-r--r--examples/winexe/wscript_build4
-rwxr-xr-xlib/fuzzing/decode_ndr_X_crash12
-rw-r--r--lib/ldb-samba/ldif_handlers.c94
-rw-r--r--lib/ldb/ABI/ldb-2.9.1.sigs305
-rw-r--r--lib/ldb/ABI/pyldb-util-2.9.1.sigs3
-rw-r--r--lib/ldb/common/attrib_handlers.c53
-rw-r--r--lib/ldb/common/ldb_dn.c30
-rw-r--r--lib/ldb/common/ldb_msg.c13
-rw-r--r--lib/ldb/common/qsort.c2
-rw-r--r--lib/ldb/include/ldb.h16
-rw-r--r--lib/ldb/modules/sort.c19
-rw-r--r--lib/ldb/wscript2
-rw-r--r--lib/socket/interfaces.c22
-rw-r--r--lib/torture/torture.h20
-rw-r--r--lib/util/charset/codepoints.c15
-rw-r--r--lib/util/charset/tests/charset.c31
-rw-r--r--lib/util/charset/util_str.c9
-rw-r--r--lib/util/data_blob.c5
-rw-r--r--lib/util/tests/binsearch.c6
-rw-r--r--lib/util/tests/test_ms_fnmatch.c2
-rw-r--r--lib/util/tsort.h19
-rw-r--r--libcli/nbt/libnbt.h3
-rw-r--r--libcli/nbt/nbtsocket.c44
-rw-r--r--libcli/security/dom_sid.c14
-rw-r--r--libcli/smb/smbXcli_base.c104
-rw-r--r--libcli/smb/smbXcli_base.h5
-rw-r--r--pidl/lib/Parse/Pidl/Typelist.pm14
-rw-r--r--python/samba/gp/gpclass.py4
-rw-r--r--python/samba/tests/blackbox/misc_dfs_widelink.py86
-rw-r--r--python/samba/tests/dns_base.py213
-rw-r--r--python/samba/tests/dns_tkey.py325
-rw-r--r--python/samba/tests/join.py2
-rw-r--r--python/samba/tests/ntacls.py2
-rwxr-xr-xscript/autobuild.py3
-rw-r--r--selftest/flapping.d/gitlab-setxattr-security18
-rw-r--r--selftest/knownfail-32bit8
-rwxr-xr-xselftest/target/Samba4.pm2
-rw-r--r--source3/include/fstring.h27
-rw-r--r--source3/include/includes.h5
-rw-r--r--source3/include/nameserv.h380
-rw-r--r--source3/include/session.h1
-rw-r--r--source3/include/smb.h26
-rw-r--r--source3/lib/sessionid_tdb.c8
-rw-r--r--source3/lib/util_tdb.c4
-rw-r--r--source3/libads/kerberos.c32
-rw-r--r--source3/libads/ldap.c16
-rw-r--r--source3/librpc/idl/ads.idl1
-rw-r--r--source3/libsmb/clidgram.c6
-rw-r--r--source3/libsmb/dsgetdcname.c29
-rw-r--r--source3/libsmb/libsmb_xattr.c14
-rw-r--r--source3/libsmb/namequery.c21
-rw-r--r--source3/libsmb/nmblib.c12
-rw-r--r--source3/libsmb/nmblib.h2
-rw-r--r--source3/libsmb/unexpected.c18
-rw-r--r--source3/libsmb/unexpected.h2
-rw-r--r--source3/locking/brlock.c7
-rw-r--r--source3/modules/posixacl_xattr.c6
-rw-r--r--source3/modules/vfs_default.c6
-rw-r--r--source3/modules/vfs_recycle.c176
-rw-r--r--source3/modules/vfs_vxfs.c6
-rw-r--r--source3/modules/vfs_widelinks.c13
-rw-r--r--source3/nmbd/nmbd.h382
-rw-r--r--source3/nmbd/nmbd_packets.c1
-rw-r--r--source3/rpc_server/wkssvc/srv_wkssvc_nt.c2
-rwxr-xr-xsource3/script/tests/test_recycle.sh5
-rwxr-xr-xsource3/script/tests/test_widelink_dfs_ci.sh72
-rwxr-xr-xsource3/selftest/tests.py11
-rw-r--r--source3/smbd/files.c18
-rw-r--r--source3/smbd/globals.h5
-rw-r--r--source3/smbd/smb2_server.c11
-rw-r--r--source3/smbd/smb2_sesssetup.c18
-rw-r--r--source3/smbd/smb2_tcon.c4
-rw-r--r--source3/utils/conn_tdb.c12
-rw-r--r--source3/utils/conn_tdb.h1
-rw-r--r--source3/utils/net_ads.c6
-rw-r--r--source3/utils/net_registry.c2
-rw-r--r--source3/utils/sharesec.c8
-rw-r--r--source3/utils/smbcacls.c15
-rw-r--r--source3/utils/status.c82
-rw-r--r--source3/utils/status.h1
-rw-r--r--source3/utils/status_json.c2
-rw-r--r--source3/winbindd/idmap_ad.c11
-rw-r--r--source3/wscript_build1
-rw-r--r--source4/dns_server/dns_crypto.c49
-rw-r--r--source4/dns_server/dns_query.c27
-rw-r--r--source4/dns_server/dns_update.c11
-rw-r--r--source4/dns_server/dnsserver_common.c8
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c26
-rw-r--r--source4/dsdb/samdb/ldb_modules/operational.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c17
-rw-r--r--source4/dsdb/schema/schema_set.c14
-rw-r--r--source4/libcli/dgram/dgramsocket.c40
-rw-r--r--source4/libcli/dgram/libdgram.h3
-rw-r--r--source4/libcli/smb2/session.c16
-rw-r--r--source4/libcli/smb2/smb2.h2
-rw-r--r--source4/nbt_server/dgram/request.c56
-rw-r--r--source4/nbt_server/interfaces.c29
-rw-r--r--source4/nbt_server/nbt_server.c143
-rw-r--r--source4/nbt_server/nbt_server.h2
-rw-r--r--source4/nbt_server/wins/winsdb.c5
-rw-r--r--source4/nbt_server/wins/winsserver.c3
-rw-r--r--source4/nbt_server/wscript_build2
-rw-r--r--source4/ntvfs/posix/pvfs_streams.c3
-rw-r--r--source4/rpc_server/dnsserver/dnsdata.c16
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c7
-rwxr-xr-xsource4/selftest/tests.py14
-rw-r--r--source4/torture/smb2/ioctl.c64
-rw-r--r--source4/torture/smb2/session.c629
-rwxr-xr-xtestprogs/blackbox/test_ldap_token.sh115
-rwxr-xr-xtestprogs/blackbox/test_trust_token.sh5
-rw-r--r--third_party/socket_wrapper/socket_wrapper.c45
-rw-r--r--third_party/socket_wrapper/wscript3
-rw-r--r--third_party/uid_wrapper/uid_wrapper.c58
-rw-r--r--third_party/uid_wrapper/wscript4
-rw-r--r--wscript20
179 files changed, 4471 insertions, 1353 deletions
diff --git a/.gitlab-ci-coverage-runners.yml b/.gitlab-ci-coverage-runners.yml
index 0f6b2ec..331c5d2 100644
--- a/.gitlab-ci-coverage-runners.yml
+++ b/.gitlab-ci-coverage-runners.yml
@@ -1,10 +1,4 @@
include:
- /.gitlab-ci-default-runners.yml
-.shared_runner_test:
- # We need the more powerful n1-standard-2 runners
- # in order to handle the lcov overhead.
- #
- # See .gitlab-ci-default-runners.yml for more details
- tags:
- - gitlab-org-docker
+# Currently we're happy with the defaults
diff --git a/.gitlab-ci-default-runners.yml b/.gitlab-ci-default-runners.yml
index f73f868..bdc504a 100644
--- a/.gitlab-ci-default-runners.yml
+++ b/.gitlab-ci-default-runners.yml
@@ -1,48 +1,26 @@
-# From https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners:
+# From https://docs.gitlab.com/ee/ci/runners/hosted_runners/linux.html
#
# ...
#
-# All your CI/CD jobs run on n1-standard-1 instances with 3.75GB of RAM, CoreOS
-# and the latest Docker Engine installed. Instances provide 1 vCPU and 25GB of
-# HDD disk space. The default region of the VMs is US East1. Each instance is
-# used only for one job, this ensures any sensitive data left on the system can’t
-# be accessed by other people their CI jobs.
-#
-# The gitlab-shared-runners-manager-X.gitlab.com fleet of runners are dedicated
-# for GitLab projects as well as community forks of them. They use a slightly
-# larger machine type (n1-standard-2) and have a bigger SSD disk size. They don’t
-# run untagged jobs and unlike the general fleet of shared runners, the instances
-# are re-used up to 40 times.
-#
-# ...
-#
-# The n1-standard-1 runners seem to be tagged with 'docker' together with 'gce'.
-#
-# The more powerful n1-standard-2 runners seem to be tagged with
-# 'gitlab-org-docker' or some with just 'gitlab-org'.
-#
+# Runner Tag vCPUs Memory Storage
+# saas-linux-small-amd64 2 8 GB 25 GB
#
# Our current private runner 'docker', 'samba-ci-private', 'shared' and
# 'ubuntu2204'. It runs with an ubuntu2204 kernel (5.15) and provides an
-# ext4 filesystem and similar RAM as the n1-standard-2 runners.
+# ext4 filesystem, 2 CPU and 4 GB (shared tag) 8G (samba-ci-private tag) RAM.
#
.shared_runner_build:
- # We use n1-standard-1 shared runners by default.
- #
- # There are currently 5 shared runners with 'docker' and 'gce',
- # while there are only 2 provising 'docker' together with 'shared'.
+ # We use saas-linux-small-amd64 shared runners by default.
+ # We avoid adding explicit tags for them in order
+ # to work with potential changes in future
#
- # We used to fallback to our private runner if the docker+shared runners
- # were busy, but now that we use the 5 docker+gce runners, we try to only
- # use shared runners without a fallback to our private runner!
- # Lets see how that will work out.
- tags:
- - docker
- - gce
+ # In order to generate valid yaml, we define a dummy variable...
+ variables:
+ SAMBA_SHARED_RUNNER_BUILD_DUMMY_VARIABLE: shared_runner_build
.shared_runner_test:
- # Currently we're fine using the n1-standard-1 runners also for testing
+ # We use saas-linux-small-amd64 shared runners by default.
extends: .shared_runner_build
.private_runner_test:
diff --git a/.gitlab-ci-main.yml b/.gitlab-ci-main.yml
index add5f32..face210 100644
--- a/.gitlab-ci-main.yml
+++ b/.gitlab-ci-main.yml
@@ -47,7 +47,7 @@ variables:
# Set this to the contents of bootstrap/sha1sum.txt
# which is generated by bootstrap/template.py --render
#
- SAMBA_CI_CONTAINER_TAG: 9a406973474a7903fe7fd6215226660911ed73c0
+ SAMBA_CI_CONTAINER_TAG: b078783e082ead539940faaa644567bf4ed67f67
#
# We use the ubuntu2204 image as default as
# it matches what we have on atb-devel-224
@@ -112,8 +112,14 @@ include:
before_script:
- uname -a
+ - ls -l /sys/module/
+ - ls -l /sys/kernel/security/
+ - if [ -e /sys/kernel/security/lsm ]; then cat /sys/kernel/security/lsm ; echo; fi
+ - if [ -e /proc/config.gz ]; then sudo zcat /proc/config.gz; echo; fi
- lsb_release -a
- cat /etc/os-release
+ - id
+ - cat /proc/self/status
- lscpu
- cat /proc/cpuinfo
- mount
@@ -141,6 +147,7 @@ include:
- ccache -s
# We are already running .gitlab-ci directives from this repo, remove additional checks that break our CI
- git config --global --add safe.directory `pwd`
+ - git config --global --add safe.directory /builds/samba-team/devel/samba/.git
after_script:
- mount
- df -h
diff --git a/VERSION b/VERSION
index cfa7539..200f6cc 100644
--- a/VERSION
+++ b/VERSION
@@ -27,7 +27,7 @@ SAMBA_COPYRIGHT_STRING="Copyright Andrew Tridgell and the Samba Team 1992-2024"
########################################################
SAMBA_VERSION_MAJOR=4
SAMBA_VERSION_MINOR=20
-SAMBA_VERSION_RELEASE=1
+SAMBA_VERSION_RELEASE=2
########################################################
# If a official release has a serious bug #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 8249e93..fb964d7 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,87 @@
==============================
+ Release Notes for Samba 4.20.2
+ June 19, 2024
+ ==============================
+
+
+This is the latest stable release of the Samba 4.20 release series.
+
+
+Changes since 4.20.1
+--------------------
+
+o Jeremy Allison <jra@samba.org>
+ * BUG 15662: vfs_widelinks with DFS shares breaks case insensitivity.
+
+o Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
+ * BUG 13213: Samba build is not reproducible.
+ * BUG 15569: ldb qsort might r/w out of bounds with an intransitive compare
+ function.
+ * BUG 15625: Many qsort() comparison functions are non-transitive, which can
+ lead to out-of-bounds access in some circumstances.
+
+o Andrew Bartlett <abartlet@samba.org>
+ * BUG 15638: Need to change gitlab-ci.yml tags in all branches to avoid CI
+ bill.
+ * BUG 15654: We have added new options --vendor-name and --vendor-patch-
+ revision arguments to ./configure to allow distributions and packagers to
+ put their name in the Samba version string so that when debugging Samba the
+ source of the binary is obvious.
+
+o Günther Deschner <gd@samba.org>
+ * BUG 15665: CTDB RADOS mutex helper misses namespace support.
+
+o Stefan Metzmacher <metze@samba.org>
+ * BUG 13019: Dynamic DNS updates with the internal DNS are not working.
+ * BUG 14981: netr_LogonSamLogonEx returns NR_STATUS_ACCESS_DENIED with
+ SysvolReady=0.
+ * BUG 15412: Anonymous smb3 signing/encryption should be allowed (similar to
+ Windows Server 2022).
+ * BUG 15573: Panic in dreplsrv_op_pull_source_apply_changes_trigger.
+ * BUG 15620: s4:nbt_server: does not provide unexpected handling, so winbindd
+ can't use nmb requests instead cldap.
+ * BUG 15642: winbindd, net ads join and other things don't work on an ipv6
+ only host.
+ * BUG 15659: Segmentation fault when deleting files in vfs_recycle.
+ * BUG 15664: Panic in vfs_offload_token_db_fetch_fsp().
+ * BUG 15666: "client use kerberos" and --use-kerberos is ignored for the
+ machine account.
+
+o Noel Power <noel.power@suse.com>
+ * BUG 15435: Regression DFS not working with widelinks = true.
+
+o Andreas Schneider <asn@samba.org>
+ * BUG 15633: samba-gpupdate - Invalid NtVer in netlogon_samlogon_response.
+ * BUG 15653: idmap_ad creates an incorrect local krb5.conf in case of trusted
+ domain lookups.
+ * BUG 15660: The images don't build after the git security release and CentOS
+ 8 Stream is EOL.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical:matrix.org matrix room, or
+#samba-technical IRC channel on irc.libera.chat.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the Samba 4.1 and newer product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+ ==============================
Release Notes for Samba 4.20.1
May 08, 2024
==============================
@@ -51,8 +134,7 @@ database (https://bugzilla.samba.org/).
======================================================================
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
==============================
Release Notes for Samba 4.20.0
March 27, 2024
diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c
index 20ab858..e563be3 100644
--- a/auth/credentials/credentials.c
+++ b/auth/credentials/credentials.c
@@ -146,6 +146,11 @@ _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct
return creds->kerberos_state;
}
+_PUBLIC_ enum credentials_obtained cli_credentials_get_kerberos_state_obtained(struct cli_credentials *creds)
+{
+ return creds->kerberos_state_obtained;
+}
+
_PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
{
return creds->forced_sasl_mech;
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index 341c984..16eddcc 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -267,6 +267,7 @@ const char *cli_credentials_get_impersonate_principal(struct cli_credentials *cr
const char *cli_credentials_get_self_service(struct cli_credentials *cred);
const char *cli_credentials_get_target_service(struct cli_credentials *cred);
enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds);
+enum credentials_obtained cli_credentials_get_kerberos_state_obtained(struct cli_credentials *creds);
const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *cred);
enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds);
NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c
index 8469d6e..906f3ff 100644
--- a/auth/credentials/credentials_secrets.c
+++ b/auth/credentials/credentials_secrets.c
@@ -370,13 +370,17 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account_db_ctx(struct cli_credenti
}
if (secrets_tdb_password_more_recent) {
- enum credentials_use_kerberos use_kerberos =
- CRED_USE_KERBEROS_DISABLED;
char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx));
cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED);
cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED);
cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
if (strequal(domain, lpcfg_workgroup(lp_ctx))) {
+ enum credentials_use_kerberos use_kerberos =
+ cli_credentials_get_kerberos_state(cred);
+ enum credentials_obtained use_kerberos_obtained =
+ cli_credentials_get_kerberos_state_obtained(cred);
+ bool is_ad = false;
+
cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED);
switch (server_role) {
@@ -388,13 +392,28 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account_db_ctx(struct cli_credenti
FALL_THROUGH;
case ROLE_ACTIVE_DIRECTORY_DC:
case ROLE_IPA_DC:
- use_kerberos = CRED_USE_KERBEROS_DESIRED;
+ is_ad = true;
break;
}
+
+ if (use_kerberos != CRED_USE_KERBEROS_DESIRED || is_ad) {
+ /*
+ * Keep an explicit selection
+ *
+ * For AD domains we also keep
+ * CRED_USE_KERBEROS_DESIRED
+ */
+ } else if (use_kerberos_obtained <= CRED_SMB_CONF) {
+ /*
+ * Disable kerberos by default within
+ * an NT4 domain.
+ */
+ cli_credentials_set_kerberos_state(cred,
+ CRED_USE_KERBEROS_DISABLED,
+ CRED_SMB_CONF);
+ }
}
- cli_credentials_set_kerberos_state(cred,
- use_kerberos,
- CRED_SPECIFIED);
+
cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
cli_credentials_set_password_last_changed_time(cred, secrets_tdb_lct);
cli_credentials_set_secure_channel_type(cred, secrets_tdb_secure_channel_type);
diff --git a/auth/credentials/tests/test_creds.c b/auth/credentials/tests/test_creds.c
index 2cb2e6d..e79f089 100644
--- a/auth/credentials/tests/test_creds.c
+++ b/auth/credentials/tests/test_creds.c
@@ -227,6 +227,8 @@ static void torture_creds_krb5_state(void **state)
TALLOC_CTX *mem_ctx = *state;
struct cli_credentials *creds = NULL;
struct loadparm_context *lp_ctx = NULL;
+ enum credentials_obtained kerberos_state_obtained;
+ enum credentials_use_kerberos kerberos_state;
bool ok;
lp_ctx = loadparm_init_global(true);
@@ -234,18 +236,27 @@ static void torture_creds_krb5_state(void **state)
creds = cli_credentials_init(mem_ctx);
assert_non_null(creds);
- assert_int_equal(creds->kerberos_state_obtained, CRED_UNINITIALISED);
- assert_int_equal(creds->kerberos_state, CRED_USE_KERBEROS_DESIRED);
+ kerberos_state_obtained =
+ cli_credentials_get_kerberos_state_obtained(creds);
+ kerberos_state = cli_credentials_get_kerberos_state(creds);
+ assert_int_equal(kerberos_state_obtained, CRED_UNINITIALISED);
+ assert_int_equal(kerberos_state, CRED_USE_KERBEROS_DESIRED);
ok = cli_credentials_set_conf(creds, lp_ctx);
assert_true(ok);
- assert_int_equal(creds->kerberos_state_obtained, CRED_SMB_CONF);
- assert_int_equal(creds->kerberos_state, CRED_USE_KERBEROS_DESIRED);
+ kerberos_state_obtained =
+ cli_credentials_get_kerberos_state_obtained(creds);
+ kerberos_state = cli_credentials_get_kerberos_state(creds);
+ assert_int_equal(kerberos_state_obtained, CRED_SMB_CONF);
+ assert_int_equal(kerberos_state, CRED_USE_KERBEROS_DESIRED);
ok = cli_credentials_guess(creds, lp_ctx);
assert_true(ok);
- assert_int_equal(creds->kerberos_state_obtained, CRED_SMB_CONF);
- assert_int_equal(creds->kerberos_state, CRED_USE_KERBEROS_DESIRED);
+ kerberos_state_obtained =
+ cli_credentials_get_kerberos_state_obtained(creds);
+ kerberos_state = cli_credentials_get_kerberos_state(creds);
+ assert_int_equal(kerberos_state_obtained, CRED_SMB_CONF);
+ assert_int_equal(kerberos_state, CRED_USE_KERBEROS_DESIRED);
assert_int_equal(creds->ccache_obtained, CRED_GUESS_FILE);
assert_non_null(creds->ccache);
@@ -253,15 +264,21 @@ static void torture_creds_krb5_state(void **state)
CRED_USE_KERBEROS_REQUIRED,
CRED_SPECIFIED);
assert_true(ok);
- assert_int_equal(creds->kerberos_state_obtained, CRED_SPECIFIED);
- assert_int_equal(creds->kerberos_state, CRED_USE_KERBEROS_REQUIRED);
+ kerberos_state_obtained =
+ cli_credentials_get_kerberos_state_obtained(creds);
+ kerberos_state = cli_credentials_get_kerberos_state(creds);
+ assert_int_equal(kerberos_state_obtained, CRED_SPECIFIED);
+ assert_int_equal(kerberos_state, CRED_USE_KERBEROS_REQUIRED);
ok = cli_credentials_set_kerberos_state(creds,
CRED_USE_KERBEROS_DISABLED,
CRED_SMB_CONF);
assert_false(ok);
- assert_int_equal(creds->kerberos_state_obtained, CRED_SPECIFIED);
- assert_int_equal(creds->kerberos_state, CRED_USE_KERBEROS_REQUIRED);
+ kerberos_state_obtained =
+ cli_credentials_get_kerberos_state_obtained(creds);
+ kerberos_state = cli_credentials_get_kerberos_state(creds);
+ assert_int_equal(kerberos_state_obtained, CRED_SPECIFIED);
+ assert_int_equal(kerberos_state, CRED_USE_KERBEROS_REQUIRED);
}
diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c
index 072188a..bcf98bd 100644
--- a/auth/gensec/gensec_start.c
+++ b/auth/gensec/gensec_start.c
@@ -1103,7 +1103,7 @@ _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
}
static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
- return (*gs2)->priority - (*gs1)->priority;
+ return NUMERIC_CMP((*gs2)->priority, (*gs1)->priority);
}
int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
diff --git a/bootstrap/.gitlab-ci.yml b/bootstrap/.gitlab-ci.yml
index ba82cdc..77b4e4f 100644
--- a/bootstrap/.gitlab-ci.yml
+++ b/bootstrap/.gitlab-ci.yml
@@ -6,9 +6,7 @@
# We need to make sure we only use gitlab.com
# runners and not our own runners, as our current runners
# don't allow 'docker build ...' to run.
- - docker
- - gce
- - shared
+ - saas-linux-small-amd64
variables:
SAMBA_CI_IS_BROKEN_IMAGE: "no"
SAMBA_CI_TEST_JOB: "samba-o3"
@@ -47,7 +45,7 @@
diff -u bootstrap/sha1sum.txt /tmp/sha1sum-template.txt
# run smoke test with samba-o3 or samba-fuzz
podman run --volume $(pwd):/src:ro ${ci_image_name} \
- /bin/bash -c "git clone /src samba && cd samba && export PKG_CONFIG_PATH=/usr/lib64/compat-gnutls34/pkgconfig:/usr/lib64/compat-nettle32/pkgconfig && script/autobuild.py ${SAMBA_CI_TEST_JOB} --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase"
+ /bin/bash -c "git config --global --add safe.directory /src/.git && git clone /src samba && cd samba && export PKG_CONFIG_PATH=/usr/lib64/compat-gnutls34/pkgconfig:/usr/lib64/compat-nettle32/pkgconfig && script/autobuild.py ${SAMBA_CI_TEST_JOB} --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase"
podman tag ${ci_image_name} ${ci_image_path}:${SAMBA_CI_CONTAINER_TAG}
podman tag ${ci_image_name} ${ci_image_path}:${timestamp_tag}
# We build all images, but only upload is it's not marked as broken
diff --git a/bootstrap/config.py b/bootstrap/config.py
index 11d8314..a5a7366 100644
--- a/bootstrap/config.py
+++ b/bootstrap/config.py
@@ -241,6 +241,9 @@ CENTOS8S_YUM_BOOTSTRAP = r"""
{GENERATED_MARKER}
set -xueo pipefail
+sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
+sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
+
yum update -y
yum install -y dnf-plugins-core
yum install -y epel-release
diff --git a/bootstrap/generated-dists/centos8s/bootstrap.sh b/bootstrap/generated-dists/centos8s/bootstrap.sh
index 4b2c62c..9e0aabb 100755
--- a/bootstrap/generated-dists/centos8s/bootstrap.sh
+++ b/bootstrap/generated-dists/centos8s/bootstrap.sh
@@ -7,6 +7,9 @@
set -xueo pipefail
+sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
+sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
+
yum update -y
yum install -y dnf-plugins-core
yum install -y epel-release
diff --git a/bootstrap/sha1sum.txt b/bootstrap/sha1sum.txt
index 61ecaf0..1bb5e92 100644
--- a/bootstrap/sha1sum.txt
+++ b/bootstrap/sha1sum.txt
@@ -1 +1 @@
-9a406973474a7903fe7fd6215226660911ed73c0
+b078783e082ead539940faaa644567bf4ed67f67
diff --git a/buildtools/wafsamba/samba_pidl.py b/buildtools/wafsamba/samba_pidl.py
index 72997c8..e101086 100644
--- a/buildtools/wafsamba/samba_pidl.py
+++ b/buildtools/wafsamba/samba_pidl.py
@@ -81,7 +81,9 @@ def SAMBA_PIDL(bld, pname, source,
else:
cc = 'CC="%s"' % bld.CONFIG_GET("CC")
- t = bld(rule='cd ${PIDL_LAUNCH_DIR} && %s%s %s ${PERL} ${PIDL} --quiet ${OPTIONS} --outputdir ${OUTPUTDIR} -- "${IDLSRC}"' % (pidl_dev, cpp, cc),
+ t = bld(rule=('cd ${PIDL_LAUNCH_DIR} && PERL_HASH_SEED=0 %s%s %s ${PERL} '
+ '${PIDL} --quiet ${OPTIONS} --outputdir ${OUTPUTDIR} -- "${IDLSRC}"' %
+ (pidl_dev, cpp, cc)),
ext_out = '.c',
before = 'c',
update_outputs = True,
diff --git a/buildtools/wafsamba/samba_third_party.py b/buildtools/wafsamba/samba_third_party.py
index 5289848..a42bb2d 100644
--- a/buildtools/wafsamba/samba_third_party.py
+++ b/buildtools/wafsamba/samba_third_party.py
@@ -24,7 +24,7 @@ Build.BuildContext.CHECK_CMOCKA = CHECK_CMOCKA
@conf
def CHECK_SOCKET_WRAPPER(conf):
- return conf.CHECK_BUNDLED_SYSTEM_PKG('socket_wrapper', minversion='1.4.2')
+ return conf.CHECK_BUNDLED_SYSTEM_PKG('socket_wrapper', minversion='1.4.3')
Build.BuildContext.CHECK_SOCKET_WRAPPER = CHECK_SOCKET_WRAPPER
@conf
@@ -39,7 +39,7 @@ Build.BuildContext.CHECK_RESOLV_WRAPPER = CHECK_RESOLV_WRAPPER
@conf
def CHECK_UID_WRAPPER(conf):
- return conf.CHECK_BUNDLED_SYSTEM_PKG('uid_wrapper', minversion='1.3.0')
+ return conf.CHECK_BUNDLED_SYSTEM_PKG('uid_wrapper', minversion='1.3.1')
Build.BuildContext.CHECK_UID_WRAPPER = CHECK_UID_WRAPPER
@conf
diff --git a/buildtools/wafsamba/samba_version.py b/buildtools/wafsamba/samba_version.py
index 31103e0..576168f 100644
--- a/buildtools/wafsamba/samba_version.py
+++ b/buildtools/wafsamba/samba_version.py
@@ -253,6 +253,11 @@ def samba_version_file(version_file, path, env=None, is_install=True):
print("Failed to parse line %s from %s" % (line, version_file))
raise
+ if "SAMBA_VERSION_VENDOR_SUFFIX" in env:
+ version_dict["SAMBA_VERSION_VENDOR_SUFFIX"] = env.SAMBA_VERSION_VENDOR_SUFFIX
+ if "SAMBA_VERSION_VENDOR_PATCH" in env:
+ version_dict["SAMBA_VERSION_VENDOR_PATCH"] = str(env.SAMBA_VERSION_VENDOR_PATCH)
+
return SambaVersion(version_dict, path, env=env, is_install=is_install)
diff --git a/ctdb/doc/ctdb_mutex_ceph_rados_helper.7.xml b/ctdb/doc/ctdb_mutex_ceph_rados_helper.7.xml
index f558f87..93d79ce 100644
--- a/ctdb/doc/ctdb_mutex_ceph_rados_helper.7.xml
+++ b/ctdb/doc/ctdb_mutex_ceph_rados_helper.7.xml
@@ -29,12 +29,14 @@
<manvolnum>5</manvolnum></citerefentry>:
</para>
<screen format="linespecific">
-cluster lock = !ctdb_mutex_ceph_rados_helper [Cluster] [User] [Pool] [Object]
+cluster lock = !ctdb_mutex_ceph_rados_helper [Cluster] [User] [Pool] [Object] [Timeout] [-n Namespace]
Cluster: Ceph cluster name (e.g. ceph)
User: Ceph cluster user name (e.g. client.admin)
Pool: Ceph RADOS pool name
Object: Ceph RADOS object name
+Timeout: Ceph RADOS lock duration in seconds (optional)
+Namespace: Ceph RADOS pool namespace (optional)
</screen>
<para>
The Ceph cluster <parameter>Cluster</parameter> must be up and running,
diff --git a/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c b/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c
index 7d868a3..46566c9 100644
--- a/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c
+++ b/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c
@@ -42,9 +42,18 @@
static char *progname = NULL;
+static void usage(void)
+{
+ fprintf(stderr, "Usage: %s <Ceph Cluster> <Ceph user> "
+ "<RADOS pool> <RADOS object> "
+ "[lock duration secs] [-n RADOS namespace]\n",
+ progname);
+}
+
static int ctdb_mutex_rados_ctx_create(const char *ceph_cluster_name,
const char *ceph_auth_name,
const char *pool_name,
+ const char *namespace,
rados_t *_ceph_cluster,
rados_ioctx_t *_ioctx)
{
@@ -87,6 +96,10 @@ static int ctdb_mutex_rados_ctx_create(const char *ceph_cluster_name,
return ret;
}
+ if (namespace != NULL) {
+ rados_ioctx_set_namespace(ioctx, namespace);
+ }
+
*_ceph_cluster = ceph_cluster;
*_ioctx = ioctx;
@@ -145,6 +158,7 @@ struct ctdb_mutex_rados_state {
const char *ceph_cluster_name;
const char *ceph_auth_name;
const char *pool_name;
+ const char *namespace;
const char *object;
uint64_t lock_duration_s;
int ppid;
@@ -295,15 +309,13 @@ static int ctdb_mutex_rados_mgr_reg(rados_t ceph_cluster)
int main(int argc, char *argv[])
{
int ret;
+ int opt;
struct ctdb_mutex_rados_state *cmr_state;
progname = argv[0];
- if ((argc != 5) && (argc != 6)) {
- fprintf(stderr, "Usage: %s <Ceph Cluster> <Ceph user> "
- "<RADOS pool> <RADOS object> "
- "[lock duration secs]\n",
- progname);
+ if (argc < 5) {
+ usage();
ret = -EINVAL;
goto err_out;
}
@@ -325,15 +337,36 @@ int main(int argc, char *argv[])
cmr_state->ceph_auth_name = argv[2];
cmr_state->pool_name = argv[3];
cmr_state->object = argv[4];
- if (argc == 6) {
+
+ optind = 5;
+ while ((opt = getopt(argc, argv, "n:")) != -1) {
+ switch(opt) {
+ case 'n':
+ cmr_state->namespace = optarg;
+ break;
+ default:
+ usage();
+ ret = -EINVAL;
+ goto err_ctx_cleanup;
+ }
+ }
+
+ if (argv[optind] != NULL) {
/* optional lock duration provided */
char *endptr = NULL;
- cmr_state->lock_duration_s = strtoull(argv[5], &endptr, 0);
- if ((endptr == argv[5]) || (*endptr != '\0')) {
+ cmr_state->lock_duration_s = strtoull(argv[optind], &endptr, 0);
+ if ((endptr == argv[optind]) || (*endptr != '\0')) {
fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
ret = -EINVAL;
goto err_ctx_cleanup;
}
+ if (argv[++optind] != NULL) {
+ /* incorrect count or format for optional arguments */
+ usage();
+ ret = -EINVAL;
+ goto err_ctx_cleanup;
+ }
+
} else {
cmr_state->lock_duration_s
= CTDB_MUTEX_CEPH_LOCK_DURATION_SECS_DEFAULT;
@@ -398,6 +431,7 @@ int main(int argc, char *argv[])
ret = ctdb_mutex_rados_ctx_create(cmr_state->ceph_cluster_name,
cmr_state->ceph_auth_name,
cmr_state->pool_name,
+ cmr_state->namespace,
&cmr_state->ceph_cluster,
&cmr_state->ioctx);
if (ret < 0) {
diff --git a/debian/TODO b/debian/TODO
index 7671a1a..5d424a8 100644
--- a/debian/TODO
+++ b/debian/TODO
@@ -1,32 +1,25 @@
-
This is an incomplete list of a number of issues that need to be fixed.
-
-TODOs before upload to unstable
-
- make a list of basic tests that should be done to ensure that the package is
acceptable for unstable (and run these tests)
- investigate impact of changes to libraries to reverse dependencies and plan
- transitions (if there are any)
- - sssd
- fixed in git (#725992)
- - openchange
- - evolution-mapi
-
-Other TODOs
-
-- handle ad-dc stuff
- - have debconf question to configure ad dc
- - the packaging from the old samba4/samba-ad-dc packages can help there
- - convert the users to the new db, or document that this doesn't happen
- automatically
-
-- what is the status of the docs?
-
- - documentation2.patch is upstream
- - The former documentation.patch needs to be rewritten against the xml input
+ transitions (if there are any).
+ - sssd: uses libndr which changes soname without transition (semi-private lib)
+ Especially painful for backports.
+ We're now emitting proper soname for libndrN at least (before it was just part
+ of samba-libs), so breakage will be at least visible before installing new
+ samba-libs
- Add script to verify that headers are usable through current dependencies
(to prevent bugs like #525888)
+- Investigate which binaries should go to which packages:
+
+ - Some libs and shared objects are specific to samba-ad-dc
+ (eg usr/lib/x86_64-linux-gnu/samba/service/kdc, ntp_signd)
+ - dlz_*: should these go to samba-ad-dc too? multiarch dlz?
+ - samba_kcc: where should it go?
+ - samba-ad-client files: should samba-dnsupdate and samba-spnupdate
+ be there?
+
diff --git a/debian/addshare.py b/debian/addshare.py
deleted file mode 100755
index 8b5e3c4..0000000
--- a/debian/addshare.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python3
-# Helper to add a share in the samba configuration file
-# Eventually this should be replaced by a call to samba-tool, but
-# for the moment that doesn't support setting individual configuration options.
-
-import optparse
-import os
-import re
-import shutil
-import stat
-import sys
-import tempfile
-
-parser = optparse.OptionParser()
-parser.add_option("--configfile", type=str, metavar="CONFFILE",
- help="Configuration file to use", default="/etc/samba/smb.conf")
-
-(opts, args) = parser.parse_args()
-if len(args) != 2:
- parser.print_usage()
-
-(share, path) = args
-done = False
-
-inf = open(opts.configfile, 'r')
-(fd, fn) = tempfile.mkstemp()
-outf = os.fdopen(fd, 'w')
-
-for l in inf.readlines():
- m = re.match(r"^\s*\[([^]]+)\]$", l)
- if m:
- name = m.groups(1)[0]
- if name.lower() == share.lower():
- sys.exit(0)
- outf.write(l)
-
-if not os.path.isdir(path):
- os.makedirs(path)
-outf.write("[%s]\n" % share)
-outf.write(" path = %s\n" % path)
-outf.write(" read only = no\n")
-outf.write("\n")
-
-os.fchmod(fd, stat.S_IMODE(os.stat(opts.configfile).st_mode))
-outf.close()
-shutil.move(fn, opts.configfile)
diff --git a/debian/changelog b/debian/changelog
index 106c9f9..7878bda 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,270 @@
+samba (2:4.20.2+dfsg-4~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.2+dfsg-4.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Wed, 26 Jun 2024 18:06:52 +0200
+
+samba (2:4.20.2+dfsg-4) unstable; urgency=medium
+
+ * d/control: add the forgotten epoch for Breaks/Replaces
+ of samba-vfs-ceph & samba-vfs-glusterfs (Closes: #1074299)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 26 Jun 2024 12:20:08 +0300
+
+samba (2:4.20.2+dfsg-3~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.2+dfsg-3.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Wed, 26 Jun 2024 18:06:20 +0200
+
+samba (2:4.20.2+dfsg-3) unstable; urgency=medium
+
+ * split out samba-vfs-glusterfs from samba-vfs-modules
+ (pick up and rework ubuntu changes)
+ * split out samba-vfs-ceph from samba-vfs-modules
+ * merge samba-vfs-modules (remaining) into main samba package
+ * the only remaining extra vfs module, snapper, does not need extra handling
+ * d/samba-ad-dc.lintian-overrides: add conflicts-with-version override
+ for /usr-move
+ * samba-common-bin: use trivial separate shell wrapper for the python script
+ * d/rules: use before-trixie build profile to control dh_movetousr run too
+ * d/*.service: provide empty value for referenced environment vars
+ (Closes: #1073969)
+ * d/dirs: remove leftover file
+ * d/samba-common-bin.dirs: stop creating /etc/samba/tls/
+ * d/samba.dirs: stop creating bin & sbin
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Tue, 25 Jun 2024 07:58:16 +0300
+
+samba (2:4.20.2+dfsg-2~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.2+dfsg-2.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Wed, 26 Jun 2024 18:05:54 +0200
+
+samba (2:4.20.2+dfsg-2) unstable; urgency=medium
+
+ * tilde-in-version.diff - allow tilde in version string
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Thu, 20 Jun 2024 09:49:50 +0300
+
+samba (2:4.20.2+dfsg-1~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging upstream version 2:4.20.2+dfsg.
+ * Merging debian version 2:4.20.2+dfsg-1.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Thu, 20 Jun 2024 06:07:32 +0200
+
+samba (2:4.20.2+dfsg-1) unstable; urgency=medium
+
+ * new upstream stable/bugfix release:
+ - https://bugzilla.samba.org/show_bug.cgi?id=13019
+ Dynamic DNS updates with the internal DNS are not working
+ - https://bugzilla.samba.org/show_bug.cgi?id=13213
+ Samba build is not reproducible
+ - https://bugzilla.samba.org/show_bug.cgi?id=14981
+ netr_LogonSamLogonEx returns NR_STATUS_ACCESS_DENIED with SysvolReady=0
+ - https://bugzilla.samba.org/show_bug.cgi?id=15412 Anonymous smb3
+ signing/encryption should be allowed (similar to Windows Server 2022)
+ - https://bugzilla.samba.org/show_bug.cgi?id=15435
+ Regression DFS not working with widelinks = true
+ - https://bugzilla.samba.org/show_bug.cgi?id=15569
+ ldb qsort might r/w out of bounds with an intransitive compare function
+ - https://bugzilla.samba.org/show_bug.cgi?id=15573
+ Panic in dreplsrv_op_pull_source_apply_changes_trigger
+ - https://bugzilla.samba.org/show_bug.cgi?id=15620
+ s4:nbt_server: does not provide unexpected handling, so winbindd
+ can't use nmb requests instead cldap
+ - https://bugzilla.samba.org/show_bug.cgi?id=15625
+ Many qsort() comparison functions are non-transitive, which can lead
+ to out-of-bounds access in some circumstances
+ - https://bugzilla.samba.org/show_bug.cgi?id=15633
+ samba-gpupdate - Invalid NtVer in netlogon_samlogon_response
+ - https://bugzilla.samba.org/show_bug.cgi?id=15638
+ Need to change gitlab-ci.yml tags in all branches to avoid CI bill
+ - https://bugzilla.samba.org/show_bug.cgi?id=15642 winbindd,
+ net ads join and other things don't work on an ipv6 only host
+ - https://bugzilla.samba.org/show_bug.cgi?id=15653 idmap_ad creates
+ an incorrect local krb5.conf in case of trusted domain lookups
+ - https://bugzilla.samba.org/show_bug.cgi?id=15654
+ new --vendor-name and --vendor-patch-revision options for ./configure
+ - https://bugzilla.samba.org/show_bug.cgi?id=15659
+ Segmentation fault when deleting files in vfs_recycle
+ Closes: #1073252
+ - https://bugzilla.samba.org/show_bug.cgi?id=15660 The images don't build
+ after the git security release and CentOS 8 Stream is EOL
+ - https://bugzilla.samba.org/show_bug.cgi?id=15662
+ vfs_widelinks with DFS shares breaks case insensitivity
+ - https://bugzilla.samba.org/show_bug.cgi?id=15664
+ Panic in vfs_offload_token_db_fetch_fsp()
+ - https://bugzilla.samba.org/show_bug.cgi?id=15665
+ CTDB RADOS mutex helper misses namespace support
+ - https://bugzilla.samba.org/show_bug.cgi?id=15666 "client use kerberos"
+ and --use-kerberos is ignored for the machine account
+ * d/libldb2.symbols,d.python3-ldb.symbols.in: add new version (2.9.1)
+ * use ./configure --vendor-name= instead of patching ./VERSION
+ * omit samba-ad-dc for i386 ubuntu
+ * samba-ad-dc: usr-move compensation maintscripts: add "set -e"
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 19 Jun 2024 23:59:36 +0300
+
+samba (2:4.20.1+dfsg-5~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.1+dfsg-5.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Tue, 11 Jun 2024 18:48:14 +0200
+
+samba (2:4.20.1+dfsg-5) unstable; urgency=medium
+
+ * Build-Depends: dpkg-dev>=trixie for Arch packages only (for t64 rename)
+ * d/samba.NEWS: reword the last entry a bit
+ * d/samba-ad-dc.init: chmod +x
+ * d/control: bump Standards-Version to 4.7.0 (no changes needed)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 10 Jun 2024 20:17:53 +0300
+
+samba (2:4.20.1+dfsg-4~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.1+dfsg-4.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Thu, 30 May 2024 05:32:07 +0200
+
+samba (2:4.20.1+dfsg-4) unstable; urgency=medium
+
+ [ Helmut Grohne ]
+ * Mitigate ineffective replaces due to /usr-move (DEP17 P1)
+ (Closes: #1072102)
+
+ [ Michael Tokarev ]
+ * d/control: mark libkeyutils-dev as linux-only [linux-any]
+ * d/control: drop old versions of versioned dependencies
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Wed, 29 May 2024 20:31:41 +0300
+
+samba (2:4.20.1+dfsg-3~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.1+dfsg-3.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Thu, 30 May 2024 05:31:42 +0200
+
+samba (2:4.20.1+dfsg-3) unstable; urgency=medium
+
+ * d/rules: move samba-common install to d/samba-common.install
+ * d/rules: install samba-ad-dc init files for the right package
+ * d/samba.postinst: remove nmbd_error_handler for the initscript
+ (it is not used in systemd case)
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 26 May 2024 18:48:17 +0300
+
+samba (2:4.20.1+dfsg-2~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging debian version 2:4.20.1+dfsg-2.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Thu, 30 May 2024 05:29:56 +0200
+
+samba (2:4.20.1+dfsg-2) unstable; urgency=medium
+
+ * move many files from samba package to samba-ad-dc package.
+ From now on, samba-ad-dc isn't just a meta-package, it is actually
+ needed for AD-DC functionality. If you run AD-DC, please ensure
+ that samba-ad-dc package is installed (it is not recommended by samba)
+ Closes: #1051770
+ * move samba-tool and samba-gpupdate from samba-common-bin and samba
+ packages to python3-samba. This is an Active Directory stuff, not
+ needed for a stand-alone server or a client, but might be useful
+ for auth-only (neither file-server nor file-client) AD installs
+ Closes: #1068360
+ * remove addshare.py, setoption.py and source_samba.py python scripts
+ These aren't used by samba packages and are hardly useful generally, esp.
+ having in mind their unusual locations. The apport hook (source_samba.py)
+ is mostly obsolete, it hasn't been updated for a very long time.
+ * add make-python-optional.diff, so python3 can be made optional
+ for samba-common-bin
+ * remove python3-samba and python from Depends of samba and samba-common-bin
+ packages, moving it to Recommends. This lets the user to install a stand-
+ alone samba file server without any Active Directory bits and even without
+ python interpreter
+ * d/samba.install: do not install samba_downgrade_db (to old pre-4.8 version)
+ * move smbcontrol binary from samba to samba-common-bin,
+ since it can also be used to control winbindd
+ * d/control: tdb-tools (tdbbackup) are run from python modules,
+ move from samba:Depends to python3-samba:Recommends
+ * d/control: samba: no need to depend on libpam-runtime or libpam-modules
+ * d/control: samba: no need to recommend samba-ad-provision
+ * debian/TODO: update a bit, remove many obsolete entries
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 26 May 2024 17:48:13 +0300
+
+samba (2:4.20.1+dfsg-1~progress7.99u1) graograman-backports; urgency=medium
+
+ * Uploading to graograman-backports, remaining changes:
+ - Updating maintainer field.
+ - Updating uploaders field.
+ - Updating bugs field.
+ - Updating vcs fields.
+ - Building without dpkg-vendor.
+ - Reverting t64 migration for backports.
+ * Merging upstream version 2:4.20.1+dfsg.
+ * Merging debian version 2:4.20.1+dfsg-1.
+
+ -- Daniel Baumann <daniel.baumann@progress-linux.org> Wed, 08 May 2024 15:06:44 +0200
+
samba (2:4.20.1+dfsg-1) unstable; urgency=medium
* new upstream major release
diff --git a/debian/control b/debian/control
index b22e64c..ea53315 100644
--- a/debian/control
+++ b/debian/control
@@ -11,13 +11,13 @@ XSBC-Original-Uploaders: Steve Langasek <vorlon@debian.org>,
Michael Tokarev <mjt@tls.msk.ru>
Bugs: mailto:maintainers@lists.progress-linux.org
Homepage: https://www.samba.org
-Standards-Version: 4.6.2
+Standards-Version: 4.7.0
Build-Depends:
- dpkg-dev (>= 1.22.5) <!pkg.samba.before-trixie>,
debhelper-compat (= 13),
dh-exec,
Build-Depends-Arch:
dh-sequence-python3,
+ dpkg-dev (>= 1.22.5) <!pkg.samba.before-trixie>,
# tools:
bison,
docbook-xml, docbook-xsl, xsltproc,
@@ -40,18 +40,18 @@ Build-Depends-Arch:
libblkid-dev,
libbsd-dev,
libcap-dev [linux-any],
-# the same [arch list] is in rules (with-ceph) and ctdb.install
+# the same [arch list] is in ctdb.install
libcephfs-dev [amd64 arm64 mips64el ppc64el riscv64 s390x],
librados-dev [amd64 arm64 mips64el ppc64el riscv64 s390x],
- libcmocka-dev (>= 1.1.3),
+ libcmocka-dev,
libcups2-dev,
libdbus-1-dev,
- libglusterfs-dev [amd64 arm64 ppc64el ppc64 riscv64 mips64el s390x ia64 sparc64],
+ libglusterfs-dev [amd64 arm64 loong64 mips64el ppc64 ppc64el riscv64 s390x sparc64],
libgnutls28-dev,
libgpgme11-dev,
libicu-dev,
libjansson-dev,
- libkeyutils-dev,
+ libkeyutils-dev [linux-any],
libkrb5-dev (>= 1.21.0~) <pkg.samba.mitkrb5>,
libldap2-dev,
liblmdb-dev,
@@ -62,11 +62,11 @@ Build-Depends-Arch:
libreadline-dev,
libtirpc-dev,
libsystemd-dev [linux-any],
- libtasn1-6-dev (>= 3.8),
+ libtasn1-6-dev,
libtasn1-bin,
liburing-dev [linux-any],
xfslibs-dev [linux-any],
- zlib1g-dev (>= 1:1.2.3),
+ zlib1g-dev,
# python (+#904999):
python3-dev:any | python3-dev, libpython3-dev,
python3-dnspython,
@@ -90,32 +90,25 @@ Package: samba
Architecture: any
Pre-Depends: ${misc:Pre-Depends}
Depends: passwd,
- libpam-modules,
- libpam-runtime (>= 1.0.1-11),
procps,
- python3,
- python3-dnspython,
- python3-samba (= ${binary:Version}),
samba-common (= ${source:Version}),
samba-common-bin (=${binary:Version}),
- tdb-tools,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
Recommends: attr,
- python3-markdown,
- samba-dsdb-modules,
- samba-vfs-modules,
- samba-ad-provision,
-Suggests: bind9 (>= 1:9.5.1),
- bind9utils,
- ctdb,
- ldb-tools,
- ntp | chrony (>= 3.0-1),
+ python3-samba,
+Suggests: ctdb,
ufw,
- winbind
-Enhances: bind9, ntp
-Breaks: samba-ad-provision (<< ${source:Upstream-Version})
+ winbind,
+ samba-vfs-ceph, samba-vfs-glusterfs,
+# move libdfs-server-ad-samba4.so.0 samba-libs=>samba-vfs-modules in 4.19.0~rc1
+# swallow samba-vfs-modules by samba in 4.20.2-dfsg-3
+Replaces: samba-libs (<< 2:4.19.0~),
+ samba-vfs-modules (<< 2:4.20.2+dfsg-3~),
+Breaks: samba-ad-provision (<< ${source:Upstream-Version}),
+ samba-libs (<< 2:4.19.0~),
+ samba-vfs-modules (<< 2:4.20.2+dfsg-3~),
Description: SMB/CIFS file, print, and login server for Unix
Samba is an implementation of the SMB/CIFS protocol for Unix systems,
providing support for cross-platform file and printer sharing with
@@ -177,21 +170,16 @@ Description: common files used by both the Samba server and client
Package: samba-common-bin
Architecture: any
-Depends: python3,
- python3-samba,
- samba-common (=${source:Version}),
- samba-libs (= ${binary:Version}),
+Depends: samba-common (= ${source:Version}),
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
-Recommends: samba-dsdb-modules
+Recommends: python3-samba,
Suggests: heimdal-clients,
- python3-markdown,
- python3-dnspython
-# moved samba-dcerpcd samba=>samba-common-bin in in 4.16.2+dfsg-1
# moved libnet-keytab-samba4.so.0 & libRPC-WORKER-samba4.so.0 samba-libs=>samba-common-bin in 4.19.0~r1
-Replaces: samba (<< 2:4.16.2+dfsg-1~), samba-libs (<< 2:4.19.0~)
-Breaks: samba (<< 2:4.16.2+dfsg-1~), samba-libs (<< 2:4.19.0~)
+# moved smbcontrol samba=>samba-common-bin in 4.20.0-2
+Replaces: samba (<< 2:4.20.1+dfsg-2~), samba-libs (<< 2:4.19.0~)
+Breaks: samba (<< 2:4.20.1+dfsg-2~), samba-libs (<< 2:4.19.0~)
Description: Samba common files used by both the server and the client
Samba is an implementation of the SMB/CIFS protocol for Unix systems,
providing support for cross-platform file sharing with Microsoft Windows, OS X,
@@ -203,17 +191,32 @@ Description: Samba common files used by both the server and the client
package).
Package: samba-ad-dc
-Architecture: all
+Architecture: any
Multi-Arch: foreign
Pre-Depends: ${misc:Pre-Depends}
-Depends: samba (>= ${source:Version}~), samba-dsdb-modules, samba-vfs-modules,
- winbind,
- krb5-kdc (>= 1.21.0~) <pkg.samba.mitkrb5>,
- ${misc:Depends}
+Depends: samba (= ${binary:Version}),
+ python3-samba (= ${binary:Version}),
+ python3-dnspython,
+ samba-dsdb-modules (= ${binary:Version}),
+ winbind (= ${binary:Version}),
+ krb5-kdc (>= 1.21.0~) <pkg.samba.mitkrb5>,
+ ${python3:Depends},
+ ${shlibs:Depends},
+ ${misc:Depends}
Recommends: libnss-winbind, libpam-winbind,
# samba-ad-provision is needed for setup only
samba-ad-provision
-Breaks: samba-ad-provision (<< ${source:Upstream-Version})
+Suggests: bind9,
+ bind9utils,
+ ldb-tools,
+ ntp | chrony,
+Enhances: bind9, ntp
+Breaks: samba-ad-provision (<< ${source:Upstream-Version}),
+# files moved from samba & samba-common-bin in 4.20.1-2:
+ samba-common-bin (<< 2:4.20.1+dfsg-2~),
+Replaces: samba-common-bin (<< 2:4.20.1+dfsg-2~),
+# Breaks+Replaces upgraded to Conflicts for DEP17 + /usr-move
+Conflicts: samba (<< 2:4.20.1+dfsg-2~),
Description: Samba control files to run AD Domain Controller
Samba is an implementation of the SMB/CIFS protocol for Unix systems,
providing support for cross-platform file and printer sharing with
@@ -292,7 +295,7 @@ Package: samba-dev
Architecture: any
Multi-Arch: same
Depends: libc6-dev,
- libldb-dev (>= 2:2),
+ libldb-dev,
libpopt-dev,
libtalloc-dev,
libtdb-dev,
@@ -323,10 +326,15 @@ Depends: python3-ldb,
${misc:Depends},
${python3:Depends},
${shlibs:Depends}
+Breaks:
+# samba-tool & samba-gpupdate moved from samba-common-bin & samba in 4.20.1-2:
+ samba-common-bin (<< 2:4.20.1+dfsg-2~), samba (<< 2:4.20.1+dfsg-2~),
Replaces:
+ samba-common-bin (<< 2:4.20.1+dfsg-2~), samba (<< 2:4.20.1+dfsg-2~),
# libsamba-policy & helpers and dckeytab python libs moved to python3-samba
- samba-libs (<< 2:4.16.0+dfsg-1~), samba (<< 2:4.16.0+dfsg-1~)
-Recommends: python3-gpg
+ samba-libs (<< 2:4.16.0+dfsg-1~),
+Recommends: python3-gpg,
+ tdb-tools,
Description: Python 3 bindings for Samba
Samba is an implementation of the SMB/CIFS protocol for Unix systems,
providing support for cross-platform file sharing with Microsoft Windows, OS X,
@@ -354,31 +362,58 @@ Description: Samba Directory Services Database
Directory features to the LDB library.
Package: samba-vfs-modules
+# Remove this package for trixie+1
Architecture: any
-Multi-Arch: same
-Depends: samba-libs (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
-Recommends: ${vfsmods:Depends}
-# move libdfs-server-ad-samba4.so.0 samba-libs=>samba-vfs-modules in 4.19.0~rc1
-Replaces: samba-libs (<< 2:4.19.0~)
-Breaks: samba-libs (<< 2:4.19.0~)
+Section: oldlibs
+Depends: ${misc:Depends}
+Description: Samba Virtual FileSystem plugins (transitional package)
+ Samba is an implementation of the SMB/CIFS protocol for Unix systems,
+ providing support for cross-platform file sharing with Microsoft Windows, OS X,
+ and other Unix systems. Samba can also function as a domain controller
+ or member server in Active Directory or NT4-style domains.
+ .
+ Virtual FileSystem modules are stacked shared libraries extending the
+ functionality of Samba. This package used to provide VFS modules for
+ samba, but since version 4.20.2+dfsg-3, most of the modules were merged
+ into main samba package, or into their own separate packages -
+ samba-vfs-ceph and samba-vfs-glusterfs.
+ .
+ This package can safely be removed.
+
+Package: samba-vfs-ceph
+Architecture: amd64 arm64 mips64el ppc64el riscv64 s390x
+Depends: samba (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
+# ceph modules moved from samba-vfs-modules in 4.20.2+dfsg-3
+Replaces: samba-vfs-modules (<< 2:4.20.2+dfsg-3~)
+Breaks: samba-vfs-modules (<< 2:4.20.2+dfsg-3~)
+Enhances: samba
+Description: Samba Virtual FileSystem ceph modules
+ Samba is an implementation of the SMB/CIFS protocol for Unix systems,
+ providing support for cross-platform file sharing with Microsoft Windows, OS X,
+ and other Unix systems. Samba can also function as a domain controller
+ or member server in Active Directory or NT4-style domains.
+ .
+ Virtual FileSystem modules are stacked shared libraries extending the
+ functionality of Samba. This package provides vfs_ceph and vfs_ceph_snapshots
+ modules.
+
+Package: samba-vfs-glusterfs
+Architecture: amd64 arm64 loong64 mips64el ppc64 ppc64el riscv64 s390x sparc64
+Depends: samba (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
+# glusterfs modules moved from samba-vfs-modules in 4.20.2+dfsg-3 (4.19.4+dfsg-2ubuntu1)
+# in ubuntu, glusterfs was in samba-vfs-modules-extra temporarily
+Replaces: samba-vfs-modules (<< 2:4.20.2+dfsg-3~), samba-vfs-modules-extra (<< 2:4.20.2+dfsg-3~)
+Breaks: samba-vfs-modules (<< 2:4.20.2+dfsg-3~), samba-vfs-modules-extra (<< 2:4.20.2+dfsg-3~)
Enhances: samba
-Description: Samba Virtual FileSystem plugins
+Description: Samba Virtual FileSystem glusterfs modules
Samba is an implementation of the SMB/CIFS protocol for Unix systems,
providing support for cross-platform file sharing with Microsoft Windows, OS X,
and other Unix systems. Samba can also function as a domain controller
or member server in Active Directory or NT4-style domains.
.
Virtual FileSystem modules are stacked shared libraries extending the
- functionality of Samba. Some examples are:
- * vfs_acl_xattr: Save NTFS-ACLs in Extended Attributes
- * vfs_audit: record selected Samba VFS operations in the system log
- * vfs_readonly: Make a Samba share read only for a specified time period
- * vfs_recycle: Give the same effect as the Recycle Bin on Windows computers
- * vfs_shadow_copy2: Expose snapshots to Windows clients as shadow copies
- * vfs_worm: Disallow writes for older file
- .
- Note: The runtime dependencies of vfs_ceph, vfs_glusterfs and vfs_snapper are
- moved to Recommends.
+ functionality of Samba. This package provides vfs_glusterfs and
+ vfs_glusterfs_fuse modules.
Package: libsmbclient0
Provides: ${t64:Provides}
@@ -459,8 +494,7 @@ Section: admin
Architecture: any
Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
-Depends: libpam-runtime (>= 1.0.1-6),
- libpam0g (>= 1.1.3-2~),
+Depends: libpam-runtime,
winbind:any (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
@@ -539,8 +573,9 @@ Depends: iproute2 [linux-any],
time,
${misc:Depends},
${shlibs:Depends}
-Recommends: ethtool [linux-any], python3:any, python3-etcd, ${rados:Depends}
-Suggests: lsof
+Recommends: ethtool [linux-any], python3:any, python3-etcd,
+Suggests: lsof,
+ ${rados:Depends}, samba-vfs-ceph [amd64 arm64 mips64el ppc64el riscv64 s390x],
Description: clustered database to store temporary data
CTDB is a cluster implementation of the TDB database used by Samba and other
projects to store temporary data. If an application is already using TDB for
diff --git a/debian/dirs b/debian/dirs
deleted file mode 100644
index acc9c2e..0000000
--- a/debian/dirs
+++ /dev/null
@@ -1,5 +0,0 @@
-etc/samba
-usr/bin
-usr/sbin
-usr/share/man/man1
-usr/share/man/man7
diff --git a/debian/libldb2.symbols b/debian/libldb2.symbols
index 8a94567..6625db8 100644
--- a/debian/libldb2.symbols
+++ b/debian/libldb2.symbols
@@ -80,6 +80,7 @@ libldb.so.2 #PACKAGE# #MINVER#
LDB_2.7.0@LDB_2.7.0 2:2.7.0
LDB_2.8.0@LDB_2.8.0 2:2.8.0
LDB_2.9.0@LDB_2.9.0 2:2.9.0
+ LDB_2.9.1@LDB_2.9.1 2:2.9.1
ldb_check_critical_controls@LDB_0.9.22 0.9.22
ldb_controls_except_specified@LDB_0.9.22 0.9.22
ldb_control_to_string@LDB_1.0.2 1.0.2~git20110403
diff --git a/debian/not-installed b/debian/not-installed
index 4e8df92..98436ec 100644
--- a/debian/not-installed
+++ b/debian/not-installed
@@ -5,3 +5,6 @@ usr/share/samba/setup
# new experimental windows search client
usr/bin/wspsearch
usr/share/man/man1/wspsearch.1
+# downgrade db to pre-4.8 version, hardly needed anymore:
+usr/sbin/samba_downgrade_db
+usr/share/man/man8/samba_downgrade_db.8
diff --git a/debian/panic-action b/debian/panic-action
index 7b73024..7b73024 100644..100755
--- a/debian/panic-action
+++ b/debian/panic-action
diff --git a/debian/patches/make-python-optional.diff b/debian/patches/make-python-optional.diff
new file mode 100644
index 0000000..4cf50f6
--- /dev/null
+++ b/debian/patches/make-python-optional.diff
@@ -0,0 +1,25 @@
+From: Michael Tokarev <mjt@tls.msk.ru>
+Subject: samba-log-parser: make python optional
+Date: Sun, 26 May 2024 14:40:40 +0300
+Forwarded: not-needed
+Debian-Specific: yes
+
+samba-log-parser is a rarely used utility written in python.
+It is the only python program in the samba-common-bin package.
+By using this simple trick (wrapping the script into #!/bin/sh)
+we can make the python package optional, to be able to install
+minimal samba client.
+
+--- a/source3/script/samba-log-parser
++++ b/source3/script/samba-log-parser
+@@ -1,4 +1,9 @@
+-#!/usr/bin/env python3
++#! /bin/sh
++""":"
++[ -x /usr/bin/python3 ] && exec /usr/bin/python3 "$0" "$@"
++echo "This program requires python3. Please install python3 package to use it." >&2
++exit 42
++":"""
+ #
+ #######################################################################
+ #
diff --git a/debian/patches/series b/debian/patches/series
index b06c91a..c469cbc 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -25,3 +25,5 @@ silence-can-not-convert-group-sid.diff
edns0.patch
passchange-error-message.patch
lower-dns-lookup-mismatch-messages.patch
+make-python-optional.diff
+tilde-in-version.diff
diff --git a/debian/patches/tilde-in-version.diff b/debian/patches/tilde-in-version.diff
new file mode 100644
index 0000000..8182935
--- /dev/null
+++ b/debian/patches/tilde-in-version.diff
@@ -0,0 +1,23 @@
+From: Michael Tokarev <mjt@tls.msk.ru>
+Subject: handle tilde in version string
+Date: Thu, 20 Jun 2024 09:47:47 +0300
+Forwarded: yes
+
+wafsamba dislikes when version string contains "special" chars.
+For some of them, upstream already has code to deal with.
+Add handling of tilde (~) to the same places too.
+
+diff --git a/buildtools/wafsamba/samba_abi.py b/buildtools/wafsamba/samba_abi.py
+index 2d9505d255c..cf7153f25f0 100644
+--- a/buildtools/wafsamba/samba_abi.py
++++ b/buildtools/wafsamba/samba_abi.py
+@@ -288,3 +288,3 @@ def abi_build_vscript(task):
+ def VSCRIPT_MAP_PRIVATE(bld, libname, orig_vscript, version, private_vscript):
+- version = version.replace("-", "_").replace("+","_").upper()
++ version = version.replace("-", "_").replace("+","_").replace("~","_").upper()
+ t = bld.SAMBA_GENERATOR(private_vscript,
+@@ -317,3 +317,3 @@ def ABI_VSCRIPT(bld, libname, abi_directory, version, vscript, abi_match=None, p
+ libname = libname.replace("-", "_").replace("+","_").upper()
+- version = version.replace("-", "_").replace("+","_").upper()
++ version = version.replace("-", "_").replace("+","_").replace("~","_").upper()
+
diff --git a/debian/python3-ldb.symbols.in b/debian/python3-ldb.symbols.in
index ac2e51a..69b236b 100755
--- a/debian/python3-ldb.symbols.in
+++ b/debian/python3-ldb.symbols.in
@@ -64,6 +64,7 @@
PYLDB_UTIL_2.7.0@PYLDB_UTIL_2.7.0 2:2.7.0
PYLDB_UTIL_2.8.0@PYLDB_UTIL_2.8.0 2:2.8.0
PYLDB_UTIL_2.9.0@PYLDB_UTIL_2.9.0 2:2.9.0
+ PYLDB_UTIL_2.9.1@PYLDB_UTIL_2.9.1 2:2.9.1
pyldb_Dn_FromDn@PYLDB_UTIL_1.1.2 2:2.0.7
pyldb_Object_AsDn@PYLDB_UTIL_1.1.2 2:2.0.7
pyldb_check_type@PYLDB_UTIL_2.1.0 2:2.1.0
diff --git a/debian/python3-samba.install b/debian/python3-samba.install
index 2a0e9a6..7eaff83 100644
--- a/debian/python3-samba.install
+++ b/debian/python3-samba.install
@@ -2,3 +2,8 @@ usr/lib/python3*/*-packages/samba
usr/lib/*/libsamba-policy.cpython-*.so.*
usr/lib/*/samba/libsamba-net.cpython-*.so.*
usr/lib/*/samba/libsamba-python.cpython-*.so.0
+
+usr/bin/samba-tool
+usr/share/man/man8/samba-tool.8
+usr/sbin/samba-gpupdate
+usr/share/man/man8/samba-gpupdate.8
diff --git a/debian/rules b/debian/rules
index bd00724..ddc885a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -35,12 +35,12 @@ LDB_DEB_VERSION = ${LDB_EPOCH}${LDB_VERSION}+samba${DEB_VERSION_UPSTREAM_REVISIO
LDB_DEPENDS = libldb2 (= ${LDB_DEB_VERSION})
LDB_PACKAGES = libldb2 libldb-dev ldb-tools python3-ldb python3-ldb-dev
+before-trixie := $(filter pkg.samba.before-trixie, ${DEB_BUILD_PROFILES})
+
omit-pkgs =
-with-glusterfs =
-with-ceph =
-with-snapper =
config-args = \
+ --vendor-name=${DEB_VENDOR}-${DEB_VERSION_UPSTREAM_REVISION} \
--prefix=/usr \
--enable-fhs \
--sysconfdir=/etc \
@@ -78,9 +78,6 @@ config-args = \
--with-logdir=/var/log/ctdb \
ifeq (${DEB_HOST_ARCH_OS}, linux) # extra linux-specific features
-with-glusterfs = $(if $(filter amd64 arm64 ppc64el ppc64 riscv64 mips64el s390x ia64 sparc64,${DEB_HOST_ARCH}),yes)
-with-ceph = $(if $(filter amd64 arm64 mips64el ppc64el riscv64 s390x, ${DEB_HOST_ARCH}),yes)
-with-snapper = yes
config-args += \
--with-quota \
@@ -90,7 +87,7 @@ endif
# Ubuntu i386 binary compatibility only effort: Disable some i386 packages and modules
ifeq (${DEB_VENDOR}-${DEB_HOST_ARCH}, Ubuntu-i386)
-omit-pkgs += ctdb libpam-winbind samba samba-testsuite samba-vfs-modules
+omit-pkgs += ctdb libpam-winbind samba samba-ad-dc samba-testsuite samba-vfs-modules samba-vfs-ceph samba-vfs-glusterfs
endif
ifneq (,$(filter armel mipsel m68k powerpc sh4,${DEB_HOST_ARCH}))
@@ -118,16 +115,8 @@ endif
# build is done in bin/default/ subdir
CFLAGS += -ffile-prefix-map=../../=
-config-args += $(if ${with-ceph},\
- --enable-cephfs --enable-ceph-reclock,\
- --disable-cephfs)
-
# we had t64 transition (libsmbclient => libsmbclient0) for trixie
-ifneq (,$(filter pkg.samba.before-trixie, ${DEB_BUILD_PROFILES}))
-libsmbclient := libsmbclient
-else
-libsmbclient := libsmbclient0
-endif
+libsmbclient := $(if ${before-trixie},libsmbclient,libsmbclient0)
with_mitkrb5 = $(filter pkg.samba.mitkrb5, ${DEB_BUILD_PROFILES})
ifneq (,${with_mitkrb5})
@@ -139,7 +128,8 @@ config-args += \
mitkrb5-samba-ver = ${DEB_VERSION}mitkrb5
mitkrb5-dep-pkgs = samba-libs samba-dev
mitkrb5-dep-pkgs += samba samba-common-bin python3-samba
-mitkrb5-dep-pkgs += samba-dsdb-modules samba-vfs-modules
+mitkrb5-dep-pkgs += samba-vfs-ceph samba-vfs-glusterfs
+mitkrb5-dep-pkgs += samba-dsdb-modules
mitkrb5-dep-pkgs += ${libsmbclient} smbclient
mitkrb5-dep-pkgs += libnss-winbind libpam-winbind
mitkrb5-dep-pkgs += winbind libwbclient0
@@ -155,6 +145,11 @@ endif
# ${build-pkgs} will honour arch/indep and the above list in ${DH_OPTIONS}
build-pkgs := $(shell dh_listpackages)
+with-ceph := $(filter samba-vfs-ceph,${build-pkgs})
+config-args += $(if ${with-ceph},\
+ --enable-cephfs --enable-ceph-reclock,\
+ --disable-cephfs)
+
binary binary-arch binary-indep \
install install-arch install-indep: %:
dh $*
@@ -162,12 +157,6 @@ install install-arch install-indep: %:
configure: bin/configured.stamp
.PHONY: configure
bin/configured.stamp:
-# branding
- if [ ! -f VERSION.orig ]; then \
- mv VERSION VERSION.orig; \
- sed -r -e 's/^(SAMBA_VERSION_VENDOR_SUFFIX).*/\1=${DEB_VENDOR}/' \
- VERSION.orig > VERSION; \
- fi
CC="${CC}" CPP="${CPP}" LD="${LD}" PKGCONFIG="${PKG_CONFIG}" \
CPPFLAGS="${CPPFLAGS}" CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" \
PYTHON=python3 PYTHON_CONFIG=${DEB_HOST_MULTIARCH}-python3-config \
@@ -252,12 +241,8 @@ override_dh_auto_install-arch:
# pam stuff
install -Dp -m0644 debian/winbind.pam-config debian/tmp/usr/share/pam-configs/winbind
mv debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/libnss_* debian/tmp/lib/$(DEB_HOST_MULTIARCH)/
- # Debian goodies to set global option in smb.conf and add a share
- install -p -m0755 debian/setoption.py -t debian/tmp/usr/share/samba/
- install -p -m0755 debian/addshare.py -t debian/tmp/usr/share/samba/
install -p -m755 debian/update-apparmor-samba-profile -t debian/tmp/usr/share/samba/
install -Dp -m0644 debian/samba.ufw.profile debian/tmp/etc/ufw/applications.d/samba
- install -Dp -m0644 debian/source_samba.py -t debian/tmp/usr/share/apport/package-hooks/
# install-and-rename docs for ctdb (also arch-specific)
mkdir -p debian/tmp/ctdb
install -p ctdb/config/events/README debian/tmp/ctdb/README.notification
@@ -280,6 +265,15 @@ endif
dh_link -plibldb2 /usr/lib/${DEB_HOST_MULTIARCH}/ldb/modules/ldb \
/usr/lib/${DEB_HOST_MULTIARCH}/samba/ldb/compat
+execute_after_dh_install:
+# some vfs modules are in separate packages. Removing them here avoids having
+# explicit list of other modules in d/samba.install
+ rm -f \
+ debian/samba/usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/glusterfs*.so \
+ debian/samba/usr/share/man/man8/vfs_glusterfs*.8 \
+ debian/samba/usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/ceph*.so \
+ debian/samba/usr/share/man/man8/vfs_ceph*.8
+
provision-dest := debian/samba-ad-provision/usr/share/samba/setup
override_dh_auto_install-indep:
@@ -291,9 +285,6 @@ override_dh_auto_install-indep:
ifeq (${DEB_VENDOR}, Ubuntu)
patch debian/samba-common/usr/share/samba/smb.conf debian/smb.conf.ubuntu.diff
endif
- install -Dp -m0755 debian/panic-action -t debian/samba-common/usr/share/samba/
- install -Dp -m0755 debian/is-configured -t debian/samba-common/usr/share/samba/
- install -Dp -m0644 debian/gdbcommands -t debian/samba-common/etc/samba/
# we wrongly have pam file in samba-common instead of samba
install -Dp -m0644 debian/samba.pam debian/samba-common/etc/pam.d/samba
@@ -312,8 +303,8 @@ ifpkg = $(if $(filter ${1},${build-pkgs}),${2})
override_dh_installinit:
ifneq (,$(filter samba, ${build-pkgs}))
dh_installinit -psamba --name smbd
- dh_installinit -psamba --name nmbd --error-handler nmbd_error_handler
- dh_installinit -psamba --name samba-ad-dc
+ dh_installinit -psamba --name nmbd
+ dh_installinit -psamba-ad-dc
endif
$(call ifpkg, winbind, dh_installinit -pwinbind)
ifneq (,$(filter ctdb, ${build-pkgs}))
@@ -326,7 +317,7 @@ override_dh_installsystemd:
ifneq (,$(filter samba, ${build-pkgs}))
dh_installsystemd -psamba --name=smbd
dh_installsystemd -psamba --name=nmbd
- dh_installsystemd -psamba --name=samba-ad-dc
+ dh_installsystemd -psamba-ad-dc
endif
$(call ifpkg, winbind, dh_installsystemd -pwinbind)
$(call ifpkg, ctdb, dh_installsystemd -pctdb --no-start --no-stop-on-upgrade)
@@ -361,7 +352,7 @@ override_dh_shlibdeps:
# for specific executables/modules, put dependencies in separate variables
# to change Depends to Recommends for them in d/control
dh_shlibdeps -l/usr/lib/${DEB_HOST_MULTIARCH}/samba \
- -Xceph.so -Xglusterfs.so -Xsnapper.so -Xctdb_mutex_ceph_rados_helper
+ -Xctdb_mutex_ceph_rados_helper
ifneq (,$(filter ctdb, ${build-pkgs}))
echo "rados:Depends=" >> debian/ctdb.substvars
ifneq (${with-ceph},)
@@ -369,15 +360,6 @@ ifneq (${with-ceph},)
debian/ctdb/usr/libexec/ctdb/ctdb_mutex_ceph_rados_helper
endif
endif
-ifneq (,$(filter samba-vfs-modules,${build-pkgs}))
- echo "vfsmods:Depends=" >> debian/samba-vfs-modules.substvars
-ifneq (${with-snapper}${with-ceph}${with-glusterfs},)
- dpkg-shlibdeps -Tdebian/samba-vfs-modules.substvars -pvfsmods \
- $(if ${with-snapper}, debian/samba-vfs-modules/usr/lib/*/samba/vfs/snapper.so) \
- $(if ${with-ceph}, debian/samba-vfs-modules/usr/lib/*/samba/vfs/ceph.so) \
- $(if ${with-glusterfs}, debian/samba-vfs-modules/usr/lib/*/samba/vfs/glusterfs.so)
-endif
-endif
# after shlibdeps run, check that we don't have wrong depdendencies
$(call depcheck, samba-libs, samba|winbind|smbclient|ctdb)
$(call depcheck, smbclient, samba|winbind|ctdb)
@@ -393,13 +375,14 @@ ifneq (,$(filter ${build-pkgs}, ${mitkrb5-dep-pkgs}))
dh_gencontrol $(addprefix -p, $(filter ${build-pkgs}, ${mitkrb5-dep-pkgs})) -- -v${mitkrb5-samba-ver} -Vldb:Depends="${LDB_DEPENDS}"
endif
dh_gencontrol --remaining-packages -- -Vldb:Depends="${LDB_DEPENDS}"
-# move files from / to /usr if needed (#1059187):
- if command -v dh_movetousr >/dev/null; then dh_movetousr -plibpam-winbind -plibnss-winbind; fi
+ifeq (,${before-trixie})
+# run dh_movetousr only on trixie and up, not before
+ dh_movetousr -plibpam-winbind -plibnss-winbind
+endif
clean:
# see also debian/clean
dh_clean bin/ testbuild/
- [ ! -f VERSION.orig ] || mv -f VERSION.orig VERSION
ifneq (,${with_mitkrb5})
[ ! -d third_party/heimdal-build-with-mitkrb5 ] || \
mv third_party/heimdal-build-with-mitkrb5 third_party/heimdal
diff --git a/debian/samba.samba-ad-dc.init b/debian/samba-ad-dc.init
index d88ca31..d88ca31 100644..100755
--- a/debian/samba.samba-ad-dc.init
+++ b/debian/samba-ad-dc.init
diff --git a/debian/samba-ad-dc.install b/debian/samba-ad-dc.install
new file mode 100644
index 0000000..baa0849
--- /dev/null
+++ b/debian/samba-ad-dc.install
@@ -0,0 +1,6 @@
+usr/sbin/samba
+usr/share/man/man8/samba.8
+usr/sbin/samba_dnsupdate
+usr/sbin/samba_spnupdate
+usr/sbin/samba_upgradedns
+usr/sbin/samba_kcc
diff --git a/debian/samba-ad-dc.lintian-overrides b/debian/samba-ad-dc.lintian-overrides
new file mode 100644
index 0000000..fd2c7a7
--- /dev/null
+++ b/debian/samba-ad-dc.lintian-overrides
@@ -0,0 +1,5 @@
+# begin-remove-after: trixie
+diversion-for-unknown-file lib/systemd/system/samba-ad-dc.service [preinst:*]
+# Breaks+Replaces upgraded to Conflicts for DEP17 + /usr-move
+conflicts-with-version samba (<< 2:4.20.1+dfsg-2~)
+# end-remove-after
diff --git a/debian/samba-ad-dc.postinst b/debian/samba-ad-dc.postinst
new file mode 100644
index 0000000..5427d99
--- /dev/null
+++ b/debian/samba-ad-dc.postinst
@@ -0,0 +1,16 @@
+#!/bin/sh
+set -e
+
+# begin-remove-after: released:trixie
+# protective diversion of files moved from / to /usr, to avoid file loss.
+# Only for upgrades.
+if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
+ dpkg-divert --package #PACKAGE# --no-rename \
+ --divert /lib/systemd/system/samba-ad-dc.service.usr-is-merged \
+ --remove /lib/systemd/system/samba-ad-dc.service
+fi
+# end-remove-after
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/samba-ad-dc.preinst b/debian/samba-ad-dc.preinst
new file mode 100644
index 0000000..a799680
--- /dev/null
+++ b/debian/samba-ad-dc.preinst
@@ -0,0 +1,16 @@
+#!/bin/sh
+set -e
+
+# begin-remove-after: released:trixie
+# protective diversion of files moved from / to /usr, to avoid file loss.
+# Only for upgrades.
+if [ "$1" = "upgrade" ] || [ "$1" = "install" ]; then
+ dpkg-divert --package #PACKAGE# --no-rename \
+ --divert /lib/systemd/system/samba-ad-dc.service.usr-is-merged \
+ --add /lib/systemd/system/samba-ad-dc.service
+fi
+# end-remove-after
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/samba.samba-ad-dc.service b/debian/samba-ad-dc.service
index fdee735..597a9ad 100644
--- a/debian/samba.samba-ad-dc.service
+++ b/debian/samba-ad-dc.service
@@ -8,6 +8,7 @@ After=network.target network-online.target
Type=notify
PIDFile=/run/samba/samba.pid
LimitNOFILE=16384
+Environment=SAMBAOPTIONS=
EnvironmentFile=-/etc/default/samba
ExecStart=/usr/sbin/samba --foreground --no-process-group $SAMBAOPTIONS
ExecReload=/bin/kill -HUP $MAINPID
diff --git a/debian/samba-common-bin.NEWS b/debian/samba-common-bin.NEWS
new file mode 100644
index 0000000..de3a2c9
--- /dev/null
+++ b/debian/samba-common-bin.NEWS
@@ -0,0 +1,9 @@
+samba (2:4.20.1+dfsg-1) unstable; urgency=medium
+
+ The tool samba-tool (python-based) has been moved from samba-common-bin
+ to python3-samba package. This is to avoid dependency on python modules
+ for minimal samba client installation. If you rely on samba-tool, please
+ ensure that the (optional in some configurations) python3-samba package is
+ also installed.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 26 May 2024 13:59:14 +0300
diff --git a/debian/samba-common-bin.dirs b/debian/samba-common-bin.dirs
index bbd723d..5e6ccf9 100644
--- a/debian/samba-common-bin.dirs
+++ b/debian/samba-common-bin.dirs
@@ -1,2 +1 @@
-etc/samba/tls
var/cache/samba
diff --git a/debian/samba-common-bin.install b/debian/samba-common-bin.install
index 696aa04..e8862e6 100644
--- a/debian/samba-common-bin.install
+++ b/debian/samba-common-bin.install
@@ -1,27 +1,24 @@
usr/bin/dbwrap_tool
usr/bin/net
usr/bin/nmblookup
-usr/bin/samba-log-parser
+debian/samba-log-parser usr/bin
+usr/bin/samba-log-parser usr/libexec/samba
usr/bin/samba-regedit
-usr/bin/samba-tool
+usr/bin/smbcontrol
usr/bin/smbpasswd
usr/bin/testparm
-usr/sbin/samba_kcc
-usr/share/apport/package-hooks/source_samba.py
usr/share/man/man1/dbwrap_tool.1
usr/share/man/man1/nmblookup.1
usr/share/man/man1/samba-log-parser.1
usr/share/man/man1/testparm.1
usr/share/man/man5/lmhosts.5
usr/share/man/man5/smb.conf.5
+usr/share/man/man1/smbcontrol.1
usr/share/man/man5/smbpasswd.5
usr/share/man/man7/samba.7
usr/share/man/man8/net.8
usr/share/man/man8/samba-regedit.8
-usr/share/man/man8/samba-tool.8
usr/share/man/man8/smbpasswd.8
-usr/share/samba/addshare.py
-usr/share/samba/setoption.py
# used by usr/bin/net only:
usr/lib/*/samba/libnet-keytab-private-samba.so.0
# used by usr/libexec/samba/rpcd_*:
diff --git a/debian/samba-common-bin.lintian-override b/debian/samba-common-bin.lintian-override
index b8e510a..79287f6 100644
--- a/debian/samba-common-bin.lintian-override
+++ b/debian/samba-common-bin.lintian-override
@@ -1,2 +1,4 @@
# deliberate, a synonym for misspelled parameter
samba-common-bin: typo-in-manual-page prefered preferred */man/man5/smb.conf.5*
+# python script wrapped in #!/bin/sh
+samba-common-bin: bash-term-in-posix-shell *usr/bin/samba-log-parser*
diff --git a/debian/samba-common.install b/debian/samba-common.install
new file mode 100644
index 0000000..7986e10
--- /dev/null
+++ b/debian/samba-common.install
@@ -0,0 +1,3 @@
+debian/is-configured usr/share/samba/
+debian/panic-action usr/share/samba/
+debian/gdbcommands etc/samba/
diff --git a/debian/samba-log-parser b/debian/samba-log-parser
new file mode 100755
index 0000000..09f6bcd
--- /dev/null
+++ b/debian/samba-log-parser
@@ -0,0 +1,5 @@
+#! /bin/sh
+me="${0##*/}"
+command -v python3 >/dev/null && exec /usr/libexec/samba/$me "$@"
+echo "$me: E: This program requires python3. Please install python3 package to use it." >&2
+exit 42
diff --git a/debian/samba-vfs-ceph.install b/debian/samba-vfs-ceph.install
new file mode 100644
index 0000000..be619c1
--- /dev/null
+++ b/debian/samba-vfs-ceph.install
@@ -0,0 +1,4 @@
+usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/ceph.so
+usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/ceph_snapshots.so
+usr/share/man/man8/vfs_ceph.8
+usr/share/man/man8/vfs_ceph_snapshots.8
diff --git a/debian/samba-vfs-ceph.lintian-overrides b/debian/samba-vfs-ceph.lintian-overrides
new file mode 100644
index 0000000..26cc8ed
--- /dev/null
+++ b/debian/samba-vfs-ceph.lintian-overrides
@@ -0,0 +1 @@
+samba-vfs-ceph: spare-manual-page */man/man8/vfs_*
diff --git a/debian/samba-vfs-glusterfs.install b/debian/samba-vfs-glusterfs.install
new file mode 100644
index 0000000..c360548
--- /dev/null
+++ b/debian/samba-vfs-glusterfs.install
@@ -0,0 +1,4 @@
+usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/glusterfs.so
+usr/lib/${DEB_HOST_MULTIARCH}/samba/vfs/glusterfs_fuse.so
+usr/share/man/man8/vfs_glusterfs.8
+usr/share/man/man8/vfs_glusterfs_fuse.8
diff --git a/debian/samba-vfs-glusterfs.lintian-overrides b/debian/samba-vfs-glusterfs.lintian-overrides
new file mode 100644
index 0000000..c864cd4
--- /dev/null
+++ b/debian/samba-vfs-glusterfs.lintian-overrides
@@ -0,0 +1 @@
+samba-vfs-glusterfs: spare-manual-page */man/man8/vfs_*
diff --git a/debian/samba-vfs-modules.NEWS b/debian/samba-vfs-modules.NEWS
new file mode 100644
index 0000000..973e561
--- /dev/null
+++ b/debian/samba-vfs-modules.NEWS
@@ -0,0 +1,15 @@
+samba-vfs-modules (2:4.20.2+dfsg-3) unstable; urgency=medium
+
+ samba-vfs-modules package has been dropped in this release.
+ Instead, all common vfs modules are now part of regular samba
+ package, so are always installed (so there is not need to install
+ samba-vfs-modules for, say, wide links = yes to work, ad-dc always
+ works too and so on).
+
+ At the same time, glusterfs and ceph vfs modules are now shipped in
+ their own separate packages, samba-vfs-glusterfs and samba-vfs-ceph
+ (samba-vfs-glusterfs in universe in ubuntu). If you need ceph or
+ glusterfs functionality, please install samba-vfs-ceph and/or
+ samba-vfs-glusterfs package(s) separately.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Mon, 24 Jun 2024 12:48:23 +0300
diff --git a/debian/samba-vfs-modules.install b/debian/samba-vfs-modules.install
deleted file mode 100644
index c82d897..0000000
--- a/debian/samba-vfs-modules.install
+++ /dev/null
@@ -1,3 +0,0 @@
-usr/lib/*/samba/vfs/*.so
-usr/share/man/man8/vfs_*.8
-usr/lib/*/samba/libdfs-server-ad-private-samba.so.0
diff --git a/debian/samba-vfs-modules.lintian-overrides b/debian/samba-vfs-modules.lintian-overrides
deleted file mode 100644
index 5e2bcbb..0000000
--- a/debian/samba-vfs-modules.lintian-overrides
+++ /dev/null
@@ -1,7 +0,0 @@
-# False positives, see #896012
-samba-vfs-modules: library-not-linked-against-libc *
-# manpages describing vfs modules:
-samba-vfs-modules: spare-manual-page */man/man8/vfs_*
-# intentional: was a typo in old config parser so we allow old config to work:
-samba-vfs-modules: hardening-no-fortify-functions */samba/vfs/expand_msdfs.so*
-samba-vfs-modules: hardening-no-fortify-functions */samba/vfs/fileid.so*
diff --git a/debian/samba.NEWS b/debian/samba.NEWS
index 5f4c14f..ddf0709 100644
--- a/debian/samba.NEWS
+++ b/debian/samba.NEWS
@@ -1,3 +1,13 @@
+samba (2:4.20.1+dfsg-2) unstable; urgency=medium
+
+ Active Directory Domain Controller (AD-DC) functionality has been split out
+ of main samba (the file server) package into its own separate package named
+ samba-ad-dc. This includes the samba binary, the startup files and a few
+ support executables. Please additionally install samba-ad-dc package if
+ you need AD-DC functionality on your system.
+
+ -- Michael Tokarev <mjt@tls.msk.ru> Sun, 26 May 2024 13:44:07 +0300
+
samba (2:4.6.5+dfsg-5) unstable; urgency=medium
The samba service has been removed. Use the individual services instead:
diff --git a/debian/samba.dirs b/debian/samba.dirs
index cd0dcc6..463322a 100644
--- a/debian/samba.dirs
+++ b/debian/samba.dirs
@@ -1,6 +1,4 @@
etc/apparmor.d/samba
-usr/bin
-usr/sbin
var/lib/samba/printers/COLOR
var/lib/samba/printers/IA64
var/lib/samba/printers/W32ALPHA
diff --git a/debian/samba.install b/debian/samba.install
index 498557c..6273a23 100755
--- a/debian/samba.install
+++ b/debian/samba.install
@@ -6,7 +6,6 @@ usr/bin/oLschema2ldif
usr/bin/pdbedit
usr/bin/profiles
usr/bin/sharesec
-usr/bin/smbcontrol
usr/bin/smbstatus
<!pkg.samba.mitkrb5> usr/lib/*/samba/libHDB-SAMBA4-private-samba.so.0
<!pkg.samba.mitkrb5> usr/lib/*/samba/libgss-preauth-private-samba.so.0
@@ -18,28 +17,23 @@ usr/libexec/samba/samba-bgqd
usr/lib/*/samba/service/*.so
usr/sbin/eventlogadm
usr/sbin/nmbd
-usr/sbin/samba
-usr/sbin/samba-gpupdate
-usr/sbin/samba_dnsupdate
-usr/sbin/samba_downgrade_db
-usr/sbin/samba_spnupdate
-usr/sbin/samba_upgradedns
usr/sbin/smbd
usr/share/man/man1/log2pcap.1
usr/share/man/man1/mvxattr.1
usr/share/man/man1/oLschema2ldif.1
usr/share/man/man1/profiles.1
usr/share/man/man1/sharesec.1
-usr/share/man/man1/smbcontrol.1
usr/share/man/man1/smbstatus.1
usr/share/man/man8/eventlogadm.8
usr/share/man/man8/nmbd.8
usr/share/man/man8/pdbedit.8
usr/share/man/man8/samba-bgqd.8
-usr/share/man/man8/samba_downgrade_db.8
-usr/share/man/man8/samba-gpupdate.8
-usr/share/man/man8/samba.8
usr/share/man/man8/smbd.8
usr/share/samba/admx/
usr/share/samba/mdssvc/elasticsearch_mappings.json
usr/share/samba/update-apparmor-samba-profile
+
+# vfs modules
+usr/lib/*/samba/vfs/*.so
+usr/share/man/man8/vfs_*.8
+usr/lib/*/samba/libdfs-server-ad-private-samba.so.0
diff --git a/debian/samba.lintian-overrides b/debian/samba.lintian-overrides
index 128f6e8..54bcfe1 100644
--- a/debian/samba.lintian-overrides
+++ b/debian/samba.lintian-overrides
@@ -1 +1,7 @@
samba: hardening-no-fortify-functions */samba/libmscat-private-samba.so.*
+# False positives, see #896012
+samba: library-not-linked-against-libc *
+# manpages describing vfs modules (they're named vfs_foo while the module is vfs/foo.so):
+samba: spare-manual-page */man/man8/vfs_*
+samba: hardening-no-fortify-functions */samba/vfs/expand_msdfs.so*
+samba: hardening-no-fortify-functions */samba/vfs/fileid.so*
diff --git a/debian/samba.nmbd.service b/debian/samba.nmbd.service
index 4f74f49..010c845 100644
--- a/debian/samba.nmbd.service
+++ b/debian/samba.nmbd.service
@@ -7,6 +7,7 @@ After=network.target network-online.target
[Service]
Type=notify
PIDFile=/run/samba/nmbd.pid
+Environment=NMBDOPTIONS=
EnvironmentFile=-/etc/default/samba
ExecStart=/usr/sbin/nmbd --foreground --no-process-group $NMBDOPTIONS
ExecReload=/bin/kill -HUP $MAINPID
diff --git a/debian/samba.postinst b/debian/samba.postinst
index ceb0b64..f15dfa5 100644
--- a/debian/samba.postinst
+++ b/debian/samba.postinst
@@ -2,23 +2,6 @@
set -e
-nmbd_error_handler() {
- if [ -d /sys/class/net/lo ] && ls /sys/class/net | grep -qv ^lo$; then
- # https://bugs.debian.org/893762
- echo 'WARNING: nmbd failed to start as there is no non-loopback interfaces available.'
- echo 'Either add an interface or set "disable netbios = yes" in smb.conf'
- return 0
- elif command -v ip > /dev/null && ip a show | grep '^[[:space:]]*inet ' | grep -vq ' lo$'; then
- # https://bugs.debian.org/859526
- echo 'WARNING: nmbd failed to start as there is no local IPv4 non-loopback interfaces available.'
- echo 'Either add an IPv4 address or set "disable netbios = yes" in smb.conf'
- return 0
- else
- echo 'ERROR: nmbd failed to start.'
- return 1 # caught by set -e
- fi
-}
-
# We generate several files during the postinst, and we don't want
# them to be readable only by root.
umask 022
diff --git a/debian/samba.smbd.service b/debian/samba.smbd.service
index a5b7929..5bff436 100644
--- a/debian/samba.smbd.service
+++ b/debian/samba.smbd.service
@@ -8,6 +8,7 @@ After=network.target network-online.target nmb.service winbind.service
Type=notify
PIDFile=/run/samba/smbd.pid
LimitNOFILE=16384
+Environment=SMBDOPTIONS=
EnvironmentFile=-/etc/default/samba
ExecStartPre=/usr/share/samba/update-apparmor-samba-profile
ExecStart=/usr/sbin/smbd --foreground --no-process-group $SMBDOPTIONS
diff --git a/debian/setoption.py b/debian/setoption.py
deleted file mode 100755
index a3f3695..0000000
--- a/debian/setoption.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python3
-# Helper to set a global option in the samba configuration file
-# Eventually this should be replaced by a call to samba-tool, but
-# for the moment that doesn't support setting individual configuration options.
-
-import optparse
-import os
-import re
-import shutil
-import stat
-import tempfile
-
-parser = optparse.OptionParser()
-parser.add_option("--configfile", type=str, metavar="CONFFILE",
- help="Configuration file to use", default="/etc/samba/smb.conf")
-
-(opts, args) = parser.parse_args()
-if len(args) != 2:
- parser.print_usage()
-
-(key, value) = args
-inglobal = False
-done = False
-
-inf = open(opts.configfile, 'r')
-(fd, fn) = tempfile.mkstemp()
-outf = os.fdopen(fd, 'w')
-
-for l in inf.readlines():
- m = re.match(r"^\s*\[([^]]+)\]$", l)
- if m:
- if inglobal and not done:
- outf.write(" %s = %s\n" % (key, value))
- done = True
- inglobal = (m.groups(1)[0] in ("global", "globals"))
- elif inglobal and re.match(r"^(\s*)" + key + r"(\s*)=.*$", l):
- l = re.sub(r"^(\s*)" + key + r"(\s*)=.*$",
- r"\1" + key + r"\2=\2" + value, l)
- done = True
- outf.write(l)
-
-if not done:
- outf.write("%s = %s\n" % (key, value))
-
-os.fchmod(fd, stat.S_IMODE(os.stat(opts.configfile).st_mode))
-outf.close()
-shutil.move(fn, opts.configfile)
diff --git a/debian/source_samba.py b/debian/source_samba.py
deleted file mode 100644
index 1d30625..0000000
--- a/debian/source_samba.py
+++ /dev/null
@@ -1,170 +0,0 @@
-#!/usr/bin/python3
-
-'''Samba Apport interface
-
-Copyright (C) 2010 Canonical Ltd/
-Author: Chuck Short <chuck.short@canonical.com>
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2 of the License, or (at your
-option) any later version. See http://www.gnu.org/copyleft/gpl.html for
-the full text of the license.
-'''
-
-import os
-from subprocess import PIPE, Popen
-from apport.hookutils import *
-
-def run_testparm():
- '''
- Run the samba testparm(1) utility against /etc/samba/smb.conf.
-
- We do not use apport's command_output() method here because:
- - we need to discard stdout, as that includes smb.conf
- - we want to know if its exit status is not zero, but that in itself
- is not an error in the test itself. command_output() would say the
- command failed and that would be confusing.
-
- Returns stderr and the exit code (as a string) of testparm as a tuple or
- None in the case of an error.
- '''
- command = ['testparm', '-s', '/etc/samba/smb.conf']
- try:
- testparm = Popen(command, stdout=PIPE, stderr=PIPE)
- except OSError:
- return None
- _, err = testparm.communicate()
- exit_code = testparm.wait()
- return (err, str(exit_code))
-
-
-def recent_smblog(pattern):
- '''Extract recent messages from log.smbd or messages which match a regex
- pattern should be a "re" object. '''
- lines = ''
- if os.path.exists('/var/log/samba/log.smbd'):
- file = '/var/log/samba/log.smbd'
- else:
- return lines
-
- for line in open(file):
- if pattern.search(line):
- lines += line
- return lines
-
-def recent_nmbdlog(pattern):
- ''' Extract recent messages from log.nmbd or messages which match regex
- pattern should be a "re" object. '''
- lines = ''
- if os.path.exists('/var/log/samba/log.nmbd'):
- file = '/var/log/samba/log.nmbd'
- else:
- return lines
-
- for line in open(file):
- if pattern.search(line):
- lines += line
- return lines
-
-def add_info(report, ui):
- packages = ['samba', 'samba-common-bin', 'samba-common', 'samba-tools', 'smbclient', 'swat',
- 'samba-doc', 'samba-doc-pdf', 'smbfs', 'libpam-smbpass', 'libsmbclient', 'libsmbclient-dev',
- 'winbind', 'samba-dbg', 'libwbclient0']
-
- versions = ''
- for package in packages:
- try:
- version = packaging.get_version(package)
- except ValueError:
- version = 'N/A'
- if version is None:
- version = 'N/A'
- versions += '%s %s\n' %(package, version)
- report['SambaInstalledVersions'] = versions
-
-
- # Interactive report
- # start by checking if /etc/samba/smb.conf exists
- if not os.path.exists ('/etc/samba/smb.conf'):
- ui.information("The configuration file '/etc/samba/smb.conf' does not exist. This file, and its contents, are critical for the operation of the SAMBA package(s). A common situation for this is:\n * you removed (but did not purge) SAMBA;\n * later on, you (or somebody) manually deleted '/etc/samba/smb.conf;\n * you reinstalled SAMBA.\nAs a result, this file is *not* reinstalled. If this is your case, please purge samba-common (e.g., sudo apt-get purge samba-common) and then reinstall SAMBA.\nYou may want to check other sources, like: https://answers.launchpad.net, https://help.ubuntu.com, and http://ubuntuforums.org. Please press any key to end apport's bug collection.")
- raise StopIteration # we are out
-
- ui.information("As a part of the bug reporting process, you'll be asked as series of questions to help provide a more descriptive bug report. Please answer the following questions to the best of your abilities. Afterwards, a browser will be opened to finish filing this as a bug in the Launchpad bug tracking system.")
-
- response = ui.choice("How would you best describe your setup?", ["I am running a Windows File Server.", "I am connecting to a Windows File Server."], False)
-
- if response == None:
- raise StopIteration # user has canceled
- elif response[0] == 0: #its a server
- response = ui.yesno("Did this used to work properly with a previous release?")
- if response == None: # user has canceled
- raise StopIteration
- if response == False:
- report['SambaServerRegression'] = "No"
- if response == True:
- report['SambaServerRegression'] = 'Yes'
-
- response = ui.choice("Which clients are failing to connect?", ["Windows", "Ubuntu", "Both", "Other"], False)
- if response == None:
- raise StopIteration # user has canceled
- if response[0] == 0:
- report['UbuntuFailedConnect'] = 'Yes'
- if response[0] == 1:
- report['WindowsFailedConnect'] = 'Yes'
- if response[0] == 2:
- report['BothFailedConnect'] = 'Yes'
- if response[0] == 3:
- report['OtherFailedConnect'] = 'Yes'
-
- response = ui.yesno("The contents of your /etc/samba/smb.conf file may help developers diagnose your bug more quickly. However, it may contain sensitive information. Do you want to include it in your bug report?")
- if response == None:
- raise StopIteration
- if response == False:
- report['SmbConfIncluded'] = 'No'
- if response == True:
- report['SmbConfIncluded'] = 'Yes'
- attach_file_if_exists(report, '/etc/samba/smb.conf', key='SMBConf')
- if command_available('testparm') and os.path.exists('/etc/samba/smb.conf'):
- testparm_result = run_testparm()
- testparm_response = ui.yesno("testparm(1) is a samba utility that will check /etc/samba/smb.conf for correctness and report issues it may find. Do you want to include its stderr output in your bug report? If you answer no, then we will only include its numeric exit status.")
- if testparm_response == None:
- raise StopIteration
- if testparm_response == True:
- if testparm_result:
- report['TestparmStderr'], report['TestparmExitCode'] = testparm_result
- else: # only include the exit code
- report['TestparmExitCode'] = testparm_result[1]
-
- response = ui.yesno("The contents of your /var/log/samba/log.smbd and /var/log/samba/log.nmbd may help developers diagnose your bug more quickly. However, it may contain sensitive information. Do you want to include it in your bug report?")
- if response == None:
- raise StopIteration
- elif response == False:
- ui.information("The contents of your /var/log/samba/log.smbd and /var/log/samba/log.nmbd will NOT be included in the bug report.")
- elif response == True:
- sec_re = re.compile('failed', re.IGNORECASE)
- report['SmbLog'] = recent_smblog(sec_re)
- report['NmbdLog'] = recent_nmbdlog(sec_re)
-
- elif response[0] == 1: #its a client
- response = ui.yesno("Did this used to work properly with a previous release?")
- if response == None: #user has canceled
- raise StopIteration
- if response == False:
- report['SambaClientRegression'] = "No"
- if response == True:
- report['SambaClientRegression'] = "Yes"
-
- response = ui.choice("How is the remote share accessed from the Ubuntu system?", ["Nautilus (or other GUI Client)", "smbclient (from the command line)", "cifs filesystem mount (from /etc/fstab or a mount command)"], False)
- if response == None: #user has canceled
- raise StopIteration
- if response[0] == 0:
- attach_related_packages(report, ['nautilus', 'gvfs'])
- if response[0] == 1:
- ui.information("Please attach the output of 'smbclient -L localhost' to the end of this bug report.")
- if response[0] == 2:
- report['CIFSMounts'] = command_output(['findmnt', '-n', '-t', 'cifs'])
- if os.path.exists('/proc/fs/cifs/DebugData'):
- report['CifsVersion'] = command_output(['cat', '/proc/fs/cifs/DebugData'])
-
- ui.information("After apport finishes collecting information, please document your steps to reproduce the issue when filling out the bug report.")
diff --git a/debian/tests/control b/debian/tests/control
index d27e025..e51a37c 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -3,7 +3,7 @@ Depends: samba, coreutils, systemd, cifs-utils, passwd
Restrictions: needs-root, allow-stderr, isolation-machine
Tests: cifs-share-access-uring
-Depends: samba, samba-vfs-modules, coreutils, systemd, cifs-utils, passwd
+Depends: samba, coreutils, systemd, cifs-utils, passwd
Restrictions: needs-root, allow-stderr, isolation-machine, skippable
Tests: python-smoke
@@ -22,7 +22,7 @@ Depends: samba, smbclient, coreutils, systemd, passwd
Restrictions: needs-root, allow-stderr, isolation-container
Tests: smbclient-share-access-uring
-Depends: samba, samba-vfs-modules, smbclient, coreutils, systemd, passwd
+Depends: samba, smbclient, coreutils, systemd, passwd
Restrictions: needs-root, allow-stderr, isolation-container, skippable
Tests: reinstall-samba-common-bin
diff --git a/debian/winbind.service b/debian/winbind.service
index 5b009a4..1c21d28 100644
--- a/debian/winbind.service
+++ b/debian/winbind.service
@@ -7,6 +7,7 @@ Before=nss-user-lookup.target
[Service]
Type=notify
PIDFile=/run/samba/winbindd.pid
+Environment=WINBINDOPTIONS=
EnvironmentFile=-/etc/default/samba
ExecStart=/usr/sbin/winbindd --foreground --no-process-group $WINBINDOPTIONS
ExecReload=/bin/kill -HUP $MAINPID
diff --git a/examples/winexe/wscript b/examples/winexe/wscript
index 6b311b1..c4f13b8 100644
--- a/examples/winexe/wscript
+++ b/examples/winexe/wscript
@@ -1,4 +1,6 @@
#!/usr/bin/env python
+import os
+
def configure(conf):
AR32 = ['i386', 'i586', 'i686']
@@ -27,5 +29,24 @@ def configure(conf):
conf.DEFINE('HAVE_WINEXE_CC_WIN64', 1);
break
+ source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH')
+ if source_date_epoch is None:
+ # We use the version to make up the timestamp that will be
+ # embedded in winexe.exe, to keep the build reproducible.
+ #
+ # This is less evil than it sounds. According to Raymond Chen in
+ # https://devblogs.microsoft.com/oldnewthing/20180103-00/?p=97705
+ # since Windows 10 the timestamp has been randomised.
+ #
+ # The purpose of the timestamp in Windows PE files seems to be
+ # to make spotting ABI changes in DLLs quicker, for which a
+ # random number is just as good as a real time. The timestamp
+ # in .exe files is not used.
+ import samba_version
+ v = samba_version.load_version(env=conf.env)
+ version = (v.MAJOR << 16) | (v.MINOR << 8) | v.RELEASE
+ source_date_epoch = str(version)
+
+ conf.env.SOURCE_DATE_EPOCH = source_date_epoch
conf.DEFINE("WINEXE_LDFLAGS",
"-s -Wall -Wl,-Bstatic -Wl,-Bdynamic -luserenv")
diff --git a/examples/winexe/wscript_build b/examples/winexe/wscript_build
index 3646834..1fe019c 100644
--- a/examples/winexe/wscript_build
+++ b/examples/winexe/wscript_build
@@ -69,7 +69,7 @@ bld.SAMBA_GENERATOR(
'winexesvc32_exe',
source='winexesvc.c',
target='winexesvc32.exe',
- rule='${WINEXE_CC_WIN32} ${SRC} -o ${TGT} ${WINEXE_LDFLAGS}',
+ rule='SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} ${WINEXE_CC_WIN32} ${SRC} -o ${TGT} ${WINEXE_LDFLAGS}',
enabled=bld.env.build_winexe and bld.env.WINEXE_CC_WIN32)
vars = {"WINEXE_FN": "winexesvc32_exe_binary"}
@@ -89,7 +89,7 @@ bld.SAMBA_GENERATOR(
'winexesvc64_exe',
source='winexesvc.c',
target='winexesvc64.exe',
- rule='${WINEXE_CC_WIN64} ${SRC} -o ${TGT} ${WINEXE_LDFLAGS}',
+ rule='SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} ${WINEXE_CC_WIN64} ${SRC} -o ${TGT} ${WINEXE_LDFLAGS}',
enabled=bld.env.build_winexe and bld.env.WINEXE_CC_WIN64)
vars = {"WINEXE_FN": "winexesvc64_exe_binary"}
diff --git a/lib/fuzzing/decode_ndr_X_crash b/lib/fuzzing/decode_ndr_X_crash
index 63c3cd7..d90e7ef 100755
--- a/lib/fuzzing/decode_ndr_X_crash
+++ b/lib/fuzzing/decode_ndr_X_crash
@@ -61,8 +61,9 @@ def process_one_file(f):
def main():
parser = argparse.ArgumentParser()
- parser.add_argument('-p', '--pipe', default='$PIPE',
- help='pipe name (for output command line)')
+ parser.add_argument('-p', '--pipe', default=None,
+ help=('pipe name (for output command line, '
+ 'default is a guess or "$PIPE")'))
parser.add_argument('-t', '--type', default=None, choices=TYPES,
help='restrict to this type')
parser.add_argument('-o', '--opnum', default=None, type=int,
@@ -91,6 +92,13 @@ def main():
sys.exit(1)
for fn in args.FILES:
+ if pipe is None:
+ m = re.search(r'clusterfuzz-testcase.+-fuzz_ndr_([a-z]+)', fn)
+ if m is None:
+ pipe = '$PIPE'
+ else:
+ pipe = m.group(1)
+
if args.crash_filter is not None:
if not re.search(args.crash_filter, fn):
print_if_verbose(f"skipping {fn}")
diff --git a/lib/ldb-samba/ldif_handlers.c b/lib/ldb-samba/ldif_handlers.c
index c30fd63..4f9d67e 100644
--- a/lib/ldb-samba/ldif_handlers.c
+++ b/lib/ldb-samba/ldif_handlers.c
@@ -150,36 +150,47 @@ bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
/*
compare two objectSids
+
+ If the SIDs seem to be strings, they are converted to binary form.
*/
static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
- if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
- return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
- } else if (ldif_comparision_objectSid_isString(v1)
- && !ldif_comparision_objectSid_isString(v2)) {
- struct ldb_val v;
- int ret;
- if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
- /* Perhaps not a string after all */
- return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
+ bool v1_is_string = ldif_comparision_objectSid_isString(v1);
+ bool v2_is_string = ldif_comparision_objectSid_isString(v2);
+ struct ldb_val parsed_1 = {};
+ struct ldb_val parsed_2 = {};
+ int ret;
+ /*
+ * If the ldb_vals look like SID strings (i.e. start with "S-"
+ * or "s-"), we try to parse them as such. If that fails, we
+ * assume they are binary SIDs, even though that's not really
+ * possible -- the first two bytes of a struct dom_sid are the
+ * version (1), and the number of sub-auths (<= 15), neither
+ * of which are close to 'S' or '-'.
+ */
+ if (v1_is_string) {
+ int r = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
+ if (r == 0) {
+ v1 = &parsed_1;
}
- ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
- talloc_free(v.data);
- return ret;
- } else if (!ldif_comparision_objectSid_isString(v1)
- && ldif_comparision_objectSid_isString(v2)) {
- struct ldb_val v;
- int ret;
- if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
- /* Perhaps not a string after all */
- return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
+ }
+ if (v2_is_string) {
+ int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
+ if (r == 0) {
+ v2 = &parsed_2;
}
- ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
- talloc_free(v.data);
- return ret;
}
- return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
+
+ ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
+
+ if (v1_is_string) {
+ TALLOC_FREE(parsed_1.data);
+ }
+ if (v2_is_string) {
+ TALLOC_FREE(parsed_2.data);
+ }
+ return ret;
}
/*
@@ -1148,22 +1159,41 @@ static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
struct ldb_dn *dn1 = NULL, *dn2 = NULL;
int ret;
+ /*
+ * In a sort context, Deleted DNs get shifted to the end.
+ * They never match in an equality
+ */
if (dsdb_dn_is_deleted_val(v1)) {
- /* If the DN is deleted, then we can't search for it */
- return -1;
- }
-
- if (dsdb_dn_is_deleted_val(v2)) {
- /* If the DN is deleted, then we can't search for it */
+ if (! dsdb_dn_is_deleted_val(v2)) {
+ return 1;
+ }
+ /*
+ * They are both deleted!
+ *
+ * The soundest thing to do at this point is carry on
+ * and compare the DNs normally. This matches the
+ * behaviour of samba_dn_extended_match() below.
+ */
+ } else if (dsdb_dn_is_deleted_val(v2)) {
return -1;
}
dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
- if ( ! ldb_dn_validate(dn1)) return -1;
-
dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
+
+ if ( ! ldb_dn_validate(dn1)) {
+ TALLOC_FREE(dn1);
+ if ( ! ldb_dn_validate(dn2)) {
+ TALLOC_FREE(dn2);
+ return 0;
+ }
+ TALLOC_FREE(dn2);
+ return 1;
+ }
+
if ( ! ldb_dn_validate(dn2)) {
- talloc_free(dn1);
+ TALLOC_FREE(dn1);
+ TALLOC_FREE(dn2);
return -1;
}
diff --git a/lib/ldb/ABI/ldb-2.9.1.sigs b/lib/ldb/ABI/ldb-2.9.1.sigs
new file mode 100644
index 0000000..759659a
--- /dev/null
+++ b/lib/ldb/ABI/ldb-2.9.1.sigs
@@ -0,0 +1,305 @@
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
+ldb_attr_dn: int (const char *)
+ldb_attr_in_list: int (const char * const *, const char *)
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
+ldb_base64_decode: int (char *)
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
+ldb_check_critical_controls: int (struct ldb_control **)
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
+ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val)
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
+ldb_dn_get_comp_num: int (struct ldb_dn *)
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
+ldb_dn_has_extended: bool (struct ldb_dn *)
+ldb_dn_is_null: bool (struct ldb_dn *)
+ldb_dn_is_special: bool (struct ldb_dn *)
+ldb_dn_is_valid: bool (struct ldb_dn *)
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
+ldb_dn_minimise: bool (struct ldb_dn *)
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
+ldb_dn_validate: bool (struct ldb_dn *)
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
+ldb_errstring: const char *(struct ldb_context *)
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *)
+ldb_filter_attrs_in_place: int (struct ldb_message *, const char * const *)
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_create_perms: unsigned int (struct ldb_context *)
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
+ldb_get_flags: unsigned int (struct ldb_context *)
+ldb_get_opaque: void *(struct ldb_context *, const char *)
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
+ldb_global_init: int (void)
+ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
+ldb_handle_use_global_event_context: void (struct ldb_handle *)
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
+ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
+ldb_load_modules: int (struct ldb_context *, const char **)
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
+ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *)
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
+ldb_match_scope: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *, enum ldb_scope)
+ldb_mod_register_control: int (struct ldb_module *, const char *)
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
+ldb_module_flags: uint32_t (struct ldb_context *)
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
+ldb_module_get_name: const char *(struct ldb_module *)
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
+ldb_module_get_private: void *(struct ldb_module *)
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
+ldb_module_next: struct ldb_module *(struct ldb_module *)
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
+ldb_module_send_referral: int (struct ldb_request *, char *)
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
+ldb_module_set_private: void (struct ldb_module *, void *)
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_modules_load: int (const char *, const char *)
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
+ldb_msg_add_distinguished_name: int (struct ldb_message *)
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
+ldb_msg_add_string_flags: int (struct ldb_message *, const char *, const char *, int)
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
+ldb_msg_append_fmt: int (struct ldb_message *, int, const char *, const char *, ...)
+ldb_msg_append_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *, int)
+ldb_msg_append_steal_string: int (struct ldb_message *, const char *, char *, int)
+ldb_msg_append_steal_value: int (struct ldb_message *, const char *, struct ldb_val *, int)
+ldb_msg_append_string: int (struct ldb_message *, const char *, const char *, int)
+ldb_msg_append_value: int (struct ldb_message *, const char *, const struct ldb_val *, int)
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
+ldb_msg_element_add_value: int (TALLOC_CTX *, struct ldb_message_element *, const struct ldb_val *)
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
+ldb_msg_element_is_inaccessible: bool (const struct ldb_message_element *)
+ldb_msg_element_mark_inaccessible: void (struct ldb_message_element *)
+ldb_msg_elements_take_ownership: int (struct ldb_message *)
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
+ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t)
+ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t)
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
+ldb_msg_remove_inaccessible: void (struct ldb_message *)
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
+ldb_msg_shrink_to_fit: void (struct ldb_message *)
+ldb_msg_sort_elements: void (struct ldb_message *)
+ldb_next_del_trans: int (struct ldb_module *)
+ldb_next_end_trans: int (struct ldb_module *)
+ldb_next_init: int (struct ldb_module *)
+ldb_next_prepare_commit: int (struct ldb_module *)
+ldb_next_read_lock: int (struct ldb_module *)
+ldb_next_read_unlock: int (struct ldb_module *)
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
+ldb_next_start_trans: int (struct ldb_module *)
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_options_copy: const char **(TALLOC_CTX *, const char **)
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
+ldb_options_get: const char **(struct ldb_context *)
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t)
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
+ldb_parse_tree_get_attr: const char *(const struct ldb_parse_tree *)
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
+ldb_register_hook: int (ldb_hook_fn)
+ldb_register_module: int (const struct ldb_module_ops *)
+ldb_register_redact_callback: int (struct ldb_context *, ldb_redact_fn, struct ldb_module *)
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
+ldb_req_is_untrusted: bool (struct ldb_request *)
+ldb_req_location: const char *(struct ldb_request *)
+ldb_req_mark_trusted: void (struct ldb_request *)
+ldb_req_mark_untrusted: void (struct ldb_request *)
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
+ldb_req_set_location: void (struct ldb_request *, const char *)
+ldb_request: int (struct ldb_context *, struct ldb_request *)
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_done: int (struct ldb_request *, int)
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
+ldb_request_get_status: int (struct ldb_request *)
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
+ldb_request_set_state: void (struct ldb_request *, int)
+ldb_reset_err_string: void (struct ldb_context *)
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
+ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *)
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
+ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
+ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *)
+ldb_schema_set_override_indexlist: void (struct ldb_context *, bool)
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
+ldb_set_debug_stderr: int (struct ldb_context *)
+ldb_set_default_dns: void (struct ldb_context *)
+ldb_set_errstring: void (struct ldb_context *, const char *)
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
+ldb_set_flags: void (struct ldb_context *, unsigned int)
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
+ldb_set_require_private_event_context: void (struct ldb_context *)
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
+ldb_set_utf8_default: void (struct ldb_context *)
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
+ldb_strerror: const char *(int)
+ldb_string_to_time: time_t (const char *)
+ldb_string_utc_to_time: time_t (const char *)
+ldb_timestring: char *(TALLOC_CTX *, time_t)
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
+ldb_transaction_cancel: int (struct ldb_context *)
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
+ldb_transaction_commit: int (struct ldb_context *)
+ldb_transaction_prepare_commit: int (struct ldb_context *)
+ldb_transaction_start: int (struct ldb_context *)
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
+ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int)
+ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *)
+ldb_val_as_bool: int (const struct ldb_val *, bool *)
+ldb_val_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_val *)
+ldb_val_as_int64: int (const struct ldb_val *, int64_t *)
+ldb_val_as_uint64: int (const struct ldb_val *, uint64_t *)
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
+ldb_valid_attr_name: int (const char *)
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
diff --git a/lib/ldb/ABI/pyldb-util-2.9.1.sigs b/lib/ldb/ABI/pyldb-util-2.9.1.sigs
new file mode 100644
index 0000000..164a806
--- /dev/null
+++ b/lib/ldb/ABI/pyldb-util-2.9.1.sigs
@@ -0,0 +1,3 @@
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
+pyldb_check_type: bool (PyObject *, const char *)
diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c
index 15470cf..3d13e4b 100644
--- a/lib/ldb/common/attrib_handlers.c
+++ b/lib/ldb/common/attrib_handlers.c
@@ -281,15 +281,36 @@ static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
}
/*
- compare two Booleans
-*/
+ * compare two Booleans.
+ *
+ * According to RFC4517 4.2.2, "the booleanMatch rule is an equality matching
+ * rule", meaning it isn't used for ordering.
+ *
+ * However, it seems conceivable that Samba could be coerced into sorting on a
+ * field with Boolean syntax, so we might as well have consistent behaviour in
+ * that case.
+ *
+ * The most probably values are {"FALSE", 5} and {"TRUE", 4}. To save time we
+ * compare first by length, which makes FALSE > TRUE. This is somewhat
+ * contrary to convention, but is how Samba has worked forever.
+ *
+ * If somehow we are comparing incompletely normalised values where the length
+ * is the same (for example {"false", 5} and {"TRUE\0", 5}), the length is the
+ * same, and we fall back to a strncasecmp. In this case, since "FALSE" is
+ * alphabetically lower, we swap the order, so that "TRUE\0" again comes
+ * before "FALSE".
+ *
+ * ldb_canonicalise_Boolean (just above) gives us a clue as to what we might
+ * expect to cope with by way of invalid values.
+ */
static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
if (v1->length != v2->length) {
- return v1->length - v2->length;
+ return NUMERIC_CMP(v2->length, v1->length);
}
- return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
+ /* reversed, see long comment above */
+ return strncasecmp((char *)v2->data, (char *)v1->data, v1->length);
}
@@ -300,7 +321,7 @@ int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
if (v1->length != v2->length) {
- return v1->length - v2->length;
+ return NUMERIC_CMP(v1->length, v2->length);
}
return memcmp(v1->data, v2->data, v1->length);
}
@@ -372,17 +393,27 @@ utf8str:
b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
if (!b1 || !b2) {
- /* One of the strings was not UTF8, so we have no
- * options but to do a binary compare */
+ /*
+ * One of the strings was not UTF8, so we have no
+ * options but to do a binary compare.
+ */
talloc_free(b1);
talloc_free(b2);
ret = memcmp(s1, s2, MIN(n1, n2));
if (ret == 0) {
- if (n1 == n2) return 0;
+ if (n1 == n2) {
+ return 0;
+ }
if (n1 > n2) {
- return (int)ldb_ascii_toupper(s1[n2]);
+ if (s1[n2] == '\0') {
+ return 0;
+ }
+ return 1;
} else {
- return -(int)ldb_ascii_toupper(s2[n1]);
+ if (s2[n1] == '\0') {
+ return 0;
+ }
+ return -1;
}
}
return ret;
@@ -404,7 +435,7 @@ utf8str:
while (*u1 == ' ') u1++;
while (*u2 == ' ') u2++;
}
- ret = (int)(*u1 - *u2);
+ ret = NUMERIC_CMP(*u1, *u2);
talloc_free(b1);
talloc_free(b2);
diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c
index 601da57..8388fdb 100644
--- a/lib/ldb/common/ldb_dn.c
+++ b/lib/ldb/common/ldb_dn.c
@@ -1111,7 +1111,7 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
/* compare attr.cf_value. */
if (b_vlen != dn_vlen) {
- return b_vlen - dn_vlen;
+ return NUMERIC_CMP(b_vlen, dn_vlen);
}
ret = strncmp(b_vdata, dn_vdata, b_vlen);
if (ret != 0) return ret;
@@ -1132,8 +1132,32 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
{
unsigned int i;
int ret;
+ /*
+ * If used in sort, we shift NULL and invalid DNs to the end.
+ *
+ * If ldb_dn_casefold_internal() fails, that goes to the end too, so
+ * we end up with:
+ *
+ * | normal DNs, sorted | casefold failed DNs | invalid DNs | NULLs |
+ */
- if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
+ if (dn0 == dn1) {
+ /* this includes the both-NULL case */
+ return 0;
+ }
+ if (dn0 == NULL) {
+ return 1;
+ }
+ if (dn1 == NULL) {
+ return -1;
+ }
+ if (dn0->invalid && dn1->invalid) {
+ return 0;
+ }
+ if (dn0->invalid) {
+ return 1;
+ }
+ if (dn1->invalid) {
return -1;
}
@@ -1190,7 +1214,7 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
/* compare attr.cf_value. */
if (dn0_vlen != dn1_vlen) {
- return dn0_vlen - dn1_vlen;
+ return NUMERIC_CMP(dn0_vlen, dn1_vlen);
}
ret = strncmp(dn0_vdata, dn1_vdata, dn0_vlen);
if (ret != 0) {
diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c
index afddbe4..c334d70 100644
--- a/lib/ldb/common/ldb_msg.c
+++ b/lib/ldb/common/ldb_msg.c
@@ -93,7 +93,7 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
{
if (v1->length != v2->length) {
- return v1->length - v2->length;
+ return NUMERIC_CMP(v1->length, v2->length);
}
return memcmp(v1->data, v2->data, v1->length);
}
@@ -749,9 +749,16 @@ int ldb_msg_element_compare(struct ldb_message_element *el1,
unsigned int i;
if (el1->num_values != el2->num_values) {
- return el1->num_values - el2->num_values;
+ return NUMERIC_CMP(el1->num_values, el2->num_values);
}
-
+ /*
+ * Note this is an inconsistent comparison, unsuitable for
+ * sorting. If A has values {a, b} and B has values {b, c},
+ * then
+ *
+ * ldb_msg_element_compare(A, B) returns -1, meaning A < B
+ * ldb_msg_element_compare(B, A) returns -1, meaning B < A
+ */
for (i=0;i<el1->num_values;i++) {
if (!ldb_msg_find_val(el2, &el1->values[i])) {
return -1;
diff --git a/lib/ldb/common/qsort.c b/lib/ldb/common/qsort.c
index 012aaf3..bae35e6 100644
--- a/lib/ldb/common/qsort.c
+++ b/lib/ldb/common/qsort.c
@@ -227,7 +227,7 @@ void ldb_qsort (void *const pbase, size_t total_elems, size_t size,
while ((run_ptr += size) <= end_ptr)
{
tmp_ptr = run_ptr - size;
- while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
+ while (tmp_ptr > base_ptr && (*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
tmp_ptr -= size;
tmp_ptr += size;
diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h
index 5d83a27..98859d4 100644
--- a/lib/ldb/include/ldb.h
+++ b/lib/ldb/include/ldb.h
@@ -2326,6 +2326,22 @@ do { \
} while (0)
#endif
+#ifndef NUMERIC_CMP
+/*
+ * NUMERIC_CMP is a safe replacement for `a - b` in comparison
+ * functions. It will work on integers, pointers, and floats.
+ *
+ * Rather than
+ *
+ * return a - b;
+ *
+ * use
+ *
+ * return NUMERIC_CMP(a, b);
+ */
+#define NUMERIC_CMP(a, b) (((a) > (b)) - ((a) < (b)))
+#endif
+
/**
diff --git a/lib/ldb/modules/sort.c b/lib/ldb/modules/sort.c
index cb6f8df..72c60fc 100644
--- a/lib/ldb/modules/sort.c
+++ b/lib/ldb/modules/sort.c
@@ -121,15 +121,28 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo
el1 = ldb_msg_find_element(*msg1, ac->attributeName);
el2 = ldb_msg_find_element(*msg2, ac->attributeName);
- if (!el1 && el2) {
+ /*
+ * NULL and empty elements sort at the end (regardless of ac->reverse flag).
+ * NULL elements come after empty ones.
+ */
+ if (el1 == el2) {
+ return 0;
+ }
+ if (el1 == NULL) {
return 1;
}
- if (el1 && !el2) {
+ if (el2 == NULL) {
return -1;
}
- if (!el1 && !el2) {
+ if (unlikely(el1->num_values == 0 && el2->num_values == 0)) {
return 0;
}
+ if (unlikely(el1->num_values == 0)) {
+ return 1;
+ }
+ if (unlikely(el2->num_values == 0)) {
+ return -1;
+ }
if (ac->reverse)
return ac->a->syntax->comparison_fn(ldb, ac, &el2->values[0], &el1->values[0]);
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index c249a82..936abe7 100644
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -2,7 +2,7 @@
APPNAME = 'ldb'
# For Samba 4.20.x !
-VERSION = '2.9.0'
+VERSION = '2.9.1'
import sys, os
diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c
index 4908b0f..2426ce2 100644
--- a/lib/socket/interfaces.c
+++ b/lib/socket/interfaces.c
@@ -386,18 +386,18 @@ static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
if (((struct sockaddr *)&i1->ip)->sa_family == AF_INET) {
struct sockaddr_in *s1 = (struct sockaddr_in *)&i1->ip;
struct sockaddr_in *s2 = (struct sockaddr_in *)&i2->ip;
-
- r = ntohl(s1->sin_addr.s_addr) -
- ntohl(s2->sin_addr.s_addr);
- if (r) {
- return r;
+ uint32_t a1 = ntohl(s1->sin_addr.s_addr);
+ uint32_t a2 = ntohl(s2->sin_addr.s_addr);
+ r = NUMERIC_CMP(a1, a2);
+ if (r == 0) {
+ /* compare netmasks as a tiebreaker */
+ s1 = (struct sockaddr_in *)&i1->netmask;
+ s2 = (struct sockaddr_in *)&i2->netmask;
+ a1 = ntohl(s1->sin_addr.s_addr);
+ a2 = ntohl(s2->sin_addr.s_addr);
+ r = NUMERIC_CMP(a1, a2);
}
-
- s1 = (struct sockaddr_in *)&i1->netmask;
- s2 = (struct sockaddr_in *)&i2->netmask;
-
- return ntohl(s1->sin_addr.s_addr) -
- ntohl(s2->sin_addr.s_addr);
+ return r;
}
return 0;
}
diff --git a/lib/torture/torture.h b/lib/torture/torture.h
index 2e86e31..2194703 100644
--- a/lib/torture/torture.h
+++ b/lib/torture/torture.h
@@ -534,6 +534,26 @@ static inline void torture_dump_data_str_cb(const char *buf, void *private_data)
} \
} while(0)
+#define torture_assert_int_less(torture_ctx,got,limit,cmt)\
+ do { int __got = (got), __limit = (limit); \
+ if (__got >= __limit) { \
+ torture_result(torture_ctx, TORTURE_FAIL, \
+ __location__": "#got" was %d (0x%X), expected < %d (0x%X): %s", \
+ __got, __got, __limit, __limit, cmt); \
+ return false; \
+ } \
+ } while(0)
+
+#define torture_assert_int_greater(torture_ctx,got,limit,cmt)\
+ do { int __got = (got), __limit = (limit); \
+ if (__got <= __limit) { \
+ torture_result(torture_ctx, TORTURE_FAIL, \
+ __location__": "#got" was %d (0x%X), expected > %d (0x%X): %s", \
+ __got, __got, __limit, __limit, cmt); \
+ return false; \
+ } \
+ } while(0)
+
#define torture_assert_int_equal_goto(torture_ctx,got,expected,ret,label,cmt)\
do { int __got = (got), __expected = (expected); \
if (__got != __expected) { \
diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c
index ea2c4be..8022627 100644
--- a/lib/util/charset/codepoints.c
+++ b/lib/util/charset/codepoints.c
@@ -26,6 +26,7 @@
#include "dynconfig/dynconfig.h"
#include "lib/util/debug.h"
#include "lib/util/byteorder.h"
+#include "lib/util/tsort.h"
#ifdef strcasecmp
#undef strcasecmp
@@ -16479,11 +16480,23 @@ _PUBLIC_ bool isupper_m(codepoint_t val)
*/
_PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
{
+ /*
+ * FIXME: this is unsuitable for use in a sort, as the
+ * comparison is intransitive.
+ *
+ * The problem is toupper_m() is only called on equality case,
+ * which has strange effects.
+ *
+ * Consider {'a', 'A', 'B'}.
+ * 'a' == 'A'
+ * 'a' > 'B' (lowercase letters come after upper)
+ * 'A' < 'B'
+ */
if (c1 == c2 ||
toupper_m(c1) == toupper_m(c2)) {
return 0;
}
- return c1 - c2;
+ return NUMERIC_CMP(c1, c2);
}
diff --git a/lib/util/charset/tests/charset.c b/lib/util/charset/tests/charset.c
index 547dc51..bca5449 100644
--- a/lib/util/charset/tests/charset.c
+++ b/lib/util/charset/tests/charset.c
@@ -72,16 +72,19 @@ static bool test_strcasecmp_m(struct torture_context *tctx)
const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 };
/* file.{accented e} in utf8 */
const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 };
- torture_assert_int_equal(tctx, strcasecmp_m("foo", "bar"), 4, "different strings both lower");
- torture_assert_int_equal(tctx, strcasecmp_m("foo", "Bar"), 4, "different strings lower/upper");
- torture_assert_int_equal(tctx, strcasecmp_m("Foo", "bar"), 4, "different strings upper/lower");
- torture_assert_int_equal(tctx, strcasecmp_m("AFoo", "_bar"), 2, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", "bar"), 0, "different strings both lower");
+ torture_assert_int_less(tctx, strcasecmp_m("bar", "foo"), 0, "different strings both lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", "Bar"), 0, "different strings lower/upper");
+ torture_assert_int_greater(tctx, strcasecmp_m("Foo", "bar"), 0, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("AFoo", "_bar"), 0, "different strings upper/lower");
torture_assert_int_equal(tctx, strcasecmp_m("foo", "foo"), 0, "same case strings");
torture_assert_int_equal(tctx, strcasecmp_m("foo", "Foo"), 0, "different case strings");
- torture_assert_int_equal(tctx, strcasecmp_m(NULL, "Foo"), -1, "one NULL");
- torture_assert_int_equal(tctx, strcasecmp_m("foo", NULL), 1, "other NULL");
+ torture_assert_int_greater(tctx, strcasecmp_m("food", "Foo"), 0, "strings differ towards the end");
+ torture_assert_int_less(tctx, strcasecmp_m("food", "Fool"), 0, "strings differ towards the end");
+ torture_assert_int_less(tctx, strcasecmp_m(NULL, "Foo"), 0, "one NULL");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", NULL), 0, "other NULL");
torture_assert_int_equal(tctx, strcasecmp_m(NULL, NULL), 0, "both NULL");
- torture_assert_int_equal(tctx, strcasecmp_m(file_iso8859_1, file_utf8), 38,
+ torture_assert_int_greater(tctx, strcasecmp_m(file_iso8859_1, file_utf8), 0,
"file.{accented e} should differ");
return true;
}
@@ -151,19 +154,19 @@ static bool test_strncasecmp_m(struct torture_context *tctx)
const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 };
/* file.{accented e} in utf8 */
const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 };
- torture_assert_int_equal(tctx, strncasecmp_m("foo", "bar", 3), 4, "different strings both lower");
- torture_assert_int_equal(tctx, strncasecmp_m("foo", "Bar", 3), 4, "different strings lower/upper");
- torture_assert_int_equal(tctx, strncasecmp_m("Foo", "bar", 3), 4, "different strings upper/lower");
- torture_assert_int_equal(tctx, strncasecmp_m("AFoo", "_bar", 4), 2, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", "bar", 3), 0, "different strings both lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", "Bar", 3), 0, "different strings lower/upper");
+ torture_assert_int_greater(tctx, strncasecmp_m("Foo", "bar", 3), 0, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("AFoo", "_bar", 4), 0, "different strings upper/lower");
torture_assert_int_equal(tctx, strncasecmp_m("foo", "foo", 3), 0, "same case strings");
torture_assert_int_equal(tctx, strncasecmp_m("foo", "Foo", 3), 0, "different case strings");
torture_assert_int_equal(tctx, strncasecmp_m("fool", "Foo", 3),0, "different case strings");
torture_assert_int_equal(tctx, strncasecmp_m("fool", "Fool", 40), 0, "over size");
torture_assert_int_equal(tctx, strncasecmp_m("BLA", "Fool", 0),0, "empty");
- torture_assert_int_equal(tctx, strncasecmp_m(NULL, "Foo", 3), -1, "one NULL");
- torture_assert_int_equal(tctx, strncasecmp_m("foo", NULL, 3), 1, "other NULL");
+ torture_assert_int_less(tctx, strncasecmp_m(NULL, "Foo", 3), 0, "one NULL");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", NULL, 3), 0, "other NULL");
torture_assert_int_equal(tctx, strncasecmp_m(NULL, NULL, 3), 0, "both NULL");
- torture_assert_int_equal(tctx, strncasecmp_m(file_iso8859_1, file_utf8, 6), 38,
+ torture_assert_int_greater(tctx, strncasecmp_m(file_iso8859_1, file_utf8, 6), 0,
"file.{accented e} should differ");
return true;
}
diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c
index 1650c9b..c52b773 100644
--- a/lib/util/charset/util_str.c
+++ b/lib/util/charset/util_str.c
@@ -26,6 +26,7 @@
#include "system/locale.h"
#include "charset.h"
#include "lib/util/fault.h"
+#include "lib/util/tsort.h"
#ifdef strcasecmp
#undef strcasecmp
@@ -79,10 +80,10 @@ _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
continue;
}
- return l1 - l2;
+ return NUMERIC_CMP(l1, l2);
}
- return *s1 - *s2;
+ return NUMERIC_CMP(*s1, *s2);
}
/**
@@ -156,14 +157,14 @@ _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
continue;
}
- return l1 - l2;
+ return NUMERIC_CMP(l1, l2);
}
if (n == 0) {
return 0;
}
- return *s1 - *s2;
+ return NUMERIC_CMP(*s1, *s2);
}
/**
diff --git a/lib/util/data_blob.c b/lib/util/data_blob.c
index 69a340c..1558200 100644
--- a/lib/util/data_blob.c
+++ b/lib/util/data_blob.c
@@ -22,6 +22,7 @@
#include "attr.h"
#include "data_blob.h"
#include "lib/util/samba_util.h"
+#include "lib/util/tsort.h"
const DATA_BLOB data_blob_null = { NULL, 0 };
@@ -121,12 +122,12 @@ _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
return 1;
}
if (d1->data == d2->data) {
- return d1->length - d2->length;
+ return NUMERIC_CMP(d1->length, d2->length);
}
ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
if (ret == 0) {
/* Note this ordering is used in conditional aces */
- return d1->length - d2->length;
+ return NUMERIC_CMP(d1->length, d2->length);
}
return ret;
}
diff --git a/lib/util/tests/binsearch.c b/lib/util/tests/binsearch.c
index b3ecda1..2484015 100644
--- a/lib/util/tests/binsearch.c
+++ b/lib/util/tests/binsearch.c
@@ -23,17 +23,19 @@
#include "includes.h"
#include "lib/util/binsearch.h"
+#include "lib/util/tsort.h"
#include "torture/torture.h"
#include "torture/local/proto.h"
static int int_cmp(int a, int b)
{
- return a - b;
+ return NUMERIC_CMP(a, b);
}
static int int_cmp_p(int a, int *b)
{
- return a - *b;
+ int _b = *b;
+ return NUMERIC_CMP(a, _b);
}
static bool test_binsearch_v(struct torture_context *tctx)
diff --git a/lib/util/tests/test_ms_fnmatch.c b/lib/util/tests/test_ms_fnmatch.c
index d11c7be..2261f9b 100644
--- a/lib/util/tests/test_ms_fnmatch.c
+++ b/lib/util/tests/test_ms_fnmatch.c
@@ -36,7 +36,7 @@ static void test_ms_fn_match_protocol_no_wildcard(void **state)
/* no wildcards in pattern, a simple strcasecmp_m */
cmp = ms_fnmatch_protocol("pattern", "string", PROTOCOL_COREPLUS,
true); /* case sensitive */
- assert_int_equal(cmp, -3);
+ assert_true(cmp < 0);
}
static void test_ms_fn_match_protocol_pattern_upgraded(void **state)
diff --git a/lib/util/tsort.h b/lib/util/tsort.h
index 811d6cd..18e82d6 100644
--- a/lib/util/tsort.h
+++ b/lib/util/tsort.h
@@ -37,4 +37,23 @@ do { \
} while (0)
#endif
+
+#ifndef NUMERIC_CMP
+/*
+ * NUMERIC_CMP is a safe replacement for `a - b` in comparison
+ * functions. It will work on integers, pointers, and floats.
+ *
+ * Rather than
+ *
+ * return a - b;
+ *
+ * use
+ *
+ * return NUMERIC_CMP(a, b);
+ *
+ * and you won't have any troubles if a - b would overflow.
+ */
+#define NUMERIC_CMP(a, b) (((a) > (b)) - ((a) < (b)))
+#endif
+
#endif
diff --git a/libcli/nbt/libnbt.h b/libcli/nbt/libnbt.h
index 204484b..6a30c9f 100644
--- a/libcli/nbt/libnbt.h
+++ b/libcli/nbt/libnbt.h
@@ -331,6 +331,9 @@ NTSTATUS nbt_set_unexpected_handler(struct nbt_name_socket *nbtsock,
void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
struct socket_address *),
void *private_data);
+NTSTATUS nbt_name_send_raw(struct nbt_name_socket *nbtsock,
+ struct socket_address *dest,
+ const DATA_BLOB pkt_blob);
NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
struct socket_address *dest,
struct nbt_name_packet *request);
diff --git a/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c
index 47e73cf..b2945ad 100644
--- a/libcli/nbt/nbtsocket.c
+++ b/libcli/nbt/nbtsocket.c
@@ -448,6 +448,50 @@ failed:
return NULL;
}
+/*
+ send off a nbt name packet
+*/
+_PUBLIC_ NTSTATUS nbt_name_send_raw(struct nbt_name_socket *nbtsock,
+ struct socket_address *dest,
+ const DATA_BLOB pkt_blob)
+{
+ struct nbt_name_request *req;
+
+ req = talloc_zero(nbtsock, struct nbt_name_request);
+ NT_STATUS_HAVE_NO_MEMORY(req);
+
+ req->nbtsock = nbtsock;
+ req->dest = socket_address_copy(req, dest);
+ if (req->dest == NULL) {
+ goto failed;
+ }
+ req->state = NBT_REQUEST_SEND;
+ /*
+ * We don't expect a response so
+ * just pretent it is a request,
+ * but we really don't care about the
+ * content.
+ */
+ req->is_reply = true;
+
+ req->encoded = data_blob_dup_talloc(req, pkt_blob);
+ if (req->encoded.length != pkt_blob.length) {
+ goto failed;
+ }
+
+ talloc_set_destructor(req, nbt_name_request_destructor);
+
+ DLIST_ADD_END(nbtsock->send_queue, req);
+
+ TEVENT_FD_WRITEABLE(nbtsock->fde);
+
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(req);
+ return NT_STATUS_NO_MEMORY;
+}
+
/*
send off a nbt name reply
diff --git a/libcli/security/dom_sid.c b/libcli/security/dom_sid.c
index eaece2a..21012b7 100644
--- a/libcli/security/dom_sid.c
+++ b/libcli/security/dom_sid.c
@@ -28,6 +28,7 @@
#include "librpc/gen_ndr/security.h"
#include "dom_sid.h"
#include "lib/util/smb_strtox.h"
+#include "lib/util/tsort.h"
/*****************************************************************
Compare the auth portion of two sids.
@@ -46,11 +47,12 @@ int dom_sid_compare_auth(const struct dom_sid *sid1,
return 1;
if (sid1->sid_rev_num != sid2->sid_rev_num)
- return sid1->sid_rev_num - sid2->sid_rev_num;
+ return NUMERIC_CMP(sid1->sid_rev_num, sid2->sid_rev_num);
for (i = 0; i < 6; i++)
- if (sid1->id_auth[i] != sid2->id_auth[i])
- return sid1->id_auth[i] - sid2->id_auth[i];
+ if (sid1->id_auth[i] != sid2->id_auth[i]) {
+ return NUMERIC_CMP(sid1->id_auth[i], sid2->id_auth[i]);
+ }
return 0;
}
@@ -71,9 +73,9 @@ int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2)
return 1;
/* Compare most likely different rids, first: i.e start at end */
- if (sid1->num_auths != sid2->num_auths)
- return sid1->num_auths - sid2->num_auths;
-
+ if (sid1->num_auths != sid2->num_auths) {
+ return NUMERIC_CMP(sid1->num_auths, sid2->num_auths);
+ }
for (i = sid1->num_auths-1; i >= 0; --i) {
if (sid1->sub_auths[i] < sid2->sub_auths[i]) {
return -1;
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index a52a615..87acddf 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -166,6 +166,13 @@ struct smb2cli_session {
uint16_t channel_sequence;
bool replay_active;
bool require_signed_response;
+
+ /*
+ * The following are just for torture tests
+ */
+ bool anonymous_signing;
+ bool anonymous_encryption;
+ bool no_signing_disconnect;
};
struct smbXcli_session {
@@ -3999,6 +4006,9 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) ||
NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) ||
+ (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
+ session != NULL &&
+ session->smb2->no_signing_disconnect) ||
NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
/*
* if the server returns
@@ -4042,8 +4052,29 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn,
/*
* If the signing check fails, we disconnect
* the connection.
+ *
+ * Unless
+ * smb2cli_session_torture_no_signing_disconnect
+ * was called in torture tests
*/
- return signing_status;
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ return signing_status;
+ }
+
+ if (!NT_STATUS_EQUAL(status, signing_status)) {
+ return signing_status;
+ }
+
+ if (session == NULL) {
+ return signing_status;
+ }
+
+ if (!session->smb2->no_signing_disconnect) {
+ return signing_status;
+ }
+
+ state->smb2.signing_skipped = true;
}
}
@@ -6332,6 +6363,23 @@ void smb2cli_session_require_signed_response(struct smbXcli_session *session,
session->smb2->require_signed_response = require_signed_response;
}
+void smb2cli_session_torture_anonymous_signing(struct smbXcli_session *session,
+ bool anonymous_signing)
+{
+ session->smb2->anonymous_signing = anonymous_signing;
+}
+
+void smb2cli_session_torture_anonymous_encryption(struct smbXcli_session *session,
+ bool anonymous_encryption)
+{
+ session->smb2->anonymous_encryption = anonymous_encryption;
+}
+
+void smb2cli_session_torture_no_signing_disconnect(struct smbXcli_session *session)
+{
+ session->smb2->no_signing_disconnect = true;
+}
+
NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
const struct iovec *iov)
{
@@ -6432,6 +6480,10 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
conn->protocol,
preauth_hash);
+ if (session->smb2->anonymous_encryption) {
+ goto skip_signing_key;
+ }
+
status = smb2_signing_key_sign_create(session->smb2,
conn->smb2.server.sign_algo,
&_session_key,
@@ -6441,6 +6493,15 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
return status;
}
+ if (session->smb2->anonymous_signing) {
+ /*
+ * skip encryption and application keys
+ */
+ goto skip_application_key;
+ }
+
+skip_signing_key:
+
status = smb2_signing_key_cipher_create(session->smb2,
conn->smb2.server.cipher,
&_session_key,
@@ -6459,6 +6520,10 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
return status;
}
+ if (session->smb2->anonymous_encryption) {
+ goto skip_application_key;
+ }
+
status = smb2_signing_key_sign_create(session->smb2,
conn->smb2.server.sign_algo,
&_session_key,
@@ -6468,6 +6533,8 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
return status;
}
+skip_application_key:
+
status = smb2_signing_key_copy(session,
session->smb2->signing_key,
&session->smb2_channel.signing_key);
@@ -6477,6 +6544,18 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
check_signature = conn->mandatory_signing;
+ if (conn->protocol >= PROTOCOL_SMB3_11) {
+ check_signature = true;
+ }
+
+ if (session->smb2->anonymous_signing) {
+ check_signature = false;
+ }
+
+ if (session->smb2->anonymous_encryption) {
+ check_signature = false;
+ }
+
hdr_flags = IVAL(recv_iov[0].iov_base, SMB2_HDR_FLAGS);
if (hdr_flags & SMB2_HDR_FLAG_SIGNED) {
/*
@@ -6492,10 +6571,6 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
check_signature = true;
}
- if (conn->protocol >= PROTOCOL_SMB3_11) {
- check_signature = true;
- }
-
if (check_signature) {
status = smb2_signing_check_pdu(session->smb2_channel.signing_key,
recv_iov, 3);
@@ -6527,6 +6602,15 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
session->smb2->should_encrypt = false;
}
+ if (session->smb2->anonymous_signing) {
+ session->smb2->should_sign = true;
+ }
+
+ if (session->smb2->anonymous_encryption) {
+ session->smb2->should_encrypt = true;
+ session->smb2->should_sign = false;
+ }
+
/*
* CCM and GCM algorithms must never have their
* nonce wrap, or the security of the whole
@@ -6698,6 +6782,16 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session)
{
+ if (session->smb2->anonymous_signing) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
+ if (session->smb2->anonymous_encryption) {
+ SMB_ASSERT(session->smb2->should_encrypt);
+ SMB_ASSERT(!session->smb2->should_sign);
+ return NT_STATUS_OK;
+ }
+
if (!session->smb2->should_sign) {
/*
* We need required signing on the session
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index 25ccd84..69fa131 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -535,6 +535,11 @@ void smb2cli_session_start_replay(struct smbXcli_session *session);
void smb2cli_session_stop_replay(struct smbXcli_session *session);
void smb2cli_session_require_signed_response(struct smbXcli_session *session,
bool require_signed_response);
+void smb2cli_session_torture_anonymous_signing(struct smbXcli_session *session,
+ bool anonymous_signing);
+void smb2cli_session_torture_anonymous_encryption(struct smbXcli_session *session,
+ bool anonymous_encryption);
+void smb2cli_session_torture_no_signing_disconnect(struct smbXcli_session *session);
NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session,
const struct iovec *iov);
NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session,
diff --git a/pidl/lib/Parse/Pidl/Typelist.pm b/pidl/lib/Parse/Pidl/Typelist.pm
index 31ea19e..2a98a16 100644
--- a/pidl/lib/Parse/Pidl/Typelist.pm
+++ b/pidl/lib/Parse/Pidl/Typelist.pm
@@ -138,8 +138,18 @@ sub resolveType($)
my ($ctype) = @_;
if (not hasType($ctype)) {
- # assume struct typedef
- return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } };
+ if (! ref $ctype) {
+ # it looks like a name.
+ # assume struct typedef
+ return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } };
+ }
+ if ($ctype->{NAME} && ($ctype->{TYPE} eq "STRUCT")) {
+ return {
+ TYPE => "TYPEDEF",
+ NAME => $ctype->{NAME},
+ DATA => $ctype
+ };
+ }
} else {
return getType($ctype);
}
diff --git a/python/samba/gp/gpclass.py b/python/samba/gp/gpclass.py
index 08be472..d86aace 100644
--- a/python/samba/gp/gpclass.py
+++ b/python/samba/gp/gpclass.py
@@ -805,9 +805,7 @@ def site_dn_for_machine(samdb, dc_hostname, lp, creds, hostname):
samlogon_response = ndr_unpack(nbt.netlogon_samlogon_response,
bytes(res.msgs[0]['Netlogon'][0]))
- if samlogon_response.ntver not in [nbt.NETLOGON_NT_VERSION_5EX,
- (nbt.NETLOGON_NT_VERSION_1
- | nbt.NETLOGON_NT_VERSION_5EX)]:
+ if not (samlogon_response.ntver & nbt.NETLOGON_NT_VERSION_5EX):
raise RuntimeError('site_dn_for_machine: Invalid NtVer in '
+ 'netlogon_samlogon_response')
diff --git a/python/samba/tests/blackbox/misc_dfs_widelink.py b/python/samba/tests/blackbox/misc_dfs_widelink.py
new file mode 100644
index 0000000..7948590
--- /dev/null
+++ b/python/samba/tests/blackbox/misc_dfs_widelink.py
@@ -0,0 +1,86 @@
+# Blackbox tests for DFS (widelink)
+#
+# Copyright (C) Noel Power noel.power@suse.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+from samba.tests import BlackboxTestCase, BlackboxProcessError
+from samba.samba3 import param as s3param
+
+from samba.credentials import Credentials
+
+import os
+
+class DfsWidelinkBlockboxTestBase(BlackboxTestCase):
+
+ def setUp(self):
+ super().setUp()
+ self.lp = s3param.get_context()
+ self.server = os.environ["SERVER"]
+ self.user = os.environ["USER"]
+ self.passwd = os.environ["PASSWORD"]
+ self.creds = Credentials()
+ self.creds.guess(self.lp)
+ self.creds.set_username(self.user)
+ self.creds.set_password(self.passwd)
+ self.testdir = os.getenv("TESTDIR", "msdfs-share-wl")
+ self.share = os.getenv("SHARE", "msdfs-share-wl")
+ self.dirpath = os.path.join(os.environ["LOCAL_PATH"],self.testdir)
+ # allow a custom teardown function to be defined
+ self.cleanup = None
+ self.cleanup_args = []
+
+ def tearDown(self):
+ try:
+ if (self.cleanup):
+ self.cleanup(self.cleanup_args)
+ except Exception as e:
+ print("remote remove failed: %s" % str(e))
+
+ def build_test_cmd(self, cmd, args):
+ cmd = [cmd, "-U%s%%%s" % (self.user, self.passwd)]
+ cmd.extend(args)
+ return cmd
+
+ def test_ci_chdir(self):
+ parent_dir = "msdfs-src1"
+ dirs = [parent_dir, parent_dir.upper()]
+ # try as named dir first then try upper-cased version
+ for adir in dirs:
+ smbclient_args = self.build_test_cmd("smbclient", ["//%s/%s" % (self.server, self.share), "-c", "cd %s" % (adir)])
+ try:
+ out_str = self.check_output(smbclient_args)
+ except BlackboxProcessError as e:
+ print(str(e))
+ self.fail(str(e))
+
+ def test_nested_chdir(self):
+ parent_dir = "dfshop1"
+ child_dir = "dfshop2"
+ smbclient_args = self.build_test_cmd("smbclient", ["//%s/%s" % (self.server, self.share), "-c", "cd %s/%s" % (parent_dir,child_dir)])
+ try:
+ out_str = self.check_output(smbclient_args)
+ except BlackboxProcessError as e:
+ print(str(e))
+ self.fail(str(e))
+
+ def test_enumerate_dfs_link(self):
+ smbclient_args = self.build_test_cmd("smbclient", ["//%s/%s" % (self.server, self.share), "-c", "dir"])
+ try:
+ out_str = self.check_output(smbclient_args)
+ except BlackboxProcessError as e:
+ print(str(e))
+ self.fail(str(e))
+ out_str = out_str.decode()
+ self.assertIn("msdfs-src1", out_str)
diff --git a/python/samba/tests/dns_base.py b/python/samba/tests/dns_base.py
index d320a0e..43a62b1 100644
--- a/python/samba/tests/dns_base.py
+++ b/python/samba/tests/dns_base.py
@@ -20,6 +20,7 @@ from samba.tests import TestCaseInTempDir
from samba.dcerpc import dns, dnsp
from samba import gensec, tests
from samba import credentials
+from samba import NTSTATUSError
import struct
import samba.ndr as ndr
import random
@@ -76,6 +77,24 @@ class DNSTest(TestCaseInTempDir):
self.assertEqual(p_opcode, opcode, "Expected OPCODE %s, got %s" %
(opcode, p_opcode))
+ def assert_dns_flags_equals(self, packet, flags):
+ "Helper function to check opcode"
+ p_flags = packet.operation & (~(dns.DNS_OPCODE|dns.DNS_RCODE))
+ self.assertEqual(p_flags, flags, "Expected FLAGS %02x, got %02x" %
+ (flags, p_flags))
+
+ def assert_echoed_dns_error(self, request, response, response_p, rcode):
+
+ request_p = ndr.ndr_pack(request)
+
+ self.assertEqual(response.id, request.id)
+ self.assert_dns_rcode_equals(response, rcode)
+ self.assert_dns_opcode_equals(response, request.operation & dns.DNS_OPCODE)
+ self.assert_dns_flags_equals(response,
+ (request.operation | dns.DNS_FLAG_REPLY) & (~(dns.DNS_OPCODE|dns.DNS_RCODE)))
+ self.assertEqual(len(response_p), len(request_p))
+ self.assertEqual(response_p[4:], request_p[4:])
+
def make_name_packet(self, opcode, qid=None):
"Helper creating a dns.name_packet"
p = dns.name_packet()
@@ -112,6 +131,8 @@ class DNSTest(TestCaseInTempDir):
return self.creds.get_realm().lower()
def dns_transaction_udp(self, packet, host,
+ allow_remaining=False,
+ allow_truncated=False,
dump=False, timeout=None):
"send a DNS query and read the reply"
s = None
@@ -128,8 +149,22 @@ class DNSTest(TestCaseInTempDir):
recv_packet = s.recv(2048, 0)
if dump:
print(self.hexdump(recv_packet))
- response = ndr.ndr_unpack(dns.name_packet, recv_packet)
+ if allow_truncated:
+ # with allow_remaining
+ # we add some zero bytes
+ # in order to also parse truncated
+ # responses
+ recv_packet_p = recv_packet + 32*b"\x00"
+ allow_remaining = True
+ else:
+ recv_packet_p = recv_packet
+ response = ndr.ndr_unpack(dns.name_packet, recv_packet_p,
+ allow_remaining=allow_remaining)
return (response, recv_packet)
+ except RuntimeError as re:
+ if s is not None:
+ s.close()
+ raise AssertionError(re)
finally:
if s is not None:
s.close()
@@ -151,11 +186,26 @@ class DNSTest(TestCaseInTempDir):
tcp_packet += send_packet
s.sendall(tcp_packet)
- recv_packet = s.recv(0xffff + 2, 0)
+ recv_packet = b''
+ length = None
+ for i in range(0, 2 + 0xffff):
+ if len(recv_packet) >= 2:
+ length, = struct.unpack('!H', recv_packet[0:2])
+ remaining = 2 + length
+ else:
+ remaining = 2 + 12
+ remaining -= len(recv_packet)
+ if remaining == 0:
+ break
+ recv_packet += s.recv(remaining, 0)
if dump:
print(self.hexdump(recv_packet))
response = ndr.ndr_unpack(dns.name_packet, recv_packet[2:])
+ except RuntimeError as re:
+ if s is not None:
+ s.close()
+ raise AssertionError(re)
finally:
if s is not None:
s.close()
@@ -217,18 +267,41 @@ class DNSTKeyTest(DNSTest):
self.creds.set_username(tests.env_get_var_value('USERNAME'))
self.creds.set_password(tests.env_get_var_value('PASSWORD'))
self.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS)
+
+ self.unpriv_creds = None
+
self.newrecname = "tkeytsig.%s" % self.get_dns_domain()
- def tkey_trans(self, creds=None):
+ def get_unpriv_creds(self):
+ if self.unpriv_creds is not None:
+ return self.unpriv_creds
+
+ self.unpriv_creds = credentials.Credentials()
+ self.unpriv_creds.guess(self.lp_ctx)
+ self.unpriv_creds.set_username(tests.env_get_var_value('USERNAME_UNPRIV'))
+ self.unpriv_creds.set_password(tests.env_get_var_value('PASSWORD_UNPRIV'))
+ self.unpriv_creds.set_kerberos_state(credentials.MUST_USE_KERBEROS)
+
+ return self.unpriv_creds
+
+ def tkey_trans(self, creds=None, algorithm_name="gss-tsig",
+ tkey_req_in_answers=False,
+ expected_rcode=dns.DNS_RCODE_OK):
"Do a TKEY transaction and establish a gensec context"
if creds is None:
creds = self.creds
- self.key_name = "%s.%s" % (uuid.uuid4(), self.get_dns_domain())
+ mech = 'spnego'
+
+ tkey = {}
+ tkey['name'] = "%s.%s" % (uuid.uuid4(), self.get_dns_domain())
+ tkey['creds'] = creds
+ tkey['mech'] = mech
+ tkey['algorithm'] = algorithm_name
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
- q = self.make_name_question(self.key_name,
+ q = self.make_name_question(tkey['name'],
dns.DNS_QTYPE_TKEY,
dns.DNS_QCLASS_IN)
questions = []
@@ -236,30 +309,30 @@ class DNSTKeyTest(DNSTest):
self.finish_name_packet(p, questions)
r = dns.res_rec()
- r.name = self.key_name
+ r.name = tkey['name']
r.rr_type = dns.DNS_QTYPE_TKEY
r.rr_class = dns.DNS_QCLASS_IN
r.ttl = 0
r.length = 0xffff
rdata = dns.tkey_record()
- rdata.algorithm = "gss-tsig"
+ rdata.algorithm = algorithm_name
rdata.inception = int(time.time())
rdata.expiration = int(time.time()) + 60 * 60
rdata.mode = dns.DNS_TKEY_MODE_GSSAPI
rdata.error = 0
rdata.other_size = 0
- self.g = gensec.Security.start_client(self.settings)
- self.g.set_credentials(creds)
- self.g.set_target_service("dns")
- self.g.set_target_hostname(self.server)
- self.g.want_feature(gensec.FEATURE_SIGN)
- self.g.start_mech_by_name("spnego")
+ tkey['gensec'] = gensec.Security.start_client(self.settings)
+ tkey['gensec'].set_credentials(creds)
+ tkey['gensec'].set_target_service("dns")
+ tkey['gensec'].set_target_hostname(self.server)
+ tkey['gensec'].want_feature(gensec.FEATURE_SIGN)
+ tkey['gensec'].start_mech_by_name(tkey['mech'])
finished = False
client_to_server = b""
- (finished, server_to_client) = self.g.update(client_to_server)
+ (finished, server_to_client) = tkey['gensec'].update(client_to_server)
self.assertFalse(finished)
data = [x if isinstance(x, int) else ord(x) for x in list(server_to_client)]
@@ -268,56 +341,76 @@ class DNSTKeyTest(DNSTest):
r.rdata = rdata
additional = [r]
- p.arcount = 1
- p.additional = additional
+ if tkey_req_in_answers:
+ p.ancount = 1
+ p.answers = additional
+ else:
+ p.arcount = 1
+ p.additional = additional
(response, response_packet) =\
self.dns_transaction_tcp(p, self.server_ip)
+ if expected_rcode != dns.DNS_RCODE_OK:
+ self.assert_echoed_dns_error(p, response, response_packet, expected_rcode)
+ return
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
tkey_record = response.answers[0].rdata
server_to_client = bytes(tkey_record.key_data)
- (finished, client_to_server) = self.g.update(server_to_client)
+ (finished, client_to_server) = tkey['gensec'].update(server_to_client)
self.assertTrue(finished)
+ self.tkey = tkey
+
self.verify_packet(response, response_packet)
def verify_packet(self, response, response_packet, request_mac=b""):
+ self.assertEqual(response.arcount, 1)
self.assertEqual(response.additional[0].rr_type, dns.DNS_QTYPE_TSIG)
+ if self.tkey['algorithm'] == "gss-tsig":
+ gss_tsig = True
+ else:
+ gss_tsig = False
+
+ request_mac_len = b""
+ if len(request_mac) > 0 and gss_tsig:
+ request_mac_len = struct.pack('!H', len(request_mac))
+
tsig_record = response.additional[0].rdata
mac = bytes(tsig_record.mac)
+ self.assertEqual(tsig_record.original_id, response.id)
+ self.assertEqual(tsig_record.mac_size, len(mac))
+
# Cut off tsig record from dns response packet for MAC verification
# and reset additional record count.
- key_name_len = len(self.key_name) + 2
- tsig_record_len = len(ndr.ndr_pack(tsig_record)) + key_name_len + 10
-
- # convert str/bytes to a list (of string char or int)
- # so it can be modified
- response_packet_list = [x if isinstance(x, int) else ord(x) for x in response_packet]
- del response_packet_list[-tsig_record_len:]
- response_packet_list[11] = 0
-
- # convert modified list (of string char or int) to str/bytes
- response_packet_wo_tsig = bytes(response_packet_list)
+ response_copy = ndr.ndr_deepcopy(response)
+ response_copy.arcount = 0
+ response_packet_wo_tsig = ndr.ndr_pack(response_copy)
fake_tsig = dns.fake_tsig_rec()
- fake_tsig.name = self.key_name
+ fake_tsig.name = self.tkey['name']
fake_tsig.rr_class = dns.DNS_QCLASS_ANY
fake_tsig.ttl = 0
fake_tsig.time_prefix = tsig_record.time_prefix
fake_tsig.time = tsig_record.time
fake_tsig.algorithm_name = tsig_record.algorithm_name
fake_tsig.fudge = tsig_record.fudge
- fake_tsig.error = 0
- fake_tsig.other_size = 0
+ fake_tsig.error = tsig_record.error
+ fake_tsig.other_size = tsig_record.other_size
+ fake_tsig.other_data = tsig_record.other_data
fake_tsig_packet = ndr.ndr_pack(fake_tsig)
- data = request_mac + response_packet_wo_tsig + fake_tsig_packet
- self.g.check_packet(data, data, mac)
+ data = request_mac_len + request_mac + response_packet_wo_tsig + fake_tsig_packet
+ try:
+ self.tkey['gensec'].check_packet(data, data, mac)
+ except NTSTATUSError as nt:
+ raise AssertionError(nt)
- def sign_packet(self, packet, key_name):
+ def sign_packet(self, packet, key_name,
+ algorithm_name="gss-tsig",
+ bad_sig=False):
"Sign a packet, calculate a MAC and add TSIG record"
packet_data = ndr.ndr_pack(packet)
@@ -327,18 +420,35 @@ class DNSTKeyTest(DNSTest):
fake_tsig.ttl = 0
fake_tsig.time_prefix = 0
fake_tsig.time = int(time.time())
- fake_tsig.algorithm_name = "gss-tsig"
+ fake_tsig.algorithm_name = algorithm_name
fake_tsig.fudge = 300
fake_tsig.error = 0
fake_tsig.other_size = 0
fake_tsig_packet = ndr.ndr_pack(fake_tsig)
data = packet_data + fake_tsig_packet
- mac = self.g.sign_packet(data, data)
+ mac = self.tkey['gensec'].sign_packet(data, data)
mac_list = [x if isinstance(x, int) else ord(x) for x in list(mac)]
+ if bad_sig:
+ if len(mac) > 8:
+ mac_list[-8] = mac_list[-8] ^ 0xff
+ if len(mac) > 7:
+ mac_list[-7] = ord('b')
+ if len(mac) > 6:
+ mac_list[-6] = ord('a')
+ if len(mac) > 5:
+ mac_list[-5] = ord('d')
+ if len(mac) > 4:
+ mac_list[-4] = ord('m')
+ if len(mac) > 3:
+ mac_list[-3] = ord('a')
+ if len(mac) > 2:
+ mac_list[-2] = ord('c')
+ if len(mac) > 1:
+ mac_list[-1] = mac_list[-1] ^ 0xff
rdata = dns.tsig_record()
- rdata.algorithm_name = "gss-tsig"
+ rdata.algorithm_name = algorithm_name
rdata.time_prefix = 0
rdata.time = fake_tsig.time
rdata.fudge = 300
@@ -363,33 +473,10 @@ class DNSTKeyTest(DNSTest):
return mac
def bad_sign_packet(self, packet, key_name):
- """Add bad signature for a packet by bitflipping
- the final byte in the MAC"""
-
- mac_list = [x if isinstance(x, int) else ord(x) for x in list("badmac")]
-
- rdata = dns.tsig_record()
- rdata.algorithm_name = "gss-tsig"
- rdata.time_prefix = 0
- rdata.time = int(time.time())
- rdata.fudge = 300
- rdata.original_id = packet.id
- rdata.error = 0
- rdata.other_size = 0
- rdata.mac = mac_list
- rdata.mac_size = len(mac_list)
+ """Add bad signature for a packet by
+ bitflipping and hardcoding bytes at the end of the MAC"""
- r = dns.res_rec()
- r.name = key_name
- r.rr_type = dns.DNS_QTYPE_TSIG
- r.rr_class = dns.DNS_QCLASS_ANY
- r.ttl = 0
- r.length = 0xffff
- r.rdata = rdata
-
- additional = [r]
- packet.additional = additional
- packet.arcount = 1
+ return self.sign_packet(packet, key_name, bad_sig=True)
def search_record(self, name):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
diff --git a/python/samba/tests/dns_tkey.py b/python/samba/tests/dns_tkey.py
index 69af14d..f8417ea 100644
--- a/python/samba/tests/dns_tkey.py
+++ b/python/samba/tests/dns_tkey.py
@@ -19,6 +19,7 @@
import sys
import optparse
import samba.getopt as options
+import samba.ndr as ndr
from samba.dcerpc import dns
from samba.tests.subunitrun import SubunitOptions, TestProgram
from samba.tests.dns_base import DNSTKeyTest
@@ -55,17 +56,34 @@ class TestDNSUpdates(DNSTKeyTest):
self.server_ip = server_ip
super().setUp()
- def test_tkey(self):
- "test DNS TKEY handshake"
+ def test_tkey_gss_tsig(self):
+ "test DNS TKEY handshake with gss-tsig"
self.tkey_trans()
+ def test_tkey_gss_microsoft_com(self):
+ "test DNS TKEY handshake with gss.microsoft.com"
+
+ self.tkey_trans(algorithm_name="gss.microsoft.com")
+
+ def test_tkey_invalid_gss_TSIG(self):
+ "test DNS TKEY handshake with invalid gss-TSIG"
+
+ self.tkey_trans(algorithm_name="gss-TSIG",
+ expected_rcode=dns.DNS_RCODE_REFUSED)
+
+ def test_tkey_invalid_gss_MICROSOFT_com(self):
+ "test DNS TKEY handshake with invalid gss.MICROSOFT.com"
+
+ self.tkey_trans(algorithm_name="gss.MICROSOFT.com",
+ expected_rcode=dns.DNS_RCODE_REFUSED)
+
def test_update_wo_tsig(self):
"test DNS update without TSIG record"
p = self.make_update_request()
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_REFUSED)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
rcode = self.search_record(self.newrecname)
self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
@@ -78,10 +96,7 @@ class TestDNSUpdates(DNSTKeyTest):
p = self.make_update_request()
self.sign_packet(p, "badkey")
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH)
- tsig_record = response.additional[0].rdata
- self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADKEY)
- self.assertEqual(tsig_record.mac_size, 0)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
rcode = self.search_record(self.newrecname)
self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
@@ -92,23 +107,149 @@ class TestDNSUpdates(DNSTKeyTest):
self.tkey_trans()
p = self.make_update_request()
- self.bad_sign_packet(p, self.key_name)
+ self.bad_sign_packet(p, self.tkey['name'])
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH)
- tsig_record = response.additional[0].rdata
- self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADSIG)
- self.assertEqual(tsig_record.mac_size, 0)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
rcode = self.search_record(self.newrecname)
self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
- def test_update_tsig(self):
- "test DNS update with correct TSIG record"
+ def test_update_tsig_bad_algorithm(self):
+ "test DNS update with a TSIG record with a bad algorithm"
self.tkey_trans()
+ algorithm_name = "gss-TSIG"
p = self.make_update_request()
- mac = self.sign_packet(p, self.key_name)
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
+
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_tsig_changed_algorithm1(self):
+ "test DNS update with a TSIG record with a changed algorithm"
+
+ algorithm_name = "gss-tsig"
+ self.tkey_trans(algorithm_name=algorithm_name)
+
+ # Now delete the record, it's most likely
+ # a no-op as it should not be there if the test
+ # runs the first time
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Now do an update with the algorithm_name
+ # changed in the requests TSIG message.
+ p = self.make_update_request()
+ algorithm_name = "gss.microsoft.com"
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ algorithm_name = "gss-tsig"
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip,
+ allow_remaining=True)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record, with the original
+ # algorithm_name used in the tkey exchange
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_tsig_changed_algorithm2(self):
+ "test DNS update with a TSIG record with a changed algorithm"
+
+ algorithm_name = "gss.microsoft.com"
+ self.tkey_trans(algorithm_name=algorithm_name)
+
+ # Now delete the record, it's most likely
+ # a no-op as it should not be there if the test
+ # runs the first time
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Now do an update with the algorithm_name
+ # changed in the requests TSIG message.
+ p = self.make_update_request()
+ algorithm_name = "gss-tsig"
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ algorithm_name = "gss.microsoft.com"
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip,
+ allow_truncated=True)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ response_p_pack = ndr.ndr_pack(response)
+ if len(response_p_pack) == len(response_p):
+ self.verify_packet(response, response_p, mac)
+ else:
+ pass # Windows bug
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record, with the original
+ # algorithm_name used in the tkey exchange
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_gss_tsig_tkey_req_additional(self):
+ "test DNS update with correct gss-tsig record tkey req in additional"
+
+ self.tkey_trans()
+
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # check it's gone
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_gss_tsig_tkey_req_answers(self):
+ "test DNS update with correct gss-tsig record tsig req in answers"
+
+ self.tkey_trans(tkey_req_in_answers=True)
+
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'])
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
self.verify_packet(response, response_p, mac)
@@ -119,7 +260,66 @@ class TestDNSUpdates(DNSTKeyTest):
# Now delete the record
p = self.make_update_request(delete=True)
- mac = self.sign_packet(p, self.key_name)
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # check it's gone
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_gss_microsoft_com_tkey_req_additional(self):
+ "test DNS update with correct gss.microsoft.com record tsig req in additional"
+
+ algorithm_name = "gss.microsoft.com"
+ self.tkey_trans(algorithm_name=algorithm_name)
+
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # check it's gone
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_gss_microsoft_com_tkey_req_answers(self):
+ "test DNS update with correct gss.microsoft.com record tsig req in answers"
+
+ algorithm_name = "gss.microsoft.com"
+ self.tkey_trans(algorithm_name=algorithm_name,
+ tkey_req_in_answers=True)
+
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'],
+ algorithm_name=algorithm_name)
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
self.verify_packet(response, response_p, mac)
@@ -131,35 +331,28 @@ class TestDNSUpdates(DNSTKeyTest):
def test_update_tsig_windows(self):
"test DNS update with correct TSIG record (follow Windows pattern)"
- newrecname = "win" + self.newrecname
+ p = self.make_update_request()
+
rr_class = dns.DNS_QCLASS_IN
ttl = 1200
- p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
- q = self.make_name_question(self.get_dns_domain(),
- dns.DNS_QTYPE_SOA,
- dns.DNS_QCLASS_IN)
- questions = []
- questions.append(q)
- self.finish_name_packet(p, questions)
-
updates = []
r = dns.res_rec()
- r.name = newrecname
+ r.name = self.newrecname
r.rr_type = dns.DNS_QTYPE_A
r.rr_class = dns.DNS_QCLASS_ANY
r.ttl = 0
r.length = 0
updates.append(r)
r = dns.res_rec()
- r.name = newrecname
+ r.name = self.newrecname
r.rr_type = dns.DNS_QTYPE_AAAA
r.rr_class = dns.DNS_QCLASS_ANY
r.ttl = 0
r.length = 0
updates.append(r)
r = dns.res_rec()
- r.name = newrecname
+ r.name = self.newrecname
r.rr_type = dns.DNS_QTYPE_A
r.rr_class = rr_class
r.ttl = ttl
@@ -171,7 +364,7 @@ class TestDNSUpdates(DNSTKeyTest):
prereqs = []
r = dns.res_rec()
- r.name = newrecname
+ r.name = self.newrecname
r.rr_type = dns.DNS_QTYPE_CNAME
r.rr_class = dns.DNS_QCLASS_NONE
r.ttl = 0
@@ -181,21 +374,87 @@ class TestDNSUpdates(DNSTKeyTest):
p.answers = prereqs
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_REFUSED)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
self.tkey_trans()
- mac = self.sign_packet(p, self.key_name)
+ mac = self.sign_packet(p, self.tkey['name'])
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
self.verify_packet(response, response_p, mac)
# Check the record is around
- rcode = self.search_record(newrecname)
+ rcode = self.search_record(self.newrecname)
self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
# Now delete the record
+ delete_updates = []
+ r = dns.res_rec()
+ r.name = self.newrecname
+ r.rr_type = dns.DNS_QTYPE_A
+ r.rr_class = dns.DNS_QCLASS_NONE
+ r.ttl = 0
+ r.length = 0xffff
+ r.rdata = "10.1.45.64"
+ delete_updates.append(r)
+ p = self.make_update_request(delete=True)
+ p.nscount = len(delete_updates)
+ p.nsrecs = delete_updates
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # check it's gone
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+ def test_update_tsig_record_access_denied(self):
+ """test DNS update with a TSIG record where the user does not have
+ permissions to change the record"""
+
+ self.tkey_trans()
+ adm_tkey = self.tkey
+
+ # First create the record as admin
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now update the same values as normal user
+ # should work without error
+ self.tkey_trans(creds=self.get_unpriv_creds())
+ unpriv_tkey = self.tkey
+
+ p = self.make_update_request()
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.verify_packet(response, response_p, mac)
+
+ # Check the record is still around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now try to delete the record a normal user (should fail)
+ p = self.make_update_request(delete=True)
+ mac = self.sign_packet(p, self.tkey['name'])
+ (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+ self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
+
+ # Check the record is still around
+ rcode = self.search_record(self.newrecname)
+ self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+ # Now delete the record as admin
+ self.tkey = adm_tkey
p = self.make_update_request(delete=True)
- mac = self.sign_packet(p, self.key_name)
+ mac = self.sign_packet(p, self.tkey['name'])
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
self.verify_packet(response, response_p, mac)
diff --git a/python/samba/tests/join.py b/python/samba/tests/join.py
index b47bc70..b04cb4a 100644
--- a/python/samba/tests/join.py
+++ b/python/samba/tests/join.py
@@ -156,7 +156,7 @@ class JoinTestCase(DNSTKeyTest):
p.nscount = len(updates)
p.nsrecs = updates
- mac = self.sign_packet(p, self.key_name)
+ mac = self.sign_packet(p, self.tkey['name'])
(response, response_p) = self.dns_transaction_udp(p, self.server_ip)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
self.verify_packet(response, response_p, mac)
diff --git a/python/samba/tests/ntacls.py b/python/samba/tests/ntacls.py
index 0b7963d..6e2adda 100644
--- a/python/samba/tests/ntacls.py
+++ b/python/samba/tests/ntacls.py
@@ -83,5 +83,5 @@ class NtaclsTests(TestCaseInTempDir):
lp = LoadParm()
open(self.tempf, 'w').write("empty")
lp.set("posix:eadb", os.path.join(self.tempdir, "eadbtest.tdb"))
- self.assertRaises(Exception, setntacl, lp, self.tempf, NTACL_SDDL,
+ self.assertRaises(PermissionError, setntacl, lp, self.tempf, NTACL_SDDL,
DOMAIN_SID, self.session_info, "native")
diff --git a/script/autobuild.py b/script/autobuild.py
index ecec352..7291522 100755
--- a/script/autobuild.py
+++ b/script/autobuild.py
@@ -892,9 +892,10 @@ tasks = {
("ldb-make", "cd lib/ldb && make"),
("ldb-install", "cd lib/ldb && make install"),
- ("nondevel-configure", samba_libs_envvars + " ./configure ${PREFIX}"),
+ ("nondevel-configure", samba_libs_envvars + " ./configure --vendor-name=autobuild-TEST-STRING --vendor-patch-revision=5 ${PREFIX}"),
("nondevel-make", "make -j"),
("nondevel-check", "./bin/smbd -b | grep WITH_NTVFS_FILESERVER && exit 1; exit 0"),
+ ("nondevel-check", "./bin/smbd --version | grep -e '-autobuild-TEST-STRING-5' && exit 0; exit 1"),
("nondevel-no-libtalloc", "find ./bin | grep -v 'libtalloc-report' | grep 'libtalloc' && exit 1; exit 0"),
("nondevel-no-libtdb", "find ./bin | grep -v 'libtdb-wrap' | grep 'libtdb' && exit 1; exit 0"),
("nondevel-no-libtevent", "find ./bin | grep -v 'libtevent-util' | grep 'libtevent' && exit 1; exit 0"),
diff --git a/selftest/flapping.d/gitlab-setxattr-security b/selftest/flapping.d/gitlab-setxattr-security
new file mode 100644
index 0000000..d7d2403
--- /dev/null
+++ b/selftest/flapping.d/gitlab-setxattr-security
@@ -0,0 +1,18 @@
+# gitlab runners with kernel 5.15.109+
+# allow setxattr() on security.NTACL
+#
+# It's not clear in detail why there's a difference
+# between various systems, one reason could be that
+# with selinux inode_owner_or_capable() is used to check
+# setxattr() permissions:
+# it checks for the fileowner too, as well as CAP_FOWNER.
+# Otherwise cap_inode_setxattr() is used, which checks for
+# CAP_SYS_ADMIN.
+#
+# But the kernel doesn't have selinux only apparmor...
+#
+# test_setntacl_forcenative expects
+# PermissionError: [Errno 1] Operation not permitted
+#
+# So for now we allow this to fail...
+^samba.tests.ntacls.samba.tests.ntacls.NtaclsTests.test_setntacl_forcenative.none
diff --git a/selftest/knownfail-32bit b/selftest/knownfail-32bit
index 2946f3e..8ab625d 100644
--- a/selftest/knownfail-32bit
+++ b/selftest/knownfail-32bit
@@ -65,14 +65,8 @@
# [171(1386)/261 at 6m24s, 4 errors] samba4.local.charset
# UNEXPECTED(failure): samba4.local.charset.strcasecmp(none)
# REASON: Exception: Exception: ../../lib/util/charset/tests/charset.c:56: strcasecmp("foo", "bar") was 1 (0x1), expected 4 (0x4): different strings both lower
-# UNEXPECTED(failure): samba4.local.charset.strcasecmp_m(none)
-# REASON: Exception: Exception: ../../lib/util/charset/tests/charset.c:85: strcasecmp_m(file_iso8859_1, file_utf8) was 1 (0x1), expected 38 (0x26): file.{accented e}
-# should differ
# UNEXPECTED(failure): samba4.local.charset.strncasecmp(none)
# REASON: Exception: Exception: ../../lib/util/charset/tests/charset.c:132: strncasecmp("foo", "bar", 3) was 1 (0x1), expected 4 (0x4): different strings both lower
-# UNEXPECTED(failure): samba4.local.charset.strncasecmp_m(none)
-# REASON: Exception: Exception: ../../lib/util/charset/tests/charset.c:167: strncasecmp_m(file_iso8859_1, file_utf8, 6) was 1 (0x1), expected 38 (0x26): file.{accent
-# ed e} should differ
# command: /home/samba/samba.git/bin/smbtorture $LOADLIST --configfile=$SMB_CONF_PATH --option='fss:sequence timeout=1' --maximum-runtime=$SELFTEST_MAXTIME --based
# ir=$SELFTEST_TMPDIR --format=subunit --option=torture:progress=no --target=samba4 ncalrpc:localhost local.charset 2>&1 | python3 /home/samba/samba.git/selftest/fi
# lter-subunit --fail-on-empty --prefix="samba4.local.charset." --suffix="(none)"
@@ -82,9 +76,7 @@
# ERROR: Testsuite[samba4.local.charset]
# REASON: Exit code was 1
^samba4.local.charset.strcasecmp.none
-^samba4.local.charset.strcasecmp_m.none
^samba4.local.charset.strncasecmp.none
-^samba4.local.charset.strncasecmp_m.none
#
# [229(2702)/261 at 8m44s, 5 errors] samba.tests.samba_tool.provision_lmdb_size
# UNEXPECTED(failure): samba.tests.samba_tool.provision_lmdb_size.samba.tests.samba_tool.provision_lmdb_size.ProvisionLmdbSizeTestCase.test_134217728b(none)
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 2d449e4..f2b84b4 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -618,6 +618,7 @@ sub provision_raw_prepare($$$$$$$$$$$$$$)
$ctx->{statedir} = "$prefix_abs/statedir";
$ctx->{cachedir} = "$prefix_abs/cachedir";
$ctx->{winbindd_socket_dir} = "$prefix_abs/wbsock";
+ $ctx->{nmbd_socket_dir} = "$prefix_abs/nmbsock";
$ctx->{ntp_signd_socket_dir} = "$prefix_abs/ntp_signd_socket";
$ctx->{nsswrap_passwd} = "$ctx->{etcdir}/passwd";
$ctx->{nsswrap_group} = "$ctx->{etcdir}/group";
@@ -774,6 +775,7 @@ sub provision_raw_step1($$)
state directory = $ctx->{statedir}
cache directory = $ctx->{cachedir}
winbindd socket directory = $ctx->{winbindd_socket_dir}
+ nmbd:socket dir = $ctx->{nmbd_socket_dir}
ntp signd socket directory = $ctx->{ntp_signd_socket_dir}
winbind separator = /
interfaces = $interfaces
diff --git a/source3/include/fstring.h b/source3/include/fstring.h
new file mode 100644
index 0000000..dfc8f17
--- /dev/null
+++ b/source3/include/fstring.h
@@ -0,0 +1,27 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) 2002 by Martin Pool <mbp@samba.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _SAMBA_FSTRING_H
+#define _SAMBA_FSTRING_H
+
+#ifndef FSTRING_LEN
+#define FSTRING_LEN 256
+typedef char fstring[FSTRING_LEN];
+#endif
+
+#endif /* _SAMBA_FSTRING_H */
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 1e7b79b..ee05b93 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -237,10 +237,7 @@ enum timestamp_set_resolution {
_________)/\\_//(\/(/\)/\//\/\///|_)_______
*/
-#ifndef FSTRING_LEN
-#define FSTRING_LEN 256
-typedef char fstring[FSTRING_LEN];
-#endif
+#include "fstring.h"
/* debug.h need to be included before samba_util.h for the macro SMB_ASSERT */
#include "../lib/util/debug.h"
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index 8fbe5a3..51efe82 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -20,18 +20,6 @@
*/
-#define INFO_VERSION "INFO/version"
-#define INFO_COUNT "INFO/num_entries"
-#define INFO_ID_HIGH "INFO/id_high"
-#define INFO_ID_LOW "INFO/id_low"
-#define ENTRY_PREFIX "ENTRY/"
-
-#define PERMANENT_TTL 0
-
-/* NTAS uses 2, NT uses 1, WfWg uses 0 */
-#define MAINTAIN_LIST 2
-#define ELECTION_VERSION 1
-
#define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */
#define MIN_DGRAM_SIZE 12
@@ -140,12 +128,6 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
-/* Workgroup state identifiers. */
-#define AM_POTENTIAL_MASTER_BROWSER(work) ((work)->mst_state == MST_POTENTIAL)
-#define AM_LOCAL_MASTER_BROWSER(work) ((work)->mst_state == MST_BROWSER)
-#define AM_DOMAIN_MASTER_BROWSER(work) ((work)->dom_state == DOMAIN_MST)
-#define AM_DOMAIN_MEMBER(work) ((work)->log_state == LOGON_SRV)
-
/* Microsoft browser NetBIOS name. */
#define MSBROWSE "\001\002__MSBROWSE__\002"
@@ -159,293 +141,33 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
#define FIND_ANY_NAME 0
#define FIND_SELF_NAME 1
-/*
- * The different name types that can be in namelists.
- *
- * SELF_NAME should only be on the broadcast and unicast subnets.
- * LMHOSTS_NAME should only be in the remote_broadcast_subnet.
- * REGISTER_NAME, DNS_NAME, DNSFAIL_NAME should only be in the wins_server_subnet.
- * WINS_PROXY_NAME should only be on the broadcast subnets.
- * PERMANENT_NAME can be on all subnets except remote_broadcast_subnet.
- *
- */
-
-enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
- DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
-enum master_state {
- MST_NONE,
- MST_POTENTIAL,
- MST_BACKUP,
- MST_MSB,
- MST_BROWSER,
- MST_UNBECOMING_MASTER
-};
-
-enum domain_state {
- DOMAIN_NONE,
- DOMAIN_WAIT,
- DOMAIN_MST
-};
-
-enum logon_state {
- LOGON_NONE,
- LOGON_WAIT,
- LOGON_SRV
-};
-
-struct subnet_record;
-
-struct nmb_data {
- uint16_t nb_flags; /* Netbios flags. */
- int num_ips; /* Number of ip entries. */
- struct in_addr *ip; /* The ip list for this name. */
-
- enum name_source source; /* Where the name came from. */
-
- time_t death_time; /* The time the record must be removed (do not remove if 0). */
- time_t refresh_time; /* The time the record should be refreshed. */
-
- uint64_t id; /* unique id */
- struct in_addr wins_ip; /* the address of the wins server this record comes from */
-
- int wins_flags; /* similar to the netbios flags but different ! */
-};
-
-/* This structure represents an entry in a local netbios name list. */
-struct name_record {
- struct name_record *prev, *next;
- struct subnet_record *subnet;
- struct nmb_name name; /* The netbios name. */
- struct nmb_data data; /* The netbios data. */
-};
-
-/* Browser cache for synchronising browse lists. */
-struct browse_cache_record {
- struct browse_cache_record *prev, *next;
- unstring lmb_name;
- unstring work_group;
- struct in_addr ip;
- time_t sync_time;
- time_t death_time; /* The time the record must be removed. */
-};
-
-/* used for server information: client, nameserv and ipc */
-struct server_info_struct {
- fstring name;
- uint32_t type;
- fstring comment;
- fstring domain; /* used ONLY in ipc.c NOT namework.c */
- bool server_added; /* used ONLY in ipc.c NOT namework.c */
-};
-
-/* This is used to hold the list of servers in my domain, and is
- contained within lists of domains. */
-
-struct server_record {
- struct server_record *next;
- struct server_record *prev;
-
- struct subnet_record *subnet;
-
- struct server_info_struct serv;
- time_t death_time;
-};
-
-/* A workgroup structure. It contains a list of servers. */
-struct work_record {
- struct work_record *next;
- struct work_record *prev;
-
- struct subnet_record *subnet;
-
- struct server_record *serverlist;
-
- /* Stage of development from non-local-master up to local-master browser. */
- enum master_state mst_state;
-
- /* Stage of development from non-domain-master to domain-master browser. */
- enum domain_state dom_state;
-
- /* Stage of development from non-logon-server to logon server. */
- enum logon_state log_state;
-
- /* Work group info. */
- unstring work_group;
- int token; /* Used when communicating with backup browsers. */
- unstring local_master_browser_name; /* Current local master browser. */
-
- /* Announce info. */
- time_t lastannounce_time;
- int announce_interval;
- bool needannounce;
-
- /* Timeout time for this workgroup. 0 means permanent. */
- time_t death_time;
-
- /* Election info */
- bool RunningElection;
- bool needelection;
- int ElectionCount;
- uint32_t ElectionCriterion;
-
- /* Domain master browser info. Used for efficient syncs. */
- struct nmb_name dmb_name;
- struct in_addr dmb_addr;
-};
-
-/* typedefs needed to define copy & free functions for userdata. */
-struct userdata_struct;
-
-typedef struct userdata_struct * (*userdata_copy_fn)(struct userdata_struct *);
-typedef void (*userdata_free_fn)(struct userdata_struct *);
-
-/* Structure to define any userdata passed around. */
-
-struct userdata_struct {
- userdata_copy_fn copy_fn;
- userdata_free_fn free_fn;
- unsigned int userdata_len;
- char data[16]; /* 16 is to ensure alignment/padding on all systems */
+#define MAX_NETBIOSNAME_LEN 16
+/* DOS character, NetBIOS namestring. Type used on the wire. */
+typedef char nstring[MAX_NETBIOSNAME_LEN];
+/* Unix character, NetBIOS namestring. Type used to manipulate name in nmbd. */
+typedef char unstring[MAX_NETBIOSNAME_LEN*4];
+
+/* A netbios name structure. */
+struct nmb_name {
+ nstring name;
+ char scope[64];
+ unsigned int name_type;
};
-struct response_record;
-struct packet_struct;
-struct res_rec;
-
-/* typedef to define the function called when this response packet comes in. */
-typedef void (*response_function)(struct subnet_record *, struct response_record *,
- struct packet_struct *);
-
-/* typedef to define the function called when this response record times out. */
-typedef void (*timeout_response_function)(struct subnet_record *,
- struct response_record *);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is successful. */
-typedef void (*success_function)(struct subnet_record *, struct userdata_struct *, ...);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is unsuccessful. */
-typedef void (*fail_function)(struct subnet_record *, struct response_record *, ...);
-
-/* List of typedefs for success and fail functions of the different query
- types. Used to catch any compile time prototype errors. */
-
-typedef void (*register_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16_t,
- int,
- struct in_addr);
-typedef void (*register_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*release_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr);
-typedef void (*release_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*refresh_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16_t,
- int,
- struct in_addr);
-typedef void (*refresh_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*query_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr,
- struct res_rec *answers);
-
-typedef void (*query_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *,
- int);
-
-typedef void (*node_status_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct res_rec *,
- struct in_addr);
-typedef void (*node_status_fail_function)( struct subnet_record *,
- struct response_record *);
-
-/* Initiated name queries are recorded in this list to track any responses. */
-
-struct response_record {
- struct response_record *next;
- struct response_record *prev;
-
- uint16_t response_id;
-
- /* Callbacks for packets received or not. */
- response_function resp_fn;
- timeout_response_function timeout_fn;
-
- /* Callbacks for the request succeeding or not. */
- success_function success_fn;
- fail_function fail_fn;
-
- struct packet_struct *packet;
-
- struct userdata_struct *userdata;
-
- int num_msgs;
-
- time_t repeat_time;
- time_t repeat_interval;
- int repeat_count;
-
- /* Recursion protection. */
- bool in_expiration_processing;
+/* A netbios node status array element. */
+struct node_status {
+ nstring name;
+ unsigned char type;
+ unsigned char flags;
};
-/* A subnet structure. It contains a list of workgroups and netbios names. */
-
-/*
- B nodes will have their own, totally separate subnet record, with their
- own netbios name set. These do NOT interact with other subnet records'
- netbios names.
-*/
-
-enum subnet_type {
- NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
- UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
- REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
- WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
-};
-
-struct subnet_record {
- struct subnet_record *next;
- struct subnet_record *prev;
-
- char *subnet_name; /* For Debug identification. */
- enum subnet_type type; /* To catagorize the subnet. */
-
- struct work_record *workgrouplist; /* List of workgroups. */
- struct name_record *namelist; /* List of netbios names. */
- struct response_record *responselist; /* List of responses expected. */
-
- bool namelist_changed;
- bool work_changed;
-
- struct in_addr bcast_ip;
- struct in_addr mask_ip;
- struct in_addr myip;
- int nmb_sock; /* socket to listen for unicast 137. */
- int nmb_bcast; /* socket to listen for broadcast 137. */
- int dgram_sock; /* socket to listen for unicast 138. */
- int dgram_bcast; /* socket to listen for broadcast 138. */
+/* The extra info from a NetBIOS node status query */
+struct node_status_extra {
+ unsigned char mac_addr[6];
+ /* There really is more here ... */
};
/* A resource record. */
@@ -564,66 +286,4 @@ struct packet_struct
#define ANN_ResetBrowserState 14
#define ANN_LocalMasterAnnouncement 15
-
-/* Broadcast packet announcement intervals, in minutes. */
-
-/* Attempt to add domain logon and domain master names. */
-#define CHECK_TIME_ADD_DOM_NAMES 5
-
-/* Search for master browsers of workgroups samba knows about,
- except default. */
-#define CHECK_TIME_MST_BROWSE 5
-
-/* Request backup browser announcements from other servers. */
-#define CHECK_TIME_ANNOUNCE_BACKUP 15
-
-/* Request host announcements from other servers: min and max of interval. */
-#define CHECK_TIME_MIN_HOST_ANNCE 3
-#define CHECK_TIME_MAX_HOST_ANNCE 12
-
-/* Announce as master to WINS server and any Primary Domain Controllers. */
-#define CHECK_TIME_MST_ANNOUNCE 15
-
-/* Time between syncs from domain master browser to local master browsers. */
-#define CHECK_TIME_DMB_TO_LMB_SYNC 15
-
-/* Do all remote announcements this often. */
-#define REMOTE_ANNOUNCE_INTERVAL 180
-
-/* what is the maximum period between name refreshes. Note that this only
- affects non-permanent self names (in seconds) */
-#define MAX_REFRESH_TIME (60*20)
-
-/* The Extinction interval: 4 days, time a node will stay in released state */
-#define EXTINCTION_INTERVAL (4*24*60*60)
-
-/* The Extinction time-out: 1 day, time a node will stay in deleted state */
-#define EXTINCTION_TIMEOUT (24*60*60)
-
-/* Macro's to enumerate subnets either with or without
- the UNICAST subnet. */
-
-extern struct subnet_record *subnetlist;
-extern struct subnet_record *unicast_subnet;
-extern struct subnet_record *wins_server_subnet;
-extern struct subnet_record *remote_broadcast_subnet;
-
-#define FIRST_SUBNET subnetlist
-#define NEXT_SUBNET_EXCLUDING_UNICAST(x) ((x)->next)
-#define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
-
-/* wins replication record used between nmbd and wrepld */
-typedef struct _WINS_RECORD {
- char name[17];
- char type;
- int nb_flags;
- int wins_flags;
- uint64_t id;
- int num_ips;
- struct in_addr ip[25];
- struct in_addr wins_ip;
-} WINS_RECORD;
-
-/* To be removed. */
-enum state_type { TEST };
#endif /* _NAMESERV_H_ */
diff --git a/source3/include/session.h b/source3/include/session.h
index 40c25e5..903208e 100644
--- a/source3/include/session.h
+++ b/source3/include/session.h
@@ -39,6 +39,7 @@ struct sessionid {
fstring ip_addr_str;
time_t connect_start;
uint16_t connection_dialect;
+ bool authenticated;
uint8_t encryption_flags;
uint16_t cipher;
uint16_t signing;
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 81d761d..ce18872 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -625,31 +625,7 @@ struct kernel_oplocks_ops {
#include "smb_macros.h"
-#define MAX_NETBIOSNAME_LEN 16
-/* DOS character, NetBIOS namestring. Type used on the wire. */
-typedef char nstring[MAX_NETBIOSNAME_LEN];
-/* Unix character, NetBIOS namestring. Type used to manipulate name in nmbd. */
-typedef char unstring[MAX_NETBIOSNAME_LEN*4];
-
-/* A netbios name structure. */
-struct nmb_name {
- nstring name;
- char scope[64];
- unsigned int name_type;
-};
-
-/* A netbios node status array element. */
-struct node_status {
- nstring name;
- unsigned char type;
- unsigned char flags;
-};
-
-/* The extra info from a NetBIOS node status query */
-struct node_status_extra {
- unsigned char mac_addr[6];
- /* There really is more here ... */
-};
+#include "nameserv.h"
#define SAFE_NETBIOS_CHARS ". -_"
diff --git a/source3/lib/sessionid_tdb.c b/source3/lib/sessionid_tdb.c
index 2376fd4..54bb895 100644
--- a/source3/lib/sessionid_tdb.c
+++ b/source3/lib/sessionid_tdb.c
@@ -24,6 +24,7 @@
#include "session.h"
#include "util_tdb.h"
#include "smbd/globals.h"
+#include "../libcli/security/session.h"
struct sessionid_traverse_read_state {
int (*fn)(const char *key, struct sessionid *session,
@@ -48,11 +49,18 @@ static int sessionid_traverse_read_fn(struct smbXsrv_session_global0 *global,
};
if (session_info != NULL) {
+ enum security_user_level ul;
+
session.uid = session_info->unix_token->uid;
session.gid = session_info->unix_token->gid;
strncpy(session.username,
session_info->unix_info->unix_name,
sizeof(fstring)-1);
+
+ ul = security_session_user_level(session_info, NULL);
+ if (ul >= SECURITY_USER) {
+ session.authenticated = true;
+ }
}
strncpy(session.remote_machine,
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index d85f676..3c7c194 100644
--- a/source3/lib/util_tdb.c
+++ b/source3/lib/util_tdb.c
@@ -324,11 +324,11 @@ int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2)
return 1;
}
if (t1.dptr == t2.dptr) {
- return t1.dsize - t2.dsize;
+ return NUMERIC_CMP(t1.dsize, t2.dsize);
}
ret = memcmp(t1.dptr, t2.dptr, MIN(t1.dsize, t2.dsize));
if (ret == 0) {
- return t1.dsize - t2.dsize;
+ return NUMERIC_CMP(t1.dsize, t2.dsize);
}
return ret;
}
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index f76c566..6c6d23c 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;
+ }
}
/*
@@ -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;
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index b5139e5..d467079 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -275,12 +275,12 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
/* Fill in the ads->config values */
+ ADS_TALLOC_CONST_FREE(ads->config.workgroup);
ADS_TALLOC_CONST_FREE(ads->config.realm);
ADS_TALLOC_CONST_FREE(ads->config.bind_path);
ADS_TALLOC_CONST_FREE(ads->config.ldap_server_name);
ADS_TALLOC_CONST_FREE(ads->config.server_site_name);
ADS_TALLOC_CONST_FREE(ads->config.client_site_name);
- ADS_TALLOC_CONST_FREE(ads->server.workgroup);
if (!check_cldap_reply_required_flags(cldap_reply->server_type,
ads->config.flags)) {
@@ -296,6 +296,13 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
goto out;
}
+ ads->config.workgroup = talloc_strdup(ads, cldap_reply->domain_name);
+ if (ads->config.workgroup == NULL) {
+ DBG_WARNING("Out of memory\n");
+ ret = false;
+ goto out;
+ }
+
ads->config.realm = talloc_asprintf_strupper_m(ads,
"%s",
cldap_reply->dns_domain);
@@ -334,13 +341,6 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
}
}
- ads->server.workgroup = talloc_strdup(ads, cldap_reply->domain_name);
- if (ads->server.workgroup == NULL) {
- DBG_WARNING("Out of memory\n");
- ret = false;
- goto out;
- }
-
ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
ads->ldap.ss = *ss;
diff --git a/source3/librpc/idl/ads.idl b/source3/librpc/idl/ads.idl
index 4f3a387..d10e5b4 100644
--- a/source3/librpc/idl/ads.idl
+++ b/source3/librpc/idl/ads.idl
@@ -59,6 +59,7 @@ interface ads
typedef [nopull,nopush] struct {
nbt_server_type flags; /* cldap flags identifying the services. */
+ string workgroup;
string realm;
string bind_path;
string ldap_server_name;
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index a45bdac..c87c870 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -349,7 +349,11 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1,
+ subreq = nb_packet_reader_send(state,
+ ev,
+ global_nmbd_socket_dir(),
+ DGRAM_PACKET,
+ -1,
state->my_mailslot);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 09a6e66..654893c 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);
@@ -930,6 +952,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,
diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c
index dcb2f9e..a902341 100644
--- a/source3/libsmb/libsmb_xattr.c
+++ b/source3/libsmb/libsmb_xattr.c
@@ -121,7 +121,13 @@ ace_compare(struct security_ace *ace1,
*/
if (ace1->type != ace2->type) {
- return ace2->type - ace1->type;
+ /*
+ * ace2 and ace1 are reversed here, so that
+ * ACCESS_DENIED_ACE_TYPE (1) sorts before
+ * ACCESS_ALLOWED_ACE_TYPE (0), which is the order you
+ * usually want.
+ */
+ return NUMERIC_CMP(ace2->type, ace1->type);
}
if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) {
@@ -129,15 +135,15 @@ ace_compare(struct security_ace *ace1,
}
if (ace1->flags != ace2->flags) {
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
}
if (ace1->access_mask != ace2->access_mask) {
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
}
if (ace1->size != ace2->size) {
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
}
return memcmp(ace1, ace2, sizeof(struct security_ace));
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index e6c0c7d..8f6a9b5 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -34,6 +34,7 @@
#include "lib/gencache.h"
#include "librpc/gen_ndr/dns.h"
#include "lib/util/util_net.h"
+#include "lib/util/tsort.h"
#include "lib/util/string_wrappers.h"
/* nmbd.c sets this to True. */
@@ -644,7 +645,12 @@ static struct tevent_req *nb_trans_send(
return tevent_req_post(req, ev);
}
- subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
+ subreq = nb_packet_reader_send(state,
+ ev,
+ global_nmbd_socket_dir(),
+ type,
+ state->trn_id,
+ NULL);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -1082,8 +1088,15 @@ bool name_status_find(const char *q_name,
}
/*
- comparison function used by sort_addr_list
-*/
+ * comparison function used by sort_addr_list
+ *
+ * This comparison is intransitive in sort if a socket has an invalid
+ * family (i.e., not IPv4 or IPv6), or an interface doesn't support
+ * the family. Say we have sockaddrs with IP versions {4,5,6}, of
+ * which 5 is invalid. By this function, 4 == 5 and 6 == 5, but 4 !=
+ * 6. This is of course a consequence of cmp() being unable to
+ * communicate error.
+ */
static int addr_compare(const struct sockaddr_storage *ss1,
const struct sockaddr_storage *ss2)
@@ -1171,7 +1184,7 @@ static int addr_compare(const struct sockaddr_storage *ss1,
max_bits2 += 128;
}
}
- return max_bits2 - max_bits1;
+ return NUMERIC_CMP(max_bits2, max_bits1);
}
/*
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index c90e92e..2297dd9 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -23,6 +23,12 @@
#include "libsmb/nmblib.h"
#include "lib/util/string_wrappers.h"
+const char *global_nmbd_socket_dir(void)
+{
+ return lp_parm_const_string(-1, "nmbd", "socket dir",
+ get_dyn_NMBDSOCKETDIR());
+}
+
static const struct opcode_names {
const char *nmb_opcode_name;
int opcode;
@@ -1229,8 +1235,10 @@ static unsigned char sort_ip[4];
static int name_query_comp(unsigned char *p1, unsigned char *p2)
{
- return matching_len_bits(p2+2, sort_ip, 4) -
- matching_len_bits(p1+2, sort_ip, 4);
+ int a = matching_len_bits(p1+2, sort_ip, 4);
+ int b = matching_len_bits(p2+2, sort_ip, 4);
+ /* reverse sort -- p2 derived value comes first */
+ return NUMERIC_CMP(b, a);
}
/****************************************************************************
diff --git a/source3/libsmb/nmblib.h b/source3/libsmb/nmblib.h
index 52600a4..5171a26 100644
--- a/source3/libsmb/nmblib.h
+++ b/source3/libsmb/nmblib.h
@@ -29,6 +29,8 @@
/* The following definitions come from libsmb/nmblib.c */
+const char *global_nmbd_socket_dir(void);
+
void debug_nmb_packet(struct packet_struct *p);
void put_name(char *dest, const char *name, int pad, unsigned int name_type);
char *nmb_namestr(const struct nmb_name *n);
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index b81d379..10ceac7 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -26,12 +26,6 @@
#include "lib/tsocket/tsocket.h"
#include "lib/util/sys_rw.h"
-static const char *nmbd_socket_dir(void)
-{
- return lp_parm_const_string(-1, "nmbd", "socket dir",
- get_dyn_NMBDSOCKETDIR());
-}
-
struct nb_packet_query {
enum packet_type type;
size_t mailslot_namelen;
@@ -74,6 +68,7 @@ static void nb_packet_server_listener(struct tevent_context *ev,
NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
int max_clients,
struct nb_packet_server **presult)
{
@@ -90,7 +85,7 @@ NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
result->max_clients = max_clients;
result->listen_sock = create_pipe_sock(
- nmbd_socket_dir(), "unexpected", 0755);
+ nmbd_socket_dir, "unexpected", 0755);
if (result->listen_sock == -1) {
status = map_nt_error_from_unix(errno);
goto fail;
@@ -248,7 +243,7 @@ static void nb_packet_got_query(struct tevent_req *req)
ssize_t nread;
int err;
- nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, client, &buf, &err);
TALLOC_FREE(req);
if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
DEBUG(10, ("read_packet_recv returned %d (%s)\n",
@@ -280,6 +275,8 @@ static void nb_packet_got_query(struct tevent_req *req)
}
}
+ TALLOC_FREE(buf);
+
client->ack.byte = 0;
client->ack.iov[0].iov_base = &client->ack.byte;
client->ack.iov[0].iov_len = 1;
@@ -333,7 +330,7 @@ static void nb_packet_client_read_done(struct tevent_req *req)
uint8_t *buf;
int err;
- nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, client, &buf, &err);
TALLOC_FREE(req);
if (nread == 1) {
DEBUG(10, ("Protocol error, received data on write-only "
@@ -495,6 +492,7 @@ static void nb_packet_reader_got_ack(struct tevent_req *subreq);
struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
enum packet_type type,
int trn_id,
const char *mailslot_name)
@@ -530,7 +528,7 @@ struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
tevent_req_nterror(req, map_nt_error_from_unix(errno));
return tevent_req_post(req, ev);
}
- rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir(),
+ rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir,
"unexpected");
if (tevent_req_nomem(rpath, req)) {
return tevent_req_post(req, ev);
diff --git a/source3/libsmb/unexpected.h b/source3/libsmb/unexpected.h
index 270976b..4ae9b20 100644
--- a/source3/libsmb/unexpected.h
+++ b/source3/libsmb/unexpected.h
@@ -29,12 +29,14 @@ struct nb_packet_reader;
NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
int max_clients,
struct nb_packet_server **presult);
void nb_packet_dispatch(struct nb_packet_server *server,
struct packet_struct *p);
struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
enum packet_type type,
int trn_id,
const char *mailslot_name);
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 905da04..328a9bf 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -408,12 +408,9 @@ static int lock_compare(const struct lock_struct *lck1,
const struct lock_struct *lck2)
{
if (lck1->start != lck2->start) {
- return (lck1->start - lck2->start);
+ return NUMERIC_CMP(lck1->start, lck2->start);
}
- if (lck2->size != lck1->size) {
- return ((int)lck1->size - (int)lck2->size);
- }
- return 0;
+ return NUMERIC_CMP(lck1->size, lck2->size);
}
#endif
diff --git a/source3/modules/posixacl_xattr.c b/source3/modules/posixacl_xattr.c
index 365cdc7..5d0516c 100644
--- a/source3/modules/posixacl_xattr.c
+++ b/source3/modules/posixacl_xattr.c
@@ -226,14 +226,14 @@ static int posixacl_xattr_entry_compare(const void *left, const void *right)
tag_left = SVAL(left, 0);
tag_right = SVAL(right, 0);
- ret = (tag_left - tag_right);
- if (!ret) {
+ ret = NUMERIC_CMP(tag_left, tag_right);
+ if (ret == 0) {
/* ID is the third element in the entry, after two short
integers (tag and perm), i.e at offset 4.
*/
id_left = IVAL(left, 4);
id_right = IVAL(right, 4);
- ret = id_left - id_right;
+ ret = NUMERIC_CMP(id_left, id_right);
}
return ret;
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 62ad506..7380598 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2147,6 +2147,12 @@ static struct tevent_req *vfswrap_offload_write_send(
.remaining = to_copy,
};
+ status = vfs_offload_token_ctx_init(handle->conn->sconn->client,
+ &vfswrap_offload_ctx);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+
tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
switch (fsctl) {
diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c
index 327a7ee..ea0417d 100644
--- a/source3/modules/vfs_recycle.c
+++ b/source3/modules/vfs_recycle.c
@@ -55,10 +55,14 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
const char *service,
const char *user)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
struct recycle_config_data *config = NULL;
int ret;
int t;
- const char *buff;
+ const char *buff = NULL;
+ const char **tmplist = NULL;
+ char *repository = NULL;
ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
if (ret < 0) {
@@ -75,10 +79,30 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
errno = ENOMEM;
return -1;
}
- config->repository = lp_parm_const_string(SNUM(handle->conn),
- "recycle",
- "repository",
- ".recycle");
+ buff = lp_parm_const_string(SNUM(handle->conn),
+ "recycle",
+ "repository",
+ ".recycle");
+ repository = talloc_sub_full(
+ config,
+ lp_servicename(talloc_tos(), lp_sub, SNUM(handle->conn)),
+ handle->conn->session_info->unix_info->unix_name,
+ handle->conn->connectpath,
+ handle->conn->session_info->unix_token->gid,
+ handle->conn->session_info->unix_info->sanitized_username,
+ handle->conn->session_info->info->domain_name,
+ buff);
+ if (repository == NULL) {
+ DBG_ERR("talloc_sub_full() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ /* shouldn't we allow absolute path names here? --metze */
+ /* Yes :-). JRA. */
+ trim_char(repository, '\0', '/');
+ config->repository = repository;
+
config->keeptree = lp_parm_bool(SNUM(handle->conn),
"recycle",
"keeptree",
@@ -95,18 +119,48 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
"recycle",
"touch_mtime",
False);
- config->exclude = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "exclude",
- NULL);
- config->exclude_dir = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "exclude_dir",
- NULL);
- config->noversions = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "noversions",
- NULL);
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "exclude",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->exclude = discard_const_p(const char *, tmpcpy);
+ }
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "exclude_dir",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->exclude_dir = discard_const_p(const char *, tmpcpy);
+ }
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "noversions",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->noversions = discard_const_p(const char *, tmpcpy);
+ }
config->minsize = conv_str_size(lp_parm_const_string(
SNUM(handle->conn), "recycle", "minsize", NULL));
config->maxsize = conv_str_size(lp_parm_const_string(
@@ -421,42 +475,27 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
int flags)
{
- const struct loadparm_substitution *lp_sub =
- loadparm_s3_global_substitution();
- connection_struct *conn = handle->conn;
+ TALLOC_CTX *frame = NULL;
struct smb_filename *full_fname = NULL;
char *path_name = NULL;
- char *temp_name = NULL;
- char *final_name = NULL;
+ const char *temp_name = NULL;
+ const char *final_name = NULL;
struct smb_filename *smb_fname_final = NULL;
- const char *base;
- char *repository = NULL;
+ const char *base = NULL;
int i = 1;
off_t file_size; /* space_avail; */
bool exist;
int rc = -1;
- struct recycle_config_data *config;
+ struct recycle_config_data *config = NULL;
SMB_VFS_HANDLE_GET_DATA(handle,
config,
struct recycle_config_data,
- return true);
+ return -1);
- repository = talloc_sub_full(
- NULL,
- lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
- conn->session_info->unix_info->unix_name,
- conn->connectpath,
- conn->session_info->unix_token->gid,
- conn->session_info->unix_info->sanitized_username,
- conn->session_info->info->domain_name,
- config->repository);
- ALLOC_CHECK(repository, done);
- /* shouldn't we allow absolute path names here? --metze */
- /* Yes :-). JRA. */
- trim_char(repository, '\0', '/');
+ frame = talloc_stackframe();
- if(!repository || *(repository) == '\0') {
+ if (config->repository[0] == '\0') {
DEBUG(3, ("recycle: repository path not set, purging %s...\n",
smb_fname_str_dbg(smb_fname)));
rc = SMB_VFS_NEXT_UNLINKAT(handle,
@@ -466,16 +505,18 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
goto done;
}
- full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ full_fname = full_path_from_dirfsp_atname(frame,
dirfsp,
smb_fname);
if (full_fname == NULL) {
- return -1;
+ rc = -1;
+ errno = ENOMEM;
+ goto done;
}
/* we don't recycle the recycle bin... */
- if (strncmp(full_fname->base_name, repository,
- strlen(repository)) == 0) {
+ if (strncmp(full_fname->base_name, config->repository,
+ strlen(config->repository)) == 0) {
DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n"));
rc = SMB_VFS_NEXT_UNLINKAT(handle,
dirfsp,
@@ -539,7 +580,7 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
*/
/* extract filename and path */
- if (!parent_dirname(talloc_tos(), full_fname->base_name, &path_name, &base)) {
+ if (!parent_dirname(frame, full_fname->base_name, &path_name, &base)) {
rc = -1;
errno = ENOMEM;
goto done;
@@ -571,13 +612,16 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
}
if (config->keeptree) {
- if (asprintf(&temp_name, "%s/%s", repository, path_name) == -1) {
- ALLOC_CHECK(temp_name, done);
+ temp_name = talloc_asprintf(frame, "%s/%s",
+ config->repository,
+ path_name);
+ if (temp_name == NULL) {
+ rc = -1;
+ goto done;
}
} else {
- temp_name = SMB_STRDUP(repository);
+ temp_name = config->repository;
}
- ALLOC_CHECK(temp_name, done);
exist = recycle_directory_exist(handle, temp_name);
if (exist) {
@@ -600,12 +644,15 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
}
}
- if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) {
- ALLOC_CHECK(final_name, done);
+ final_name = talloc_asprintf(frame, "%s/%s",
+ temp_name, base);
+ if (final_name == NULL) {
+ rc = -1;
+ goto done;
}
/* Create smb_fname with final base name and orig stream name. */
- smb_fname_final = synthetic_smb_fname(talloc_tos(),
+ smb_fname_final = synthetic_smb_fname(frame,
final_name,
full_fname->stream_name,
NULL,
@@ -641,20 +688,16 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
/* rename file we move to recycle bin */
i = 1;
while (recycle_file_exist(handle, smb_fname_final)) {
- SAFE_FREE(final_name);
- if (asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base) == -1) {
- ALLOC_CHECK(final_name, done);
- }
+ char *copy = NULL;
+
TALLOC_FREE(smb_fname_final->base_name);
- smb_fname_final->base_name = talloc_strdup(smb_fname_final,
- final_name);
- if (smb_fname_final->base_name == NULL) {
- rc = SMB_VFS_NEXT_UNLINKAT(handle,
- dirfsp,
- smb_fname,
- flags);
+ copy = talloc_asprintf(smb_fname_final, "%s/Copy #%d of %s",
+ temp_name, i++, base);
+ if (copy == NULL) {
+ rc = -1;
goto done;
}
+ smb_fname_final->base_name = copy;
}
DEBUG(10, ("recycle: Moving %s to %s\n", smb_fname_str_dbg(full_fname),
@@ -681,12 +724,7 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
recycle_do_touch(handle, smb_fname_final, config->touch_mtime);
done:
- TALLOC_FREE(path_name);
- SAFE_FREE(temp_name);
- SAFE_FREE(final_name);
- TALLOC_FREE(full_fname);
- TALLOC_FREE(smb_fname_final);
- TALLOC_FREE(repository);
+ TALLOC_FREE(frame);
return rc;
}
diff --git a/source3/modules/vfs_vxfs.c b/source3/modules/vfs_vxfs.c
index aae2ca1..ecc53d0 100644
--- a/source3/modules/vfs_vxfs.c
+++ b/source3/modules/vfs_vxfs.c
@@ -111,13 +111,13 @@ static int vxfs_ace_cmp(const void *ace1, const void *ace2)
type_a1 = SVAL(ace1, 0);
type_a2 = SVAL(ace2, 0);
- ret = (type_a1 - type_a2);
- if (!ret) {
+ ret = NUMERIC_CMP(type_a1, type_a2);
+ if (ret == 0) {
/* Compare ID under type */
/* skip perm thus take offset as 4*/
id_a1 = IVAL(ace1, 4);
id_a2 = IVAL(ace2, 4);
- ret = id_a1 - id_a2;
+ ret = NUMERIC_CMP(id_a1, id_a2);
}
return ret;
diff --git a/source3/modules/vfs_widelinks.c b/source3/modules/vfs_widelinks.c
index c5b5084..4339f6d 100644
--- a/source3/modules/vfs_widelinks.c
+++ b/source3/modules/vfs_widelinks.c
@@ -383,8 +383,17 @@ static int widelinks_openat(vfs_handle_struct *handle,
}
lstat_ret = SMB_VFS_NEXT_LSTAT(handle,
full_fname);
- if (lstat_ret != -1 &&
- VALID_STAT(full_fname->st) &&
+ if (lstat_ret == -1) {
+ /*
+ * Path doesn't exist. We must
+ * return errno from LSTAT.
+ */
+ int saved_errno = errno;
+ TALLOC_FREE(full_fname);
+ errno = saved_errno;
+ return -1;
+ }
+ if (VALID_STAT(full_fname->st) &&
S_ISLNK(full_fname->st.st_ex_mode)) {
fsp->fsp_name->st = full_fname->st;
}
diff --git a/source3/nmbd/nmbd.h b/source3/nmbd/nmbd.h
index f207eb9..0a8e345 100644
--- a/source3/nmbd/nmbd.h
+++ b/source3/nmbd/nmbd.h
@@ -26,6 +26,388 @@
#endif
#include "libsmb/nmblib.h"
+
+#define INFO_VERSION "INFO/version"
+#define INFO_COUNT "INFO/num_entries"
+#define INFO_ID_HIGH "INFO/id_high"
+#define INFO_ID_LOW "INFO/id_low"
+#define ENTRY_PREFIX "ENTRY/"
+
+#define PERMANENT_TTL 0
+
+/* NTAS uses 2, NT uses 1, WfWg uses 0 */
+#define MAINTAIN_LIST 2
+#define ELECTION_VERSION 1
+
+#define REFRESH_TIME (15*60)
+#define NAME_POLL_REFRESH_TIME (5*60)
+#define NAME_POLL_INTERVAL 15
+
+/* Workgroup state identifiers. */
+#define AM_POTENTIAL_MASTER_BROWSER(work) ((work)->mst_state == MST_POTENTIAL)
+#define AM_LOCAL_MASTER_BROWSER(work) ((work)->mst_state == MST_BROWSER)
+#define AM_DOMAIN_MASTER_BROWSER(work) ((work)->dom_state == DOMAIN_MST)
+#define AM_DOMAIN_MEMBER(work) ((work)->log_state == LOGON_SRV)
+
+/* Microsoft browser NetBIOS name. */
+#define MSBROWSE "\001\002__MSBROWSE__\002"
+
+/* Mail slots. */
+#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+#define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON"
+#define NT_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NTLOGON"
+#define LANMAN_MAILSLOT "\\MAILSLOT\\LANMAN"
+
+/* Samba definitions for find_name_on_subnet(). */
+#define FIND_ANY_NAME 0
+#define FIND_SELF_NAME 1
+
+/*
+ * The different name types that can be in namelists.
+ *
+ * SELF_NAME should only be on the broadcast and unicast subnets.
+ * LMHOSTS_NAME should only be in the remote_broadcast_subnet.
+ * REGISTER_NAME, DNS_NAME, DNSFAIL_NAME should only be in the wins_server_subnet.
+ * WINS_PROXY_NAME should only be on the broadcast subnets.
+ * PERMANENT_NAME can be on all subnets except remote_broadcast_subnet.
+ *
+ */
+
+enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
+ DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
+
+enum master_state {
+ MST_NONE,
+ MST_POTENTIAL,
+ MST_BACKUP,
+ MST_MSB,
+ MST_BROWSER,
+ MST_UNBECOMING_MASTER
+};
+
+enum domain_state {
+ DOMAIN_NONE,
+ DOMAIN_WAIT,
+ DOMAIN_MST
+};
+
+enum logon_state {
+ LOGON_NONE,
+ LOGON_WAIT,
+ LOGON_SRV
+};
+
+struct subnet_record;
+
+struct nmb_data {
+ uint16_t nb_flags; /* Netbios flags. */
+ int num_ips; /* Number of ip entries. */
+ struct in_addr *ip; /* The ip list for this name. */
+
+ enum name_source source; /* Where the name came from. */
+
+ time_t death_time; /* The time the record must be removed (do not remove if 0). */
+ time_t refresh_time; /* The time the record should be refreshed. */
+
+ uint64_t id; /* unique id */
+ struct in_addr wins_ip; /* the address of the wins server this record comes from */
+
+ int wins_flags; /* similar to the netbios flags but different ! */
+};
+
+/* This structure represents an entry in a local netbios name list. */
+struct name_record {
+ struct name_record *prev, *next;
+ struct subnet_record *subnet;
+ struct nmb_name name; /* The netbios name. */
+ struct nmb_data data; /* The netbios data. */
+};
+
+/* Browser cache for synchronising browse lists. */
+struct browse_cache_record {
+ struct browse_cache_record *prev, *next;
+ unstring lmb_name;
+ unstring work_group;
+ struct in_addr ip;
+ time_t sync_time;
+ time_t death_time; /* The time the record must be removed. */
+};
+
+/* used for server information: client, nameserv and ipc */
+struct server_info_struct {
+ fstring name;
+ uint32_t type;
+ fstring comment;
+ fstring domain; /* used ONLY in ipc.c NOT namework.c */
+ bool server_added; /* used ONLY in ipc.c NOT namework.c */
+};
+
+/* This is used to hold the list of servers in my domain, and is
+ contained within lists of domains. */
+
+struct server_record {
+ struct server_record *next;
+ struct server_record *prev;
+
+ struct subnet_record *subnet;
+
+ struct server_info_struct serv;
+ time_t death_time;
+};
+
+/* A workgroup structure. It contains a list of servers. */
+struct work_record {
+ struct work_record *next;
+ struct work_record *prev;
+
+ struct subnet_record *subnet;
+
+ struct server_record *serverlist;
+
+ /* Stage of development from non-local-master up to local-master browser. */
+ enum master_state mst_state;
+
+ /* Stage of development from non-domain-master to domain-master browser. */
+ enum domain_state dom_state;
+
+ /* Stage of development from non-logon-server to logon server. */
+ enum logon_state log_state;
+
+ /* Work group info. */
+ unstring work_group;
+ int token; /* Used when communicating with backup browsers. */
+ unstring local_master_browser_name; /* Current local master browser. */
+
+ /* Announce info. */
+ time_t lastannounce_time;
+ int announce_interval;
+ bool needannounce;
+
+ /* Timeout time for this workgroup. 0 means permanent. */
+ time_t death_time;
+
+ /* Election info */
+ bool RunningElection;
+ bool needelection;
+ int ElectionCount;
+ uint32_t ElectionCriterion;
+
+ /* Domain master browser info. Used for efficient syncs. */
+ struct nmb_name dmb_name;
+ struct in_addr dmb_addr;
+};
+
+/* typedefs needed to define copy & free functions for userdata. */
+struct userdata_struct;
+
+typedef struct userdata_struct * (*userdata_copy_fn)(struct userdata_struct *);
+typedef void (*userdata_free_fn)(struct userdata_struct *);
+
+/* Structure to define any userdata passed around. */
+
+struct userdata_struct {
+ userdata_copy_fn copy_fn;
+ userdata_free_fn free_fn;
+ unsigned int userdata_len;
+ char data[16]; /* 16 is to ensure alignment/padding on all systems */
+};
+
+struct response_record;
+struct packet_struct;
+struct res_rec;
+
+/* typedef to define the function called when this response packet comes in. */
+typedef void (*response_function)(struct subnet_record *, struct response_record *,
+ struct packet_struct *);
+
+/* typedef to define the function called when this response record times out. */
+typedef void (*timeout_response_function)(struct subnet_record *,
+ struct response_record *);
+
+/* typedef to define the function called when the request that caused this
+ response record to be created is successful. */
+typedef void (*success_function)(struct subnet_record *, struct userdata_struct *, ...);
+
+/* typedef to define the function called when the request that caused this
+ response record to be created is unsuccessful. */
+typedef void (*fail_function)(struct subnet_record *, struct response_record *, ...);
+
+/* List of typedefs for success and fail functions of the different query
+ types. Used to catch any compile time prototype errors. */
+
+typedef void (*register_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ uint16_t,
+ int,
+ struct in_addr);
+typedef void (*register_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*release_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ struct in_addr);
+typedef void (*release_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*refresh_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ uint16_t,
+ int,
+ struct in_addr);
+typedef void (*refresh_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*query_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ struct in_addr,
+ struct res_rec *answers);
+
+typedef void (*query_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *,
+ int);
+
+typedef void (*node_status_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct res_rec *,
+ struct in_addr);
+typedef void (*node_status_fail_function)( struct subnet_record *,
+ struct response_record *);
+
+/* Initiated name queries are recorded in this list to track any responses. */
+
+struct response_record {
+ struct response_record *next;
+ struct response_record *prev;
+
+ uint16_t response_id;
+
+ /* Callbacks for packets received or not. */
+ response_function resp_fn;
+ timeout_response_function timeout_fn;
+
+ /* Callbacks for the request succeeding or not. */
+ success_function success_fn;
+ fail_function fail_fn;
+
+ struct packet_struct *packet;
+
+ struct userdata_struct *userdata;
+
+ int num_msgs;
+
+ time_t repeat_time;
+ time_t repeat_interval;
+ int repeat_count;
+
+ /* Recursion protection. */
+ bool in_expiration_processing;
+};
+
+/* A subnet structure. It contains a list of workgroups and netbios names. */
+
+/*
+ B nodes will have their own, totally separate subnet record, with their
+ own netbios name set. These do NOT interact with other subnet records'
+ netbios names.
+*/
+
+enum subnet_type {
+ NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
+ UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
+ REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
+ WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
+};
+
+struct subnet_record {
+ struct subnet_record *next;
+ struct subnet_record *prev;
+
+ char *subnet_name; /* For Debug identification. */
+ enum subnet_type type; /* To catagorize the subnet. */
+
+ struct work_record *workgrouplist; /* List of workgroups. */
+ struct name_record *namelist; /* List of netbios names. */
+ struct response_record *responselist; /* List of responses expected. */
+
+ bool namelist_changed;
+ bool work_changed;
+
+ struct in_addr bcast_ip;
+ struct in_addr mask_ip;
+ struct in_addr myip;
+ int nmb_sock; /* socket to listen for unicast 137. */
+ int nmb_bcast; /* socket to listen for broadcast 137. */
+ int dgram_sock; /* socket to listen for unicast 138. */
+ int dgram_bcast; /* socket to listen for broadcast 138. */
+};
+
+/* Broadcast packet announcement intervals, in minutes. */
+
+/* Attempt to add domain logon and domain master names. */
+#define CHECK_TIME_ADD_DOM_NAMES 5
+
+/* Search for master browsers of workgroups samba knows about,
+ except default. */
+#define CHECK_TIME_MST_BROWSE 5
+
+/* Request backup browser announcements from other servers. */
+#define CHECK_TIME_ANNOUNCE_BACKUP 15
+
+/* Request host announcements from other servers: min and max of interval. */
+#define CHECK_TIME_MIN_HOST_ANNCE 3
+#define CHECK_TIME_MAX_HOST_ANNCE 12
+
+/* Announce as master to WINS server and any Primary Domain Controllers. */
+#define CHECK_TIME_MST_ANNOUNCE 15
+
+/* Time between syncs from domain master browser to local master browsers. */
+#define CHECK_TIME_DMB_TO_LMB_SYNC 15
+
+/* Do all remote announcements this often. */
+#define REMOTE_ANNOUNCE_INTERVAL 180
+
+/* what is the maximum period between name refreshes. Note that this only
+ affects non-permanent self names (in seconds) */
+#define MAX_REFRESH_TIME (60*20)
+
+/* The Extinction interval: 4 days, time a node will stay in released state */
+#define EXTINCTION_INTERVAL (4*24*60*60)
+
+/* The Extinction time-out: 1 day, time a node will stay in deleted state */
+#define EXTINCTION_TIMEOUT (24*60*60)
+
+/* Macro's to enumerate subnets either with or without
+ the UNICAST subnet. */
+
+extern struct subnet_record *subnetlist;
+extern struct subnet_record *unicast_subnet;
+extern struct subnet_record *wins_server_subnet;
+extern struct subnet_record *remote_broadcast_subnet;
+
+#define FIRST_SUBNET subnetlist
+#define NEXT_SUBNET_EXCLUDING_UNICAST(x) ((x)->next)
+#define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
+
+/* wins replication record used between nmbd and wrepld */
+typedef struct _WINS_RECORD {
+ char name[17];
+ char type;
+ int nb_flags;
+ int wins_flags;
+ uint64_t id;
+ int num_ips;
+ struct in_addr ip[25];
+ struct in_addr wins_ip;
+} WINS_RECORD;
+
#include "nmbd/nmbd_proto.h"
#define NMBD_WAIT_INTERFACES_TIME_USEC (250 * 1000)
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index a1d8dee..1da3657 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -43,6 +43,7 @@ bool nmbd_init_packet_server(void)
status = nb_packet_server_create(
NULL, nmbd_event_context(),
+ global_nmbd_socket_dir(),
lp_parm_int(-1, "nmbd", "unexpected_clients", 200),
&packet_server);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
index 0724dd0..ed16278 100644
--- a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
+++ b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
@@ -50,7 +50,7 @@ static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
/* Called from qsort to compare two domain users in a dom_usr_t array
* for sorting by login time. Return >0 if usr1 login time was later
* than usr2 login time, <0 if it was earlier */
- return (usr1->login_time - usr2->login_time);
+ return NUMERIC_CMP(usr1->login_time, usr2->login_time);
}
/*******************************************************************
diff --git a/source3/script/tests/test_recycle.sh b/source3/script/tests/test_recycle.sh
index 8c9291f..ba1d0a5 100755
--- a/source3/script/tests/test_recycle.sh
+++ b/source3/script/tests/test_recycle.sh
@@ -90,11 +90,16 @@ quit
return 0
}
+panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG)
testit "recycle" \
test_recycle ||
failed=$((failed + 1))
+panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG)
+
+testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1)
+
#
# Cleanup.
do_cleanup
diff --git a/source3/script/tests/test_widelink_dfs_ci.sh b/source3/script/tests/test_widelink_dfs_ci.sh
new file mode 100755
index 0000000..6ae5cf5
--- /dev/null
+++ b/source3/script/tests/test_widelink_dfs_ci.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# regression test for dfs access with wide links enabled on dfs share
+# Ensure we still maintain case insensitivity.
+
+if [ $# -lt 7 ]; then
+ cat <<EOF
+Usage: test_widelink_dfs_ci.sh SERVER SERVER_IP SHARE USERNAME PASSWORD PREFIX SMBCLIENT <smbclient arguments>
+EOF
+ exit 1
+fi
+
+SERVER="$1"
+SERVER_IP="$2"
+SHARE="$3"
+USERNAME="$4"
+PASSWORD="$5"
+PREFIX="$6"
+SMBCLIENT="$7"
+shift 7
+ADDARGS="$@"
+
+incdir=$(dirname "$0")"/../../../testprogs/blackbox"
+. "$incdir/subunit.sh"
+. "$incdir/common_test_fns.inc"
+
+failed=0
+
+# Do not let deprecated option warnings muck this up
+SAMBA_DEPRECATED_SUPPRESS=1
+export SAMBA_DEPRECATED_SUPPRESS
+
+# Test chdir'ing into a lowercase directory with upper case.
+test_ci()
+{
+ tmpfile="$PREFIX/smbclient_ci_commands"
+
+ cat >"$tmpfile" <<EOF
+mkdir x
+cd X
+cd ..
+rmdir x
+quit
+EOF
+
+ cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share-wl -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
+ eval echo "$cmd"
+ out=$(eval "$cmd")
+ ret=$?
+ rm -f "$tmpfile"
+
+ if [ $ret != 0 ]; then
+ echo "$out"
+ echo "failed create x then chdir into X with error $ret"
+ return 1
+ fi
+
+ echo "$out" | grep 'NT_STATUS_'
+ ret="$?"
+ if [ "$ret" -eq 0 ]; then
+ echo "$out"
+ echo "Error create x then chdir into X"
+ return 1
+ fi
+ return 0
+}
+
+testit "creating a directory x and chdir into it" \
+ test_ci ||
+ failed=$((failed + 1))
+
+testok "$0" "$failed"
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 0901c24..0648797 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1808,6 +1808,17 @@ plantestsuite("samba3.blackbox.smbclient-bug15435",
smbclient3,
configuration])
+plantestsuite("samba3.blackbox.widelink_dfs_ci",
+ "fileserver",
+ [os.path.join(samba3srcdir, "script/tests/test_widelink_dfs_ci.sh"),
+ "$SERVER",
+ "$SERVER_IP",
+ "msdfs-share-wl",
+ "$USERNAME",
+ "$PASSWORD",
+ "$PREFIX",
+ smbclient3])
+
if have_cluster_support:
t = "readdir-timestamp"
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 6aad76a..42bb323 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -1312,6 +1312,24 @@ next:
}
if (fd == -1) {
+ /*
+ * vfs_widelink widelink_openat will update stat for fsp
+ * and return ELOOP for non-existing link, we can report
+ * the link here and let calling code decide what to do.
+ */
+ if ((errno == ELOOP) && S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+ status = create_open_symlink_err(mem_ctx,
+ dirfsp,
+ &rel_fname,
+ &symlink_err);
+ if (NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_STOPPED_ON_SYMLINK;
+ } else {
+ DBG_ERR("read_symlink_reparse failed: %s\n",
+ nt_errstr(status));
+ }
+ goto fail;
+ }
status = map_nt_error_from_unix(errno);
DBG_DEBUG("SMB_VFS_OPENAT() failed: %s\n",
strerror(errno));
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 4928d1f..a954499 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -522,6 +522,11 @@ struct smbXsrv_connection {
} smbtorture;
bool signing_mandatory;
+ /*
+ * This is ConstrainedConnection in MS-SMB2,
+ * but with reversed value...
+ */
+ bool got_authenticated_session;
} smb2;
};
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index afb86ab..5b83d4d 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -494,6 +494,17 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
goto inval;
}
+ if (!xconn->smb2.got_authenticated_session) {
+ D_INFO("Got SMB2_TRANSFORM header, "
+ "but not no authenticated session yet "
+ "client[%s] server[%s]\n",
+ tsocket_address_string(
+ xconn->remote_address, talloc_tos()),
+ tsocket_address_string(
+ xconn->local_address, talloc_tos()));
+ goto inval;
+ }
+
if (len < SMB2_TF_HDR_SIZE) {
DEBUG(1, ("%d bytes left, expected at least %d\n",
(int)len, SMB2_TF_HDR_SIZE));
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index ac71e55..d3b21ea 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -271,6 +271,13 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
/* we map anonymous to guest internally */
guest = true;
+ } else {
+ /*
+ * Remember we got one authenticated session on the connection
+ * in order to allow SMB3 decryption to happen
+ * (sadly even for future anonymous connections).
+ */
+ xconn->smb2.got_authenticated_session = true;
}
if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
@@ -288,7 +295,10 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
}
x->global->signing_algo = xconn->smb2.server.sign_algo;
x->global->encryption_cipher = xconn->smb2.server.cipher;
- if (guest) {
+ if (*out_session_flags & SMB2_SESSION_FLAG_IS_GUEST) {
+ /*
+ * A fallback to guest can't do any encryption
+ */
x->global->encryption_cipher = SMB2_ENCRYPTION_NONE;
}
@@ -642,6 +652,12 @@ static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
return NT_STATUS_LOGON_FAILURE;
}
+ /*
+ * Remember we got one authenticated session on the connection
+ * in order to allow SMB3 decryption to happen
+ */
+ xconn->smb2.got_authenticated_session = true;
+
*out_session_id = session->global->session_wire_id;
return NT_STATUS_OK;
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
index b228036..20d8967 100644
--- a/source3/smbd/smb2_tcon.c
+++ b/source3/smbd/smb2_tcon.c
@@ -331,6 +331,10 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
}
}
+ if (guest_session) {
+ /* make sure we don't ask for optional encryption */
+ encryption_desired = false;
+ }
if (encryption_desired) {
encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
}
diff --git a/source3/utils/conn_tdb.c b/source3/utils/conn_tdb.c
index 3724bd4..3f4ef00 100644
--- a/source3/utils/conn_tdb.c
+++ b/source3/utils/conn_tdb.c
@@ -27,6 +27,7 @@
#include "conn_tdb.h"
#include "util_tdb.h"
#include "lib/util/string_wrappers.h"
+#include "../libcli/security/session.h"
struct connections_forall_state {
struct db_context *session_by_pid;
@@ -44,7 +45,7 @@ struct connections_forall_session {
uint16_t cipher;
uint16_t dialect;
uint16_t signing;
- uint8_t signing_flags;
+ bool authenticated;
};
static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
@@ -56,6 +57,7 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
uint32_t id = global->session_global_id;
struct connections_forall_session sess;
+ enum security_user_level ul;
if (global->auth_session_info == NULL) {
sess.uid = -1;
@@ -69,7 +71,12 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
sess.cipher = global->channels[0].encryption_cipher;
sess.signing = global->channels[0].signing_algo;
sess.dialect = global->connection_dialect;
- sess.signing_flags = global->signing_flags;
+ ul = security_session_user_level(global->auth_session_info, NULL);
+ if (ul >= SECURITY_USER) {
+ sess.authenticated = true;
+ } else {
+ sess.authenticated = false;
+ }
status = dbwrap_store(state->session_by_pid,
make_tdb_data((void*)&id, sizeof(id)),
@@ -134,6 +141,7 @@ static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
data.dialect = sess.dialect;
data.signing = sess.signing;
data.signing_flags = global->signing_flags;
+ data.authenticated = sess.authenticated;
state->count++;
diff --git a/source3/utils/conn_tdb.h b/source3/utils/conn_tdb.h
index 2a6e04e..23a5e21 100644
--- a/source3/utils/conn_tdb.h
+++ b/source3/utils/conn_tdb.h
@@ -36,6 +36,7 @@ struct connections_data {
uint16_t dialect;
uint8_t signing_flags;
uint16_t signing;
+ bool authenticated;
};
/* The following definitions come from lib/conn_tdb.c */
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index d95a209..43fa026 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -521,6 +521,11 @@ static int net_ads_info_json(ADS_STRUCT *ads)
goto failure;
}
+ ret = json_add_string (&jsobj, "Workgroup", ads->config.workgroup);
+ if (ret != 0) {
+ goto failure;
+ }
+
ret = json_add_string (&jsobj, "Realm", ads->config.realm);
if (ret != 0) {
goto failure;
@@ -627,6 +632,7 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
d_printf(_("LDAP server: %s\n"), addr);
d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
+ d_printf(_("Workgroup: %s\n"), ads->config.workgroup);
d_printf(_("Realm: %s\n"), ads->config.realm);
d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
d_printf(_("LDAP port: %d\n"), ads->ldap.port);
diff --git a/source3/utils/net_registry.c b/source3/utils/net_registry.c
index 5d1314e..b47a8ff 100644
--- a/source3/utils/net_registry.c
+++ b/source3/utils/net_registry.c
@@ -1146,7 +1146,7 @@ static int registry_value_cmp(
if (v1->type == v2->type) {
return data_blob_cmp(&v1->data, &v2->data);
}
- return v1->type - v2->type;
+ return NUMERIC_CMP(v1->type, v2->type);
}
static WERROR precheck_create_val(struct precheck_ctx *ctx,
diff --git a/source3/utils/sharesec.c b/source3/utils/sharesec.c
index a6481e2..4175729 100644
--- a/source3/utils/sharesec.c
+++ b/source3/utils/sharesec.c
@@ -120,19 +120,19 @@ static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
return 0;
if (ace1->type != ace2->type)
- return ace2->type - ace1->type;
+ return NUMERIC_CMP(ace2->type, ace1->type);
if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
return dom_sid_compare(&ace1->trustee, &ace2->trustee);
if (ace1->flags != ace2->flags)
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
if (ace1->access_mask != ace2->access_mask)
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
if (ace1->size != ace2->size)
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
return memcmp(ace1, ace2, sizeof(struct security_ace));
}
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index e0591ac..5df7158 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -510,22 +510,23 @@ static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
return -1;
if ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) &&
(ace2->flags & SEC_ACE_FLAG_INHERITED_ACE))
- return ace1 - ace2;
-
- if (ace1->type != ace2->type)
- return ace2->type - ace1->type;
+ return NUMERIC_CMP(ace2->type, ace1->type);
+ if (ace1->type != ace2->type) {
+ /* note the reverse order */
+ return NUMERIC_CMP(ace2->type, ace1->type);
+ }
if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
return dom_sid_compare(&ace1->trustee, &ace2->trustee);
if (ace1->flags != ace2->flags)
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
if (ace1->access_mask != ace2->access_mask)
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
if (ace1->size != ace2->size)
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
return memcmp(ace1, ace2, sizeof(struct security_ace));
}
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 4102b41..02a5f6d 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -483,9 +483,33 @@ static int traverse_connections_stdout(struct traverse_state *state,
char *server_id,
const char *machine,
const char *timestr,
- const char *encryption,
- const char *signing)
+ const char *encryption_cipher,
+ enum crypto_degree encryption_degree,
+ const char *signing_cipher,
+ enum crypto_degree signing_degree)
{
+ fstring encryption;
+ fstring signing;
+
+ if (encryption_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
+ } else {
+ fstr_sprintf(encryption, "-");
+ }
+ if (signing_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(signing, "partial(%s)", signing_cipher);
+ } else {
+ fstr_sprintf(signing, "-");
+ }
+
d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
servicename, server_id, machine, timestr, encryption, signing);
@@ -538,7 +562,9 @@ static int traverse_connections(const struct connections_data *crec,
return -1;
}
- if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ if (smbXsrv_is_encrypted(crec->encryption_flags) ||
+ smbXsrv_is_partially_encrypted(crec->encryption_flags))
+ {
switch (crec->cipher) {
case SMB_ENCRYPTION_GSSAPI:
encryption = "GSSAPI";
@@ -549,14 +575,31 @@ static int traverse_connections(const struct connections_data *crec,
case SMB2_ENCRYPTION_AES128_GCM:
encryption = "AES-128-GCM";
break;
+ case SMB2_ENCRYPTION_AES256_CCM:
+ encryption = "AES-256-CCM";
+ break;
+ case SMB2_ENCRYPTION_AES256_GCM:
+ encryption = "AES-256-GCM";
+ break;
default:
encryption = "???";
break;
}
- encryption_degree = CRYPTO_DEGREE_FULL;
+ if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
- if (smbXsrv_is_signed(crec->signing_flags)) {
+ if (smbXsrv_is_signed(crec->signing_flags) ||
+ smbXsrv_is_partially_signed(crec->signing_flags))
+ {
switch (crec->signing) {
case SMB2_SIGNING_MD5_SMB1:
signing = "HMAC-MD5";
@@ -574,7 +617,16 @@ static int traverse_connections(const struct connections_data *crec,
signing = "???";
break;
}
- signing_degree = CRYPTO_DEGREE_FULL;
+ if (smbXsrv_is_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
if (!state->json_output) {
@@ -584,7 +636,9 @@ static int traverse_connections(const struct connections_data *crec,
crec->machine,
timestr,
encryption,
- signing);
+ encryption_degree,
+ signing,
+ signing_degree);
} else {
result = traverse_connections_json(state,
crec,
@@ -615,6 +669,8 @@ static int traverse_sessionid_stdout(struct traverse_state *state,
if (encryption_degree == CRYPTO_DEGREE_FULL) {
fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
} else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
} else {
@@ -622,6 +678,8 @@ static int traverse_sessionid_stdout(struct traverse_state *state,
}
if (signing_degree == CRYPTO_DEGREE_FULL) {
fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
} else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
fstr_sprintf(signing, "partial(%s)", signing_cipher);
} else {
@@ -756,6 +814,11 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
encryption_degree = CRYPTO_DEGREE_PARTIAL;
}
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
if (smbXsrv_is_signed(session->signing_flags) ||
@@ -783,6 +846,11 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
signing_degree = CRYPTO_DEGREE_PARTIAL;
}
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
diff --git a/source3/utils/status.h b/source3/utils/status.h
index c08aba4..6674f0d 100644
--- a/source3/utils/status.h
+++ b/source3/utils/status.h
@@ -38,6 +38,7 @@ struct traverse_state {
enum crypto_degree {
CRYPTO_DEGREE_NONE,
CRYPTO_DEGREE_PARTIAL,
+ CRYPTO_DEGREE_ANONYMOUS,
CRYPTO_DEGREE_FULL
};
diff --git a/source3/utils/status_json.c b/source3/utils/status_json.c
index ee24a3b..f558c91 100644
--- a/source3/utils/status_json.c
+++ b/source3/utils/status_json.c
@@ -258,6 +258,8 @@ static int add_crypto_to_json(struct json_object *parent_json,
if (degree == CRYPTO_DEGREE_NONE) {
degree_str = "none";
+ } else if (degree == CRYPTO_DEGREE_ANONYMOUS) {
+ degree_str = "anonymous";
} else if (degree == CRYPTO_DEGREE_PARTIAL) {
degree_str = "partial";
} else {
diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index 5c9fe07..b800282 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");
diff --git a/source3/wscript_build b/source3/wscript_build
index ff8de1e..3fcdb55 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -901,6 +901,7 @@ bld.SAMBA3_SUBSYSTEM('LIBNMB',
LIBTSOCKET
LIBCLI_NETLOGON
samba3util
+ smbconf
addns
lmhosts
resolv
diff --git a/source4/dns_server/dns_crypto.c b/source4/dns_server/dns_crypto.c
index be79a4e..d30e971 100644
--- a/source4/dns_server/dns_crypto.c
+++ b/source4/dns_server/dns_crypto.c
@@ -27,6 +27,7 @@
#include "libcli/util/ntstatus.h"
#include "auth/auth.h"
#include "auth/gensec/gensec.h"
+#include "lib/util/bytearray.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_DNS
@@ -106,7 +107,7 @@ WERROR dns_verify_tsig(struct dns_server *dns,
struct dns_server_tkey *tkey = NULL;
struct dns_fake_tsig_rec *check_rec = talloc_zero(mem_ctx,
struct dns_fake_tsig_rec);
-
+ const char *algorithm = NULL;
/* Find the first TSIG record in the additional records */
for (i=0; i < packet->arcount; i++) {
@@ -145,7 +146,7 @@ WERROR dns_verify_tsig(struct dns_server *dns,
tkey = dns_find_tkey(dns->tkeys, state->tsig->name);
if (tkey == NULL) {
- DBG_DEBUG("dns_find_tkey() => NOTAUTH / DNS_RCODE_BADKEY\n");
+ DBG_DEBUG("dns_find_tkey() => REFUSED / DNS_RCODE_BADKEY\n");
/*
* We must save the name for use in the TSIG error
* response and have no choice here but to save the
@@ -157,10 +158,20 @@ WERROR dns_verify_tsig(struct dns_server *dns,
return WERR_NOT_ENOUGH_MEMORY;
}
state->tsig_error = DNS_RCODE_BADKEY;
- return DNS_ERR(NOTAUTH);
+ return DNS_ERR(REFUSED);
}
DBG_DEBUG("dns_find_tkey() => found\n");
+ algorithm = state->tsig->rdata.tsig_record.algorithm_name;
+ if (strcmp(algorithm, "gss-tsig") == 0) {
+ /* ok */
+ } else if (strcmp(algorithm, "gss.microsoft.com") == 0) {
+ /* ok */
+ } else {
+ state->tsig_error = DNS_RCODE_BADKEY;
+ return DNS_ERR(REFUSED);
+ }
+
/*
* Remember the keyname that found an existing tkey, used
* later to fetch the key with dns_find_tkey() when signing
@@ -183,7 +194,7 @@ WERROR dns_verify_tsig(struct dns_server *dns,
}
check_rec->rr_class = DNS_QCLASS_ANY;
check_rec->ttl = 0;
- check_rec->algorithm_name = talloc_strdup(check_rec, tkey->algorithm);
+ check_rec->algorithm_name = talloc_strdup(check_rec, algorithm);
if (check_rec->algorithm_name == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
@@ -239,7 +250,7 @@ WERROR dns_verify_tsig(struct dns_server *dns,
dump_data_dbgc(DBGC_DNS, 8, buffer, buffer_len);
DBG_NOTICE("Verifying tsig failed: %s\n", nt_errstr(status));
state->tsig_error = DNS_RCODE_BADSIG;
- return DNS_ERR(NOTAUTH);
+ return DNS_ERR(REFUSED);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -271,11 +282,19 @@ static WERROR dns_tsig_compute_mac(TALLOC_CTX *mem_ctx,
struct dns_fake_tsig_rec *check_rec = talloc_zero(mem_ctx,
struct dns_fake_tsig_rec);
size_t mac_size = 0;
+ bool gss_tsig;
if (check_rec == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
+ if (strcmp(tkey->algorithm, "gss-tsig") == 0) {
+ gss_tsig = true;
+ } else {
+ /* gss.microsoft.com */
+ gss_tsig = false;
+ }
+
/* first build and verify check packet */
check_rec->name = talloc_strdup(check_rec, tkey->name);
if (check_rec->name == NULL) {
@@ -315,6 +334,9 @@ static WERROR dns_tsig_compute_mac(TALLOC_CTX *mem_ctx,
}
buffer_len = mac_size;
+ if (gss_tsig && mac_size > 0) {
+ buffer_len += 2;
+ }
buffer_len += packet_blob.length;
if (buffer_len < packet_blob.length) {
@@ -335,11 +357,21 @@ static WERROR dns_tsig_compute_mac(TALLOC_CTX *mem_ctx,
/*
* RFC 2845 "4.2 TSIG on Answers", how to lay out the buffer
* that we're going to sign:
- * 1. MAC of request (if present)
+ * 1. if MAC of request is present
+ * - 16bit big endian length of MAC of request
+ * - MAC of request
* 2. Outgoing packet
* 3. TSIG record
*/
if (mac_size > 0) {
+ if (gss_tsig) {
+ /*
+ * only gss-tsig not with
+ * gss.microsoft.com
+ */
+ PUSH_BE_U16(p, 0, mac_size);
+ p += 2;
+ }
memcpy(p, state->tsig->rdata.tsig_record.mac, mac_size);
p += mac_size;
}
@@ -372,6 +404,7 @@ WERROR dns_sign_tsig(struct dns_server *dns,
.data = NULL,
.length = 0
};
+ const char *algorithm = "gss-tsig";
tsig = talloc_zero(mem_ctx, struct dns_res_rec);
if (tsig == NULL) {
@@ -392,6 +425,8 @@ WERROR dns_sign_tsig(struct dns_server *dns,
if (!W_ERROR_IS_OK(werror)) {
return werror;
}
+
+ algorithm = tkey->algorithm;
}
tsig->name = talloc_strdup(tsig, state->key_name);
@@ -402,7 +437,7 @@ WERROR dns_sign_tsig(struct dns_server *dns,
tsig->rr_type = DNS_QTYPE_TSIG;
tsig->ttl = 0;
tsig->length = UINT16_MAX;
- tsig->rdata.tsig_record.algorithm_name = talloc_strdup(tsig, "gss-tsig");
+ tsig->rdata.tsig_record.algorithm_name = talloc_strdup(tsig, algorithm);
if (tsig->rdata.tsig_record.algorithm_name == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 181beda..1f46ee0 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -663,8 +663,17 @@ static NTSTATUS create_tkey(struct dns_server *dns,
{
NTSTATUS status;
struct dns_server_tkey_store *store = dns->tkeys;
- struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey);
+ struct dns_server_tkey *k = NULL;
+
+ if (strcmp(algorithm, "gss-tsig") == 0) {
+ /* ok */
+ } else if (strcmp(algorithm, "gss.microsoft.com") == 0) {
+ /* ok */
+ } else {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ k = talloc_zero(store, struct dns_server_tkey);
if (k == NULL) {
return NT_STATUS_NO_MEMORY;
}
@@ -790,12 +799,22 @@ static WERROR handle_tkey(struct dns_server *dns,
{
struct dns_res_rec *in_tkey = NULL;
struct dns_res_rec *ret_tkey;
- uint16_t i;
- for (i = 0; i < in->arcount; i++) {
+ /*
+ * TKEY needs to we the last one in
+ * additional or answers
+ */
+ if (in->arcount >= 1) {
+ uint16_t i = in->arcount - 1;
if (in->additional[i].rr_type == DNS_QTYPE_TKEY) {
in_tkey = &in->additional[i];
- break;
+ }
+ } else if (in->nscount >= 1) {
+ /* no lookup */
+ } else if (in->ancount >= 1) {
+ uint16_t i = in->ancount - 1;
+ if (in->answers[i].rr_type == DNS_QTYPE_TKEY) {
+ in_tkey = &in->answers[i];
}
}
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
index 4d2ee0b..1285111 100644
--- a/source4/dns_server/dns_update.c
+++ b/source4/dns_server/dns_update.c
@@ -570,6 +570,8 @@ static WERROR handle_one_update(struct dns_server *dns,
W_ERROR_NOT_OK_RETURN(werror);
for (i = first; i < rcount; i++) {
+ struct dnsp_DnssrvRpcRecord orig_rec = recs[i];
+
if (!dns_record_match(&recs[i], &recs[rcount])) {
continue;
}
@@ -583,6 +585,15 @@ static WERROR handle_one_update(struct dns_server *dns,
werror = dns_replace_records(dns, mem_ctx, dn,
needs_add, recs, rcount);
DBG_DEBUG("dns_replace_records(REPLACE): %s\n", win_errstr(werror));
+ if (W_ERROR_EQUAL(werror, WERR_ACCESS_DENIED) &&
+ !needs_add &&
+ orig_rec.dwTtlSeconds == recs[i].dwTtlSeconds)
+ {
+ DBG_NOTICE("dns_replace_records(REPLACE): %s "
+ "=> skip no-op\n",
+ win_errstr(werror));
+ werror = WERR_OK;
+ }
W_ERROR_NOT_OK_RETURN(werror);
return WERR_OK;
diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c
index aba7f41..88aed2e 100644
--- a/source4/dns_server/dnsserver_common.c
+++ b/source4/dns_server/dnsserver_common.c
@@ -68,6 +68,8 @@ uint8_t werr_to_dns_err(WERROR werr)
return DNS_RCODE_NOTZONE;
} else if (W_ERROR_EQUAL(DNS_ERR(BADKEY), werr)) {
return DNS_RCODE_BADKEY;
+ } else if (W_ERROR_EQUAL(WERR_ACCESS_DENIED, werr)) {
+ return DNS_RCODE_REFUSED;
}
DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr)));
return DNS_RCODE_SERVFAIL;
@@ -642,7 +644,7 @@ static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1,
* The records are sorted with higher types first,
* which puts tombstones (type 0) last.
*/
- return r2->wType - r1->wType;
+ return NUMERIC_CMP(r2->wType, r1->wType);
}
/*
* Then we need to sort from the oldest to newest timestamp.
@@ -650,7 +652,7 @@ static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1,
* Note that dwTimeStamp == 0 (never expiring) records come first,
* then the ones whose expiry is soonest.
*/
- return r1->dwTimeStamp - r2->dwTimeStamp;
+ return NUMERIC_CMP(r1->dwTimeStamp, r2->dwTimeStamp);
}
/*
@@ -1408,7 +1410,7 @@ static int dns_common_sort_zones(struct ldb_message **m1, struct ldb_message **m
/* If the string lengths are not equal just sort by length */
if (l1 != l2) {
/* If m1 is the larger zone name, return it first */
- return l2 - l1;
+ return NUMERIC_CMP(l2, l1);
}
/*TODO: We need to compare DNs here, we want the DomainDNSZones first */
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index d46b19e..7ba5c79 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -1043,7 +1043,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
if (W_ERROR_EQUAL(status, WERR_DS_DRA_SCHEMA_MISMATCH)) {
struct dreplsrv_partition *p;
- bool ok;
+ struct tevent_req *subreq = NULL;
if (was_schema) {
nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
@@ -1141,12 +1141,15 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
state->retry_started = true;
- ok = dreplsrv_op_pull_source_detect_schema_cycle(req);
- if (!ok) {
+ subreq = dreplsrv_out_drsuapi_send(state,
+ state->ev,
+ state->op->source_dsa->conn);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
-
- dreplsrv_op_pull_source_get_changes_trigger(req);
+ tevent_req_set_callback(subreq,
+ dreplsrv_op_pull_source_connect_done,
+ req);
return;
} else if (!W_ERROR_IS_OK(status)) {
@@ -1205,10 +1208,21 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
* operation once we are done.
*/
if (state->source_dsa_retry != NULL) {
+ struct tevent_req *subreq = NULL;
+
state->op->source_dsa = state->source_dsa_retry;
state->op->extended_op = state->extended_op_retry;
state->source_dsa_retry = NULL;
- dreplsrv_op_pull_source_get_changes_trigger(req);
+
+ subreq = dreplsrv_out_drsuapi_send(state,
+ state->ev,
+ state->op->source_dsa->conn);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ dreplsrv_op_pull_source_connect_done,
+ req);
return;
}
diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c
index 1317b58..20613a7 100644
--- a/source4/dsdb/samdb/ldb_modules/operational.c
+++ b/source4/dsdb/samdb/ldb_modules/operational.c
@@ -1070,7 +1070,7 @@ static int pso_compare(struct ldb_message **m1, struct ldb_message **m2)
return ndr_guid_compare(&guid1, &guid2);
} else {
- return prec1 - prec2;
+ return NUMERIC_CMP(prec1, prec2);
}
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 7aec006..2790679 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -1063,16 +1063,21 @@ static int replmd_ldb_message_element_attid_sort(const struct ldb_message_elemen
a2 = dsdb_attribute_by_lDAPDisplayName(schema, e2->name);
/*
- * TODO: remove this check, we should rely on e1 and e2 having valid attribute names
- * in the schema
+ * If the elements do not have valid attribute names in the schema
+ * (which we would prefer to think can't happen), we need to sort them
+ * somehow. The current strategy is to put them at the end, sorted by
+ * attribute name.
*/
- if (!a1 || !a2) {
+ if (a1 == NULL && a2 == NULL) {
return strcasecmp(e1->name, e2->name);
}
- if (a1->attributeID_id == a2->attributeID_id) {
- return 0;
+ if (a1 == NULL) {
+ return 1;
+ }
+ if (a2 == NULL) {
+ return -1;
}
- return a1->attributeID_id > a2->attributeID_id ? 1 : -1;
+ return NUMERIC_CMP(a1->attributeID_id, a2->attributeID_id);
}
static void replmd_ldb_message_sort(struct ldb_message *msg,
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
index 398091c..8b90e7f 100644
--- a/source4/dsdb/schema/schema_set.c
+++ b/source4/dsdb/schema/schema_set.c
@@ -478,19 +478,13 @@ static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_
TALLOC_FREE(frame);
}
-static int uint32_cmp(uint32_t c1, uint32_t c2)
-{
- if (c1 == c2) return 0;
- return c1 > c2 ? 1 : -1;
-}
-
static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2)
{
return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName);
}
static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2)
{
- return uint32_cmp((*c1)->governsID_id, (*c2)->governsID_id);
+ return NUMERIC_CMP((*c1)->governsID_id, (*c2)->governsID_id);
}
static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2)
{
@@ -507,11 +501,11 @@ static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1,
}
static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
- return uint32_cmp((*a1)->attributeID_id, (*a2)->attributeID_id);
+ return NUMERIC_CMP((*a1)->attributeID_id, (*a2)->attributeID_id);
}
static int dsdb_compare_attribute_by_msDS_IntId(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
- return uint32_cmp((*a1)->msDS_IntId, (*a2)->msDS_IntId);
+ return NUMERIC_CMP((*a1)->msDS_IntId, (*a2)->msDS_IntId);
}
static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
@@ -519,7 +513,7 @@ static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1,
}
static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
- return uint32_cmp((*a1)->linkID, (*a2)->linkID);
+ return NUMERIC_CMP((*a1)->linkID, (*a2)->linkID);
}
static int dsdb_compare_attribute_by_cn(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
{
diff --git a/source4/libcli/dgram/dgramsocket.c b/source4/libcli/dgram/dgramsocket.c
index 154a667..2a98792 100644
--- a/source4/libcli/dgram/dgramsocket.c
+++ b/source4/libcli/dgram/dgramsocket.c
@@ -90,6 +90,10 @@ static void dgm_socket_recv(struct nbt_dgram_socket *dgmsock)
dgmslot->handler(dgmslot, packet, src);
} else {
DEBUG(2,("No mailslot handler for '%s'\n", mailslot_name));
+ /* dispatch if there is a general handler */
+ if (dgmsock->incoming.handler) {
+ dgmsock->incoming.handler(dgmsock, packet, src);
+ }
}
} else {
/* dispatch if there is a general handler */
@@ -205,6 +209,38 @@ NTSTATUS dgram_set_incoming_handler(struct nbt_dgram_socket *dgmsock,
return NT_STATUS_OK;
}
+NTSTATUS nbt_dgram_send_raw(struct nbt_dgram_socket *dgmsock,
+ struct socket_address *dest,
+ const DATA_BLOB pkt_blob)
+{
+ struct nbt_dgram_request *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ req = talloc(dgmsock, struct nbt_dgram_request);
+ if (req == NULL) {
+ goto failed;
+ }
+
+ req->dest = socket_address_copy(req, dest);
+ if (req->dest == NULL) {
+ goto failed;
+ }
+
+ req->encoded = data_blob_dup_talloc(req, pkt_blob);
+ if (req->encoded.length != pkt_blob.length) {
+ goto failed;
+ }
+
+ DLIST_ADD_END(dgmsock->send_queue, req);
+
+ TEVENT_FD_WRITEABLE(dgmsock->fde);
+
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(req);
+ return status;
+}
/*
queue a datagram for send
@@ -220,8 +256,8 @@ NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock,
req = talloc(dgmsock, struct nbt_dgram_request);
if (req == NULL) goto failed;
- req->dest = dest;
- if (talloc_reference(req, dest) == NULL) goto failed;
+ req->dest = socket_address_copy(req, dest);
+ if (req->dest == NULL) goto failed;
ndr_err = ndr_push_struct_blob(&req->encoded, req, packet,
(ndr_push_flags_fn_t)ndr_push_nbt_dgram_packet);
diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h
index 0f313a6..7e57a94 100644
--- a/source4/libcli/dgram/libdgram.h
+++ b/source4/libcli/dgram/libdgram.h
@@ -83,6 +83,9 @@ struct dgram_mailslot_handler {
/* prototypes */
+NTSTATUS nbt_dgram_send_raw(struct nbt_dgram_socket *dgmsock,
+ struct socket_address *dest,
+ const DATA_BLOB pkt_blob);
NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock,
struct nbt_dgram_packet *packet,
struct socket_address *dest);
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index e94512d..322a7bd 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -385,7 +385,9 @@ static void smb2_session_setup_spnego_both_ready(struct tevent_req *req)
return;
}
- if (cli_credentials_is_anonymous(state->credentials)) {
+ if (cli_credentials_is_anonymous(state->credentials) &&
+ !state->session->anonymous_session_key)
+ {
/*
* Windows server does not set the
* SMB2_SESSION_FLAG_IS_GUEST nor
@@ -399,10 +401,14 @@ static void smb2_session_setup_spnego_both_ready(struct tevent_req *req)
return;
}
- status = gensec_session_key(session->gensec, state,
- &session_key);
- if (tevent_req_nterror(req, status)) {
- return;
+ if (state->session->forced_session_key.length != 0) {
+ session_key = state->session->forced_session_key;
+ } else {
+ status = gensec_session_key(session->gensec, state,
+ &session_key);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
}
if (state->session_bind) {
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index 88e651a..1e2f185 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -128,6 +128,8 @@ struct smb2_session {
struct gensec_security *gensec;
struct smbXcli_session *smbXcli;
bool needs_bind;
+ bool anonymous_session_key;
+ DATA_BLOB forced_session_key;
};
diff --git a/source4/nbt_server/dgram/request.c b/source4/nbt_server/dgram/request.c
index ea2b6e8..7614514 100644
--- a/source4/nbt_server/dgram/request.c
+++ b/source4/nbt_server/dgram/request.c
@@ -27,6 +27,11 @@
#include "nbt_server/dgram/proto.h"
#include "librpc/gen_ndr/ndr_nbt.h"
#include "param/param.h"
+#include "lib/util/util_str_escape.h"
+#include "lib/util/util_net.h"
+#include "../source3/include/fstring.h"
+#include "../source3/libsmb/nmblib.h"
+#include "../source3/libsmb/unexpected.h"
/*
a list of mailslots that we have static handlers for
@@ -51,8 +56,55 @@ void dgram_request_handler(struct nbt_dgram_socket *dgmsock,
struct nbt_dgram_packet *packet,
struct socket_address *src)
{
- DEBUG(0,("General datagram request from %s:%d\n", src->addr, src->port));
- NDR_PRINT_DEBUG(nbt_dgram_packet, packet);
+ struct nbtd_interface *iface =
+ talloc_get_type_abort(dgmsock->incoming.private_data,
+ struct nbtd_interface);
+ struct nbtd_server *nbtsrv = iface->nbtsrv;
+ const char *mailslot_name = NULL;
+ struct packet_struct *pstruct = NULL;
+ DATA_BLOB blob = { .length = 0, };
+ enum ndr_err_code ndr_err;
+
+ mailslot_name = dgram_mailslot_name(packet);
+ if (mailslot_name != NULL) {
+ DBG_DEBUG("Unexpected mailslot[%s] datagram request from %s:%d\n",
+ log_escape(packet, mailslot_name),
+ src->addr, src->port);
+ } else {
+ DBG_DEBUG("Unexpected general datagram request from %s:%d\n",
+ src->addr, src->port);
+ }
+
+ if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+ NDR_PRINT_DEBUG(nbt_dgram_packet, packet);
+ }
+
+ /*
+ * For now we only pass DGRAM_DIRECT_UNIQUE
+ * messages via nb_packet_dispatch() to
+ * nbtsrv->unexpected_server
+ */
+ if (packet->msg_type != DGRAM_DIRECT_UNIQUE) {
+ return;
+ }
+
+ ndr_err = ndr_push_struct_blob(&blob, packet, packet,
+ (ndr_push_flags_fn_t)ndr_push_nbt_dgram_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_ERR("ndr_push_nbt_dgram_packet - %s\n",
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ pstruct = parse_packet((char *)blob.data,
+ blob.length,
+ DGRAM_PACKET,
+ interpret_addr2(src->addr),
+ src->port);
+ if (pstruct != NULL) {
+ nb_packet_dispatch(nbtsrv->unexpected_server, pstruct);
+ free_packet(pstruct);
+ }
}
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
index b946a1d..0888c1b 100644
--- a/source4/nbt_server/interfaces.c
+++ b/source4/nbt_server/interfaces.c
@@ -31,6 +31,9 @@
#include "param/param.h"
#include "lib/util/util_net.h"
#include "lib/util/idtree.h"
+#include "../source3/include/fstring.h"
+#include "../source3/libsmb/nmblib.h"
+#include "../source3/libsmb/unexpected.h"
/*
receive an incoming request and dispatch it to the right place
@@ -115,7 +118,33 @@ static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
}
if (!req) {
+ struct packet_struct *pstruct = NULL;
+ DATA_BLOB blob = { .length = 0, };
+ enum ndr_err_code ndr_err;
+
+ /*
+ * Here we have NBT_FLAG_REPLY
+ */
DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
+
+ ndr_err = ndr_push_struct_blob(&blob, packet, packet,
+ (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_ERR("ndr_push_nbt_name_packet - %s\n",
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ pstruct = parse_packet((char *)blob.data,
+ blob.length,
+ NMB_PACKET,
+ interpret_addr2(src->addr),
+ src->port);
+ if (pstruct != NULL) {
+ nb_packet_dispatch(nbtsrv->unexpected_server, pstruct);
+ free_packet(pstruct);
+ }
+
return;
}
diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c
index 6d28bbd..c3f9fac 100644
--- a/source4/nbt_server/nbt_server.c
+++ b/source4/nbt_server/nbt_server.c
@@ -29,9 +29,113 @@
#include "auth/auth.h"
#include "dsdb/samdb/samdb.h"
#include "param/param.h"
+#include "dynconfig/dynconfig.h"
+#include "lib/util/pidfile.h"
+#include "lib/util/util_net.h"
+#include "lib/socket/socket.h"
+#include "../source3/include/fstring.h"
+#include "../source3/libsmb/nmblib.h"
+#include "../source3/libsmb/unexpected.h"
+#include "../source3/lib/util_procid.h"
NTSTATUS server_service_nbtd_init(TALLOC_CTX *);
+static void nbtd_server_msg_send_packet(struct imessaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id src,
+ size_t num_fds,
+ int *fds,
+ DATA_BLOB *data)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct nbtd_server *nbtsrv =
+ talloc_get_type_abort(private_data,
+ struct nbtd_server);
+ struct packet_struct *p = (struct packet_struct *)data->data;
+ struct sockaddr_storage ss;
+ struct socket_address *dst = NULL;
+ struct nbtd_interface *iface = NULL;
+ char buf[1024] = { 0, };
+ DATA_BLOB blob = { .length = 0, };
+
+ DBG_DEBUG("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src));
+
+ if (data->length != sizeof(struct packet_struct)) {
+ DBG_WARNING("Discarding invalid packet length from %u\n",
+ (unsigned int)procid_to_pid(&src));
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ if ((p->packet_type != NMB_PACKET) &&
+ (p->packet_type != DGRAM_PACKET)) {
+ DBG_WARNING("Discarding invalid packet type from %u: %d\n",
+ (unsigned int)procid_to_pid(&src), p->packet_type);
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ if (p->packet_type == DGRAM_PACKET) {
+ p->port = 138;
+ }
+
+ in_addr_to_sockaddr_storage(&ss, p->ip);
+ dst = socket_address_from_sockaddr_storage(frame, &ss, p->port);
+ if (dst == NULL) {
+ TALLOC_FREE(frame);
+ return;
+ }
+ if (p->port == 0) {
+ DBG_WARNING("Discarding packet with missing port for addr[%s] "
+ "from %u\n",
+ dst->addr, (unsigned int)procid_to_pid(&src));
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ iface = nbtd_find_request_iface(nbtsrv, dst->addr, true);
+ if (iface == NULL) {
+ DBG_WARNING("Could not find iface for packet to addr[%s] "
+ "from %u\n",
+ dst->addr, (unsigned int)procid_to_pid(&src));
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ p->recv_fd = -1;
+ p->send_fd = -1;
+
+ if (p->packet_type == DGRAM_PACKET) {
+ p->packet.dgram.header.source_ip.s_addr = interpret_addr(iface->ip_address);
+ p->packet.dgram.header.source_port = 138;
+ }
+
+ blob.length = build_packet(buf, sizeof(buf), p);
+ if (blob.length == 0) {
+ TALLOC_FREE(frame);
+ return;
+ }
+ blob.data = (uint8_t *)buf;
+
+ if (p->packet_type == DGRAM_PACKET) {
+ nbt_dgram_send_raw(iface->dgmsock, dst, blob);
+ } else {
+ nbt_name_send_raw(iface->nbtsock, dst, blob);
+ }
+
+ TALLOC_FREE(frame);
+}
+
+static int nbtd_server_destructor(struct nbtd_server *nbtsrv)
+{
+ struct task_server *task = nbtsrv->task;
+
+ pidfile_unlink(lpcfg_pid_directory(task->lp_ctx), "nmbd");
+
+ return 0;
+}
+
/*
startup the nbtd task
*/
@@ -40,6 +144,8 @@ static NTSTATUS nbtd_task_init(struct task_server *task)
struct nbtd_server *nbtsrv;
NTSTATUS status;
struct interface *ifaces;
+ const char *nmbd_socket_dir = NULL;
+ int unexpected_clients;
load_interface_list(task, task->lp_ctx, &ifaces);
@@ -66,6 +172,8 @@ static NTSTATUS nbtd_task_init(struct task_server *task)
nbtsrv->bcast_interface = NULL;
nbtsrv->wins_interface = NULL;
+ talloc_set_destructor(nbtsrv, nbtd_server_destructor);
+
/* start listening on the configured network interfaces */
status = nbtd_startup_interfaces(nbtsrv, task->lp_ctx, ifaces);
if (!NT_STATUS_IS_OK(status)) {
@@ -73,6 +181,30 @@ static NTSTATUS nbtd_task_init(struct task_server *task)
return status;
}
+ nmbd_socket_dir = lpcfg_parm_string(task->lp_ctx,
+ NULL,
+ "nmbd",
+ "socket dir");
+ if (nmbd_socket_dir == NULL) {
+ nmbd_socket_dir = get_dyn_NMBDSOCKETDIR();
+ }
+
+ unexpected_clients = lpcfg_parm_int(task->lp_ctx,
+ NULL,
+ "nmbd",
+ "unexpected_clients",
+ 200);
+
+ status = nb_packet_server_create(nbtsrv,
+ nbtsrv->task->event_ctx,
+ nmbd_socket_dir,
+ unexpected_clients,
+ &nbtsrv->unexpected_server);
+ if (!NT_STATUS_IS_OK(status)) {
+ task_server_terminate(task, "nbtd failed to start unexpected_server", true);
+ return status;
+ }
+
nbtsrv->sam_ctx = samdb_connect(nbtsrv,
task->event_ctx,
task->lp_ctx,
@@ -93,11 +225,22 @@ static NTSTATUS nbtd_task_init(struct task_server *task)
nbtd_register_irpc(nbtsrv);
+ status = imessaging_register(task->msg_ctx,
+ nbtsrv,
+ MSG_SEND_PACKET,
+ nbtd_server_msg_send_packet);
+ if (!NT_STATUS_IS_OK(status)) {
+ task_server_terminate(task, "nbtd failed imessaging_register(MSG_SEND_PACKET)", true);
+ return status;
+ }
+
/* start the process of registering our names on all interfaces */
nbtd_register_names(nbtsrv);
irpc_add_name(task->msg_ctx, "nbt_server");
+ pidfile_create(lpcfg_pid_directory(task->lp_ctx), "nmbd");
+
return NT_STATUS_OK;
}
diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h
index c80e5bf..cbad3e9 100644
--- a/source4/nbt_server/nbt_server.h
+++ b/source4/nbt_server/nbt_server.h
@@ -78,6 +78,8 @@ struct nbtd_server {
struct nbtd_statistics stats;
struct ldb_context *sam_ctx;
+
+ struct nb_packet_server *unexpected_server;
};
diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c
index 2a05e96..7df40c3 100644
--- a/source4/nbt_server/wins/winsdb.c
+++ b/source4/nbt_server/wins/winsdb.c
@@ -32,6 +32,7 @@
#include "lib/socket/netif.h"
#include "param/param.h"
#include "lib/util/smb_strtox.h"
+#include "lib/util/tsort.h"
#undef strcasecmp
@@ -349,7 +350,7 @@ static int winsdb_addr_sort_list (struct winsdb_addr **p1, struct winsdb_addr **
* then the replica addresses with the newest to the oldest address
*/
if (a2->expire_time != a1->expire_time) {
- return a2->expire_time - a1->expire_time;
+ return NUMERIC_CMP(a2->expire_time, a1->expire_time);
}
if (strcmp(a2->wins_owner, h->local_owner) == 0) {
@@ -360,7 +361,7 @@ static int winsdb_addr_sort_list (struct winsdb_addr **p1, struct winsdb_addr **
a1_owned = true;
}
- return a2_owned - a1_owned;
+ return NUMERIC_CMP(a2_owned, a1_owned);
}
struct winsdb_addr **winsdb_addr_list_add(struct winsdb_handle *h, const struct winsdb_record *rec,
diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c
index a9f3ecd..6679961 100644
--- a/source4/nbt_server/wins/winsserver.c
+++ b/source4/nbt_server/wins/winsserver.c
@@ -36,6 +36,7 @@
#include "param/param.h"
#include "libcli/resolve/resolve.h"
#include "lib/util/util_net.h"
+#include "lib/util/tsort.h"
/*
work out the ttl we will use given a client requested ttl
@@ -653,7 +654,7 @@ static int nbtd_wins_randomize1Clist_sort(void *p1,/* (const char **) */
match_bits1 = ipv4_match_bits(interpret_addr2(a1), interpret_addr2(src->addr));
match_bits2 = ipv4_match_bits(interpret_addr2(a2), interpret_addr2(src->addr));
- return match_bits2 - match_bits1;
+ return NUMERIC_CMP(match_bits2, match_bits1);
}
static void nbtd_wins_randomize1Clist(struct loadparm_context *lp_ctx,
diff --git a/source4/nbt_server/wscript_build b/source4/nbt_server/wscript_build
index 9d0c24a..ce436e8 100644
--- a/source4/nbt_server/wscript_build
+++ b/source4/nbt_server/wscript_build
@@ -38,7 +38,7 @@ bld.SAMBA_SUBSYSTEM('NBTD_DGRAM',
bld.SAMBA_SUBSYSTEM('NBT_SERVER',
source='interfaces.c register.c query.c nodestatus.c defense.c packet.c irpc.c',
autoproto='nbt_server_proto.h',
- deps='cli-nbt NBTD_WINS NBTD_DGRAM service',
+ deps='cli-nbt NBTD_WINS NBTD_DGRAM service LIBNMB',
enabled=bld.AD_DC_BUILD_IS_ENABLED()
)
diff --git a/source4/ntvfs/posix/pvfs_streams.c b/source4/ntvfs/posix/pvfs_streams.c
index 9210237..d2d5eed 100644
--- a/source4/ntvfs/posix/pvfs_streams.c
+++ b/source4/ntvfs/posix/pvfs_streams.c
@@ -22,6 +22,7 @@
#include "includes.h"
#include "vfs_posix.h"
#include "librpc/gen_ndr/xattr.h"
+#include "lib/util/tsort.h"
/*
normalise a stream name, removing a :$DATA suffix if there is one
@@ -51,7 +52,7 @@ static int stream_name_cmp(const char *name1, const char *name2)
l1 = c1?(c1 - name1):strlen(name1);
l2 = c2?(c2 - name2):strlen(name2);
if (l1 != l2) {
- return l1 - l2;
+ return NUMERIC_CMP(l1, l2);
}
ret = strncasecmp_m(name1, name2, l1);
if (ret != 0) {
diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c
index e6d35fc..6ffca19 100644
--- a/source4/rpc_server/dnsserver/dnsdata.c
+++ b/source4/rpc_server/dnsserver/dnsdata.c
@@ -1075,9 +1075,23 @@ int dns_name_compare(struct ldb_message * const *m1, struct ldb_message * const
name1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
name2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
- if (name1 == NULL || name2 == NULL) {
+ /*
+ * We sort NULL names to the start of the list, because the only
+ * caller of this function, dnsserver_enumerate_records() will call
+ * dns_build_tree() with the sorted list, which will always return an
+ * error when it hits a NULL, so we might as well make that happen
+ * quickly.
+ */
+ if (name1 == name2) {
+ /* this includes the both NULL case */
return 0;
}
+ if (name1 == NULL) {
+ return -1;
+ }
+ if (name2 == NULL) {
+ return 1;
+ }
/* Compare the last components of names.
* If search_name is not NULL, compare the second last components of names */
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 841c764..66a7785 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -1166,7 +1166,7 @@ static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call
*/
static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
{
- return e1->idx - e2->idx;
+ return NUMERIC_CMP(e1->idx, e2->idx);
}
static int compare_msgRid(struct ldb_message **m1, struct ldb_message **m2) {
@@ -1197,8 +1197,9 @@ static int compare_msgRid(struct ldb_message **m1, struct ldb_message **m2) {
}
/*
- * Get and compare the rids, if we fail to extract a rid treat it as a
- * missing SID and sort to the end of the list
+ * Get and compare the rids. If we fail to extract a rid (because
+ * there are no subauths) the msg goes to the end of the list, but
+ * before the NULL SIDs.
*/
status = dom_sid_split_rid(NULL, sid1, NULL, &rid1);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index d70d7d5..e47eb57 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -531,7 +531,11 @@ plantestsuite_loadlist("samba.tests.dns_aging", "fl2003dc:local",
plantestsuite_loadlist("samba.tests.dns_forwarder", "fl2003dc:local", [python, os.path.join(srcdir(), "python/samba/tests/dns_forwarder.py"), '$SERVER', '$SERVER_IP', '$DNS_FORWARDER1', '$DNS_FORWARDER2', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
-plantestsuite_loadlist("samba.tests.dns_tkey", "fl2008r2dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_tkey.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
+plantestsuite_loadlist("samba.tests.dns_tkey", "fl2008r2dc",
+ ['USERNAME_UNPRIV=$DOMAIN_USER','PASSWORD_UNPRIV=$DOMAIN_USER_PASSWORD',
+ python, os.path.join(srcdir(), "python/samba/tests/dns_tkey.py"),
+ '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"',
+ '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
plantestsuite_loadlist("samba.tests.dns_wildcard", "ad_dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_wildcard.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
plantestsuite_loadlist("samba.tests.dns_invalid", "ad_dc", [python, os.path.join(srcdir(), "python/samba/tests/dns_invalid.py"), '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
@@ -817,6 +821,11 @@ plantestsuite("samba4.blackbox.trust_ntlm", "fl2000dc:local", [os.path.join(bbdi
plantestsuite("samba4.blackbox.trust_ntlm", "ad_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
plantestsuite("samba4.blackbox.trust_ntlm", "nt4_member:local", [os.path.join(bbdir, "test_trust_ntlm.sh"), '$SERVER_IP', '$USERNAME', '$PASSWORD', '$SERVER', '$SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$DOMAIN', '$DOMAIN', 'member', 'auto', 'NT_STATUS_LOGON_FAILURE'])
+plantestsuite("samba4.blackbox.ldap_token", "fl2008r2dc:local", [os.path.join(bbdir, "test_ldap_token.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$DOMSID'])
+plantestsuite("samba4.blackbox.ldap_token", "fl2003dc:local", [os.path.join(bbdir, "test_ldap_token.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$DOMSID'])
+plantestsuite("samba4.blackbox.ldap_token", "fl2000dc:local", [os.path.join(bbdir, "test_ldap_token.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$DOMSID'])
+plantestsuite("samba4.blackbox.ldap_token", "ad_member:local", [os.path.join(bbdir, "test_ldap_token.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$DOMAIN', '$DOMSID'])
+
plantestsuite("samba4.blackbox.trust_utils(fl2008r2dc:local)", "fl2008r2dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "forest"])
plantestsuite("samba4.blackbox.trust_utils(fl2003dc:local)", "fl2003dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
plantestsuite("samba4.blackbox.trust_utils(fl2000dc:local)", "fl2000dc:local", [os.path.join(bbdir, "test_trust_utils.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external"])
@@ -1477,6 +1486,9 @@ planoldpythontestsuite("fileserver",
"samba.tests.blackbox.smbcacls_dfs_propagate_inherit",
"samba.tests.blackbox.smbcacls_dfs_propagate_inherit(DFS-msdfs-root)",
environ={'SHARE': 'smbcacls_share'})
+
+planoldpythontestsuite("fileserver",
+ "samba.tests.blackbox.misc_dfs_widelink")
#
# Want a selection of environments across the process models
#
diff --git a/source4/torture/smb2/ioctl.c b/source4/torture/smb2/ioctl.c
index 3765dc0..beceaa5 100644
--- a/source4/torture/smb2/ioctl.c
+++ b/source4/torture/smb2/ioctl.c
@@ -7389,6 +7389,68 @@ static bool test_ioctl_bug14788_NETWORK_INTERFACE(struct torture_context *tortur
}
/*
+ * basic regression test for BUG 15664
+ * https://bugzilla.samba.org/show_bug.cgi?id=15664
+ */
+static bool test_ioctl_copy_chunk_bug15644(struct torture_context *torture,
+ struct smb2_tree *tree)
+{
+ struct smb2_handle dest_h;
+ NTSTATUS status;
+ union smb_ioctl ioctl;
+ TALLOC_CTX *tmp_ctx = talloc_new(tree);
+ struct srv_copychunk chunk;
+ struct srv_copychunk_copy cc_copy;
+ enum ndr_err_code ndr_ret;
+ bool ok;
+
+ ok = test_setup_create_fill(torture,
+ tree,
+ tmp_ctx,
+ FNAME2,
+ &dest_h,
+ 0,
+ SEC_RIGHTS_FILE_ALL,
+ FILE_ATTRIBUTE_NORMAL);
+ torture_assert(torture, ok, "dest file create fill");
+
+ ZERO_STRUCT(ioctl);
+ ioctl.smb2.level = RAW_IOCTL_SMB2;
+ ioctl.smb2.in.file.handle = dest_h;
+ ioctl.smb2.in.function = FSCTL_SRV_COPYCHUNK;
+ ioctl.smb2.in.max_output_response = sizeof(struct srv_copychunk_rsp);
+ ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
+
+ ZERO_STRUCT(chunk);
+ ZERO_STRUCT(cc_copy);
+ /* overwrite the resume key with a bogus value */
+ memcpy(cc_copy.source_key, "deadbeefdeadbeefdeadbeef", 24);
+ cc_copy.chunk_count = 1;
+ cc_copy.chunks = &chunk;
+ cc_copy.chunks[0].source_off = 0;
+ cc_copy.chunks[0].target_off = 0;
+ cc_copy.chunks[0].length = 4096;
+
+ ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
+ &cc_copy,
+ (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+ torture_assert_ndr_success(torture, ndr_ret,
+ "ndr_push_srv_copychunk_copy");
+
+ /* Server 2k12 returns NT_STATUS_OBJECT_NAME_NOT_FOUND */
+ status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
+ torture_assert_ntstatus_equal(torture, status,
+ NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ "FSCTL_SRV_COPYCHUNK");
+
+ status = smb2_util_close(tree, dest_h);
+ torture_assert_ntstatus_ok(torture, status, "close");
+
+ talloc_free(tmp_ctx);
+ return true;
+}
+
+/*
* testing of SMB2 ioctls
*/
struct torture_suite *torture_smb2_ioctl_init(TALLOC_CTX *ctx)
@@ -7420,6 +7482,8 @@ struct torture_suite *torture_smb2_ioctl_init(TALLOC_CTX *ctx)
test_ioctl_copy_chunk_dest_lck);
torture_suite_add_1smb2_test(suite, "copy_chunk_bad_key",
test_ioctl_copy_chunk_bad_key);
+ torture_suite_add_1smb2_test(suite, "copy_chunk_bug15644",
+ test_ioctl_copy_chunk_bug15644);
torture_suite_add_1smb2_test(suite, "copy_chunk_src_is_dest",
test_ioctl_copy_chunk_src_is_dest);
torture_suite_add_1smb2_test(suite, "copy_chunk_src_is_dest_overlap",
diff --git a/source4/torture/smb2/session.c b/source4/torture/smb2/session.c
index 823304f..2a3d0e6 100644
--- a/source4/torture/smb2/session.c
+++ b/source4/torture/smb2/session.c
@@ -5527,6 +5527,630 @@ static bool test_session_ntlmssp_bug14932(struct torture_context *tctx, struct s
return ret;
}
+static bool test_session_anon_encryption1(struct torture_context *tctx,
+ struct smb2_tree *tree0)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = "IPC$";
+ char *unc = NULL;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct cli_credentials *anon_creds = NULL;
+ struct smbcli_options options;
+ struct smb2_transport *transport = NULL;
+ struct smb2_session *anon_session = NULL;
+ struct smb2_tree *anon_tree = NULL;
+ NTSTATUS status;
+ bool ok = true;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ anon_creds = cli_credentials_init_anon(tctx);
+ torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
+ ok = cli_credentials_set_smb_encryption(anon_creds,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options = transport0->options;
+ options.client_guid = GUID_random();
+ options.only_negprot = true;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ anon_creds,
+ &anon_tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
+ anon_session = anon_tree->session;
+ transport = anon_session->transport;
+
+ anon_session->anonymous_session_key = true;
+ smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
+
+ status = smb2_session_setup_spnego(anon_session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2_session_setup_spnego failed");
+
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ /*
+ * The connection is still in ConstrainedConnection state...
+ *
+ * This will use encryption and causes a connection reset
+ */
+ timeout_msec = transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
+ status = NT_STATUS_CONNECTION_RESET;
+ }
+ torture_assert_ntstatus_equal(tctx, status,
+ NT_STATUS_CONNECTION_RESET,
+ "smb2cli_tcon_recv");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, !ok, "smbXcli_conn_is_connected still connected");
+
+ return true;
+}
+
+static bool test_session_anon_encryption2(struct torture_context *tctx,
+ struct smb2_tree *tree0)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = "IPC$";
+ char *unc = NULL;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct cli_credentials *_creds = samba_cmdline_get_creds();
+ struct cli_credentials *user_creds = NULL;
+ struct cli_credentials *anon_creds = NULL;
+ struct smbcli_options options;
+ struct smb2_transport *transport = NULL;
+ struct smb2_session *user_session = NULL;
+ struct smb2_tree *user_tree = NULL;
+ struct smb2_session *anon_session = NULL;
+ struct smb2_tree *anon_tree = NULL;
+ struct smb2_ioctl ioctl = {
+ .level = RAW_IOCTL_SMB2,
+ .in = {
+ .file = {
+ .handle = {
+ .data = {
+ [0] = UINT64_MAX,
+ [1] = UINT64_MAX,
+ },
+ },
+ },
+ .function = FSCTL_QUERY_NETWORK_INTERFACE_INFO,
+ /* Windows client sets this to 64KiB */
+ .max_output_response = 0x10000,
+ .flags = SMB2_IOCTL_FLAG_IS_FSCTL,
+ },
+ };
+ NTSTATUS status;
+ bool ok = true;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+ uint32_t caps = smb2cli_conn_server_capabilities(transport0->conn);
+ NTSTATUS expected_mc_status;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ if (caps & SMB2_CAP_MULTI_CHANNEL) {
+ expected_mc_status = NT_STATUS_OK;
+ } else {
+ expected_mc_status = NT_STATUS_FS_DRIVER_REQUIRED;
+ }
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ user_creds = cli_credentials_shallow_copy(tctx, _creds);
+ torture_assert(tctx, user_creds != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(user_creds,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ anon_creds = cli_credentials_init_anon(tctx);
+ torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
+ ok = cli_credentials_set_smb_encryption(anon_creds,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options = transport0->options;
+ options.client_guid = GUID_random();
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ user_creds,
+ &user_tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
+ user_session = user_tree->session;
+ transport = user_session->transport;
+ ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
+ torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(user)");
+ ok = smbXcli_session_is_authenticated(user_session->smbXcli);
+ torture_assert(tctx, ok, "smbXcli_session_is_authenticated(user)");
+
+ anon_session = smb2_session_init(transport,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tctx);
+ torture_assert(tctx, anon_session != NULL, "smb2_session_init(anon)");
+
+ anon_session->anonymous_session_key = true;
+ smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
+
+ status = smb2_session_setup_spnego(anon_session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2_session_setup_spnego failed");
+
+ ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
+ torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ anon_tree = smb2_tree_init(anon_session, tctx, false);
+ torture_assert(tctx, anon_tree != NULL, "smb2_tree_init");
+
+ timeout_msec = transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2cli_tcon_recv(anon)");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ ok = smb2cli_tcon_is_encryption_on(anon_tree->smbXcli);
+ torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ status = smb2_ioctl(user_tree, tctx, &ioctl);
+ torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
+ "FSCTL_QUERY_NETWORK_INTERFACE_INFO user");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ status = smb2_ioctl(anon_tree, tctx, &ioctl);
+ torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
+ "FSCTL_QUERY_NETWORK_INTERFACE_INFO anonymous");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ status = smb2_ioctl(user_tree, tctx, &ioctl);
+ torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
+ "FSCTL_QUERY_NETWORK_INTERFACE_INFO user");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ status = smb2_ioctl(anon_tree, tctx, &ioctl);
+ torture_assert_ntstatus_equal(tctx, status, expected_mc_status,
+ "FSCTL_QUERY_NETWORK_INTERFACE_INFO anonymous");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ return true;
+}
+
+static bool test_session_anon_encryption3(struct torture_context *tctx,
+ struct smb2_tree *tree0)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = "IPC$";
+ char *unc = NULL;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct cli_credentials *_creds = samba_cmdline_get_creds();
+ struct cli_credentials *user_creds = NULL;
+ struct cli_credentials *anon_creds = NULL;
+ struct smbcli_options options;
+ struct smb2_transport *transport = NULL;
+ struct smb2_session *user_session = NULL;
+ struct smb2_tree *user_tree = NULL;
+ struct smb2_session *anon_session = NULL;
+ struct smb2_tree *anon_tree = NULL;
+ NTSTATUS status;
+ bool ok = true;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+ uint8_t wrong_session_key[16] = { 0x1f, 0x2f, 0x3f, };
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ user_creds = cli_credentials_shallow_copy(tctx, _creds);
+ torture_assert(tctx, user_creds != NULL, "cli_credentials_shallow_copy");
+ ok = cli_credentials_set_smb_encryption(user_creds,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ anon_creds = cli_credentials_init_anon(tctx);
+ torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
+ ok = cli_credentials_set_smb_encryption(anon_creds,
+ SMB_ENCRYPTION_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options = transport0->options;
+ options.client_guid = GUID_random();
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ user_creds,
+ &user_tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
+ user_session = user_tree->session;
+ transport = user_session->transport;
+ ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
+ torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(user)");
+ ok = smbXcli_session_is_authenticated(user_session->smbXcli);
+ torture_assert(tctx, ok, "smbXcli_session_is_authenticated(user)");
+
+ anon_session = smb2_session_init(transport,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tctx);
+ torture_assert(tctx, anon_session != NULL, "smb2_session_init(anon)");
+
+ anon_session->anonymous_session_key = true;
+ anon_session->forced_session_key = data_blob_const(wrong_session_key,
+ ARRAY_SIZE(wrong_session_key));
+ smb2cli_session_torture_anonymous_encryption(anon_session->smbXcli, true);
+
+ status = smb2_session_setup_spnego(anon_session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2_session_setup_spnego failed");
+
+ ok = smb2cli_tcon_is_encryption_on(user_tree->smbXcli);
+ torture_assert(tctx, ok, "smb2cli_tcon_is_encryption_on(anon)");
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ anon_tree = smb2_tree_init(anon_session, tctx, false);
+ torture_assert(tctx, anon_tree != NULL, "smb2_tree_init");
+
+ timeout_msec = transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
+ status = NT_STATUS_CONNECTION_RESET;
+ }
+ torture_assert_ntstatus_equal(tctx, status,
+ NT_STATUS_CONNECTION_RESET,
+ "smb2cli_tcon_recv");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, !ok, "smbXcli_conn_is_connected still connected");
+
+ return true;
+}
+
+static bool test_session_anon_signing1(struct torture_context *tctx,
+ struct smb2_tree *tree0)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = "IPC$";
+ char *unc = NULL;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct cli_credentials *anon_creds = NULL;
+ struct smbcli_options options;
+ struct smb2_transport *transport = NULL;
+ struct smb2_session *anon_session = NULL;
+ struct smb2_tree *anon_tree = NULL;
+ NTSTATUS status;
+ bool ok = true;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ anon_creds = cli_credentials_init_anon(tctx);
+ torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
+ ok = cli_credentials_set_smb_signing(anon_creds,
+ SMB_SIGNING_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_signing");
+ ok = cli_credentials_set_smb_ipc_signing(anon_creds,
+ SMB_SIGNING_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_ipc_signing");
+ ok = cli_credentials_set_smb_encryption(anon_creds,
+ SMB_ENCRYPTION_OFF,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options = transport0->options;
+ options.client_guid = GUID_random();
+ options.only_negprot = true;
+ options.signing = SMB_SIGNING_REQUIRED;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ anon_creds,
+ &anon_tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
+ anon_session = anon_tree->session;
+ transport = anon_session->transport;
+
+ anon_session->anonymous_session_key = true;
+ smb2cli_session_torture_anonymous_signing(anon_session->smbXcli, true);
+
+ status = smb2_session_setup_spnego(anon_session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2_session_setup_spnego failed");
+
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ timeout_msec = transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ torture_assert_ntstatus_ok(tctx, status, "smb2cli_tcon_recv");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ return true;
+}
+
+static bool test_session_anon_signing2(struct torture_context *tctx,
+ struct smb2_tree *tree0)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = "IPC$";
+ char *unc = NULL;
+ struct smb2_transport *transport0 = tree0->session->transport;
+ struct cli_credentials *anon_creds = NULL;
+ struct smbcli_options options;
+ struct smb2_transport *transport = NULL;
+ struct smb2_session *anon_session = NULL;
+ struct smb2_session *anon_session_nosign = NULL;
+ struct smb2_tree *anon_tree = NULL;
+ NTSTATUS status;
+ bool ok = true;
+ struct tevent_req *subreq = NULL;
+ uint32_t timeout_msec;
+ uint8_t wrong_session_key[16] = { 0x1f, 0x2f, 0x3f, };
+ uint64_t session_id;
+
+ if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx,
+ "Can't test without SMB3 support");
+ }
+
+ unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
+ torture_assert(tctx, unc != NULL, "talloc_asprintf");
+
+ anon_creds = cli_credentials_init_anon(tctx);
+ torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon");
+ ok = cli_credentials_set_smb_signing(anon_creds,
+ SMB_SIGNING_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_signing");
+ ok = cli_credentials_set_smb_ipc_signing(anon_creds,
+ SMB_SIGNING_REQUIRED,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_ipc_signing");
+ ok = cli_credentials_set_smb_encryption(anon_creds,
+ SMB_ENCRYPTION_OFF,
+ CRED_SPECIFIED);
+ torture_assert(tctx, ok, "cli_credentials_set_smb_encryption");
+
+ options = transport0->options;
+ options.client_guid = GUID_random();
+ options.only_negprot = true;
+ options.signing = SMB_SIGNING_REQUIRED;
+
+ status = smb2_connect(tctx,
+ host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ anon_creds,
+ &anon_tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ torture_assert_ntstatus_ok(tctx, status, "smb2_connect failed");
+ anon_session = anon_tree->session;
+ transport = anon_session->transport;
+
+ anon_session->anonymous_session_key = true;
+ anon_session->forced_session_key = data_blob_const(wrong_session_key,
+ ARRAY_SIZE(wrong_session_key));
+ smb2cli_session_torture_anonymous_signing(anon_session->smbXcli, true);
+ smb2cli_session_torture_no_signing_disconnect(anon_session->smbXcli);
+
+ status = smb2_session_setup_spnego(anon_session,
+ anon_creds,
+ 0 /* previous_session_id */);
+ torture_assert_ntstatus_ok(tctx, status,
+ "smb2_session_setup_spnego failed");
+
+ ok = smbXcli_session_is_authenticated(anon_session->smbXcli);
+ torture_assert(tctx, !ok, "smbXcli_session_is_authenticated(anon) wrong");
+
+ /*
+ * create a new structure for the same session id,
+ * but without smb2.should_sign set.
+ */
+ session_id = smb2cli_session_current_id(anon_session->smbXcli);
+ anon_session_nosign = smb2_session_init(transport,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx),
+ tctx);
+ torture_assert(tctx, anon_session_nosign != NULL, "smb2_session_init(anon_nosign)");
+ smb2cli_session_set_id_and_flags(anon_session_nosign->smbXcli, session_id, 0);
+ smb2cli_session_torture_no_signing_disconnect(anon_session_nosign->smbXcli);
+
+ timeout_msec = transport->options.request_timeout * 1000;
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ torture_assert_ntstatus_equal(tctx, status,
+ NT_STATUS_ACCESS_DENIED,
+ "smb2cli_tcon_recv");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ subreq = smb2cli_tcon_send(tctx,
+ tctx->ev,
+ transport->conn,
+ timeout_msec,
+ anon_session_nosign->smbXcli,
+ anon_tree->smbXcli,
+ 0, /* flags */
+ unc);
+ torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
+
+ torture_assert(tctx,
+ tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
+ "tevent_req_poll_ntstatus");
+
+ status = smb2cli_tcon_recv(subreq);
+ TALLOC_FREE(subreq);
+ torture_assert_ntstatus_ok(tctx, status, "smb2cli_tcon_recv");
+
+ ok = smbXcli_conn_is_connected(transport->conn);
+ torture_assert(tctx, ok, "smbXcli_conn_is_connected");
+
+ return true;
+}
+
struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
{
struct torture_suite *suite =
@@ -5599,6 +6223,11 @@ struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx)
torture_suite_add_1smb2_test(suite, "encryption-aes-256-ccm", test_session_encryption_aes_256_ccm);
torture_suite_add_1smb2_test(suite, "encryption-aes-256-gcm", test_session_encryption_aes_256_gcm);
torture_suite_add_1smb2_test(suite, "ntlmssp_bug14932", test_session_ntlmssp_bug14932);
+ torture_suite_add_1smb2_test(suite, "anon-encryption1", test_session_anon_encryption1);
+ torture_suite_add_1smb2_test(suite, "anon-encryption2", test_session_anon_encryption2);
+ torture_suite_add_1smb2_test(suite, "anon-encryption3", test_session_anon_encryption3);
+ torture_suite_add_1smb2_test(suite, "anon-signing1", test_session_anon_signing1);
+ torture_suite_add_1smb2_test(suite, "anon-signing2", test_session_anon_signing2);
suite->description = talloc_strdup(suite, "SMB2-SESSION tests");
diff --git a/testprogs/blackbox/test_ldap_token.sh b/testprogs/blackbox/test_ldap_token.sh
new file mode 100755
index 0000000..5965590
--- /dev/null
+++ b/testprogs/blackbox/test_ldap_token.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Copyright (C) 2017 Stefan Metzmacher <metze@samba.org>
+
+if [ $# -lt 6 ]; then
+ cat <<EOF
+Usage: $# test_ldap_token.sh SERVER USERNAME PASSWORD REALM DOMAIN DOMSID
+EOF
+ exit 1
+fi
+
+SERVER=$1
+shift 1
+USERNAME=$1
+PASSWORD=$2
+REALM=$3
+DOMAIN=$4
+DOMSID=$5
+shift 5
+failed=0
+
+. $(dirname $0)/subunit.sh
+. $(dirname $0)/common_test_fns.inc
+
+ldbsearch=$(system_or_builddir_binary ldbsearch "${BINDIR}")
+
+test_token()
+{
+ auth_user="${1}"
+ shift 1
+ auth_sid="${1}"
+ shift 1
+ auth_args="$@"
+
+ out=$($VALGRIND $ldbsearch -H ldap://$SERVER.$REALM ${auth_user} -b '' --scope=base ${auth_args} tokenGroups 2>&1)
+ ret=$?
+ test x"$ret" = x"0" || {
+ echo "$out"
+ return 1
+ }
+
+ domain_sids=$(echo "$out" | grep '^tokenGroups' | grep "${DOMSID}-" | wc -l)
+ test "$domain_sids" -ge "1" || {
+ echo "$out"
+ echo "Less than 1 sid from $DOMAIN $DOMSID"
+ return 1
+ }
+
+ builtin_sids=$(echo "$out" | grep '^tokenGroups' | grep "S-1-5-32-" | wc -l)
+ test "$builtin_sids" -ge "1" || {
+ echo "$out"
+ echo "Less than 1 sid from BUILTIN S-1-5-32"
+ return 1
+ }
+
+ #
+ # The following should always be present
+ #
+ # SID_WORLD(S-1-1-0)
+ # SID_NT_NETWORK(S-1-5-2)
+ # SID_NT_AUTHENTICATED_USERS(S-1-5-11)
+ #
+ required_sids="S-1-1-0 S-1-5-2 S-1-5-11 ${auth_sid}"
+ for sid in $required_sids; do
+ found=$(echo "$out" | grep "^tokenGroups: ${sid}$" | wc -l)
+ test x"$found" = x"1" || {
+ echo "$out"
+ echo "SID: ${sid} not found"
+ return 1
+ }
+ done
+
+ return 0
+}
+
+UARGS="-U$REALM\\$USERNAME%$PASSWORD"
+# Check that SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY(S-1-18-1) is added for krb5
+AARGS="-k yes"
+testit "Test token with kerberos USER (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=required"
+testit "Test token with kerberos USER (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--option=clientusekerberos=required"
+testit "Test token with kerberos USER (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=required --option=clientusekerberos=off"
+testit "Test token with kerberos USER (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+# Check that SID_NT_NTLM_AUTHENTICATION(S-1-5-64-10) is added for NTLMSSP
+AARGS="-k no"
+testit "Test token with NTLMSSP USER (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=off"
+testit "Test token with NTLMSSP USER (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--option=clientusekerberos=off"
+testit "Test token with NTLMSSP USER (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=off --option=clientusekerberos=required"
+testit "Test token with NTLMSSP USER (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+
+UARGS="-P"
+# Check that SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY(S-1-18-1) is added for krb5
+AARGS="-k yes"
+testit "Test token with kerberos MACHINE (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=required"
+testit "Test token with kerberos MACHINE (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--option=clientusekerberos=required"
+testit "Test token with kerberos MACHINE (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=required --option=clientusekerberos=off"
+testit "Test token with kerberos MACHINE (${AARGS})" test_token "${UARGS}" "S-1-18-1" "${AARGS}" || failed=$(expr $failed + 1)
+# Check that SID_NT_NTLM_AUTHENTICATION(S-1-5-64-10) is added for NTLMSSP
+AARGS="-k no"
+testit "Test token with NTLMSSP MACHINE (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=off"
+testit "Test token with NTLMSSP MACHINE (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--option=clientusekerberos=off"
+testit "Test token with NTLMSSP MACHINE (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+AARGS="--use-kerberos=off --option=clientusekerberos=required"
+testit "Test token with NTLMSSP MACHINE (${AARGS})" test_token "${UARGS}" "S-1-5-64-10" "${AARGS}" || failed=$(expr $failed + 1)
+
+exit $failed
diff --git a/testprogs/blackbox/test_trust_token.sh b/testprogs/blackbox/test_trust_token.sh
index 075c032..92d4ad5 100755
--- a/testprogs/blackbox/test_trust_token.sh
+++ b/testprogs/blackbox/test_trust_token.sh
@@ -34,7 +34,7 @@ ldbsearch=$(system_or_builddir_binary ldbsearch "${BINDIR}")
test_token()
{
auth_args="${1}"
- auth_sid="${2-}"
+ auth_sid="${2}"
out=$($VALGRIND $ldbsearch -H ldap://$SERVER.$REALM -U$TRUST_REALM\\$TRUST_USERNAME%$TRUST_PASSWORD -b '' --scope=base -k ${auth_args} tokenGroups 2>&1)
ret=$?
@@ -84,7 +84,8 @@ test_token()
return 0
}
-testit "Test token with kerberos" test_token "yes" "" || failed=$(expr $failed + 1)
+# Check that SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY(S-1-18-1) is added for krb5
+testit "Test token with kerberos" test_token "yes" "S-1-18-1" || failed=$(expr $failed + 1)
# Check that SID_NT_NTLM_AUTHENTICATION(S-1-5-64-10) is added for NTLMSSP
testit "Test token with NTLMSSP" test_token "no" "S-1-5-64-10" || failed=$(expr $failed + 1)
diff --git a/third_party/socket_wrapper/socket_wrapper.c b/third_party/socket_wrapper/socket_wrapper.c
index c759d35..37799c8 100644
--- a/third_party/socket_wrapper/socket_wrapper.c
+++ b/third_party/socket_wrapper/socket_wrapper.c
@@ -1388,6 +1388,9 @@ static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
}
+/* JEMALLOC: This tells socket_wrapper if it should handle syscall() */
+static bool swrap_handle_syscall;
+
#ifdef HAVE_SYSCALL
DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
static long int libc_vsyscall(long int sysno, va_list va)
@@ -1396,7 +1399,27 @@ static long int libc_vsyscall(long int sysno, va_list va)
long int rc;
int i;
- swrap_bind_symbol_all();
+ /*
+ * JEMALLOC:
+ *
+ * This is a workaround to prevent a deadlock in jemalloc calling
+ * malloc_init() twice. The first allocation call will trigger a
+ * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+ * so it goes to socket or uid wrapper. In this code path we need to
+ * avoid any allocation calls. This will prevent the deadlock.
+ *
+ * We also need to avoid dlopen() as that would trigger the recursion
+ * into malloc_init(), so we use dlsym(RTLD_NEXT), until we reached
+ * swrap_constructor() or any real socket call at that time
+ * swrap_bind_symbol_all() will replace the function pointer again after
+ * dlopen of libc.
+ */
+ if (swrap_handle_syscall) {
+ swrap_bind_symbol_all();
+ } else if (swrap.libc.symbols._libc_syscall.obj == NULL) {
+ swrap.libc.symbols._libc_syscall.obj = dlsym(RTLD_NEXT,
+ "syscall");
+ }
for (i = 0; i < 8; i++) {
args[i] = va_arg(va, long int);
@@ -1517,6 +1540,8 @@ static void __swrap_bind_symbol_all_once(void)
swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
#endif
+
+ swrap_handle_syscall = true;
}
static void swrap_bind_symbol_all(void)
@@ -8745,6 +8770,21 @@ long int syscall(long int sysno, ...)
va_start(va, sysno);
/*
+ * JEMALLOC:
+ *
+ * This is a workaround to prevent a deadlock in jemalloc calling
+ * malloc_init() twice. The first allocation call will trigger a
+ * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+ * so it goes to socket or uid wrapper. In this code path we need to
+ * avoid any allocation calls. This will prevent the deadlock.
+ */
+ if (!swrap_handle_syscall) {
+ rc = libc_vsyscall(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
+ /*
* We should only handle the syscall numbers
* we care about...
*/
@@ -8860,6 +8900,9 @@ void swrap_constructor(void)
pthread_atfork(&swrap_thread_prepare,
&swrap_thread_parent,
&swrap_thread_child);
+
+ /* Let socket_wrapper handle syscall() */
+ swrap_handle_syscall = true;
}
/****************************
diff --git a/third_party/socket_wrapper/wscript b/third_party/socket_wrapper/wscript
index 9d2210d..cdd3493 100644
--- a/third_party/socket_wrapper/wscript
+++ b/third_party/socket_wrapper/wscript
@@ -2,7 +2,7 @@
import os
-VERSION = "1.4.2"
+VERSION = "1.4.3"
def configure(conf):
@@ -10,6 +10,7 @@ def configure(conf):
conf.DEFINE('USING_SYSTEM_SOCKET_WRAPPER', 1)
libsocket_wrapper_so_path = 'libsocket_wrapper.so'
else:
+ conf.CHECK_HEADERS('gnu/lib-names.h')
if conf.CONFIG_SET("HAVE___THREAD"):
conf.DEFINE("HAVE_GCC_THREAD_LOCAL_STORAGE", 1)
diff --git a/third_party/uid_wrapper/uid_wrapper.c b/third_party/uid_wrapper/uid_wrapper.c
index 5b6a82b..ca578e6 100644
--- a/third_party/uid_wrapper/uid_wrapper.c
+++ b/third_party/uid_wrapper/uid_wrapper.c
@@ -38,6 +38,10 @@
#include <pthread.h>
+#ifdef HAVE_GNU_LIB_NAMES_H
+#include <gnu/lib-names.h>
+#endif
+
#ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
# define UWRAP_THREAD __thread
#else
@@ -558,6 +562,13 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib)
switch (lib) {
case UWRAP_LIBC:
handle = uwrap.libc.handle;
+#ifdef LIBC_SO
+ if (handle == NULL) {
+ handle = dlopen(LIBC_SO, flags);
+
+ uwrap.libc.handle = handle;
+ }
+#endif
if (handle == NULL) {
for (i = 10; i >= 0; i--) {
char soname[256] = {0};
@@ -656,6 +667,9 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
dlsym(RTLD_DEFAULT, #sym_name); \
}
+/* JEMALLOC: This tells uid_wrapper if it should handle syscall() */
+static bool uwrap_handle_syscall;
+
/* DO NOT call this function during library initialization! */
static void __uwrap_bind_symbol_all_once(void)
{
@@ -699,6 +713,8 @@ static void __uwrap_bind_symbol_all_once(void)
#endif
uwrap_bind_symbol_libpthread(pthread_create);
uwrap_bind_symbol_libpthread(pthread_exit);
+
+ uwrap_handle_syscall = true;
}
static void uwrap_bind_symbol_all(void)
@@ -863,7 +879,27 @@ static long int libc_vsyscall(long int sysno, va_list va)
long int rc;
int i;
- uwrap_bind_symbol_all();
+ /*
+ * JEMALLOC:
+ *
+ * This is a workaround to prevent a deadlock in jemalloc calling
+ * malloc_init() twice. The first allocation call will trigger a
+ * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+ * so it goes to socket or uid wrapper. In this code path we need to
+ * avoid any allocation calls. This will prevent the deadlock.
+ *
+ * We also need to avoid dlopen() as that would trigger the recursion
+ * into malloc_init(), so we use dlsym(RTLD_NEXT), until we reached
+ * swrap_constructor() or any real socket call at that time
+ * swrap_bind_symbol_all() will replace the function pointer again after
+ * dlopen of libc.
+ */
+ if (uwrap_handle_syscall) {
+ uwrap_bind_symbol_all();
+ } else if (uwrap.libc.symbols._libc_syscall.obj == NULL) {
+ uwrap.libc.symbols._libc_syscall.obj = dlsym(RTLD_NEXT,
+ "syscall");
+ }
for (i = 0; i < 8; i++) {
args[i] = va_arg(va, long int);
@@ -1375,7 +1411,7 @@ static void uwrap_init_env(struct uwrap_thread *id)
exit(-1);
}
- UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
+ UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize groups with %s", env);
id->ngroups = ngroups;
}
}
@@ -2709,6 +2745,21 @@ long int syscall (long int sysno, ...)
va_start(va, sysno);
/*
+ * JEMALLOC:
+ *
+ * This is a workaround to prevent a deadlock in jemalloc calling
+ * malloc_init() twice. The first allocation call will trigger a
+ * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
+ * so it goes to socket or uid wrapper. In this code path we need to
+ * avoid any allocation calls. This will prevent the deadlock.
+ */
+ if (!uwrap_handle_syscall) {
+ rc = libc_vsyscall(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
+ /*
* We need to check for uwrap related syscall numbers before calling
* uid_wrapper_enabled() otherwise we'd deadlock during the freebsd libc
* fork() which calls syscall() after invoking uwrap_thread_prepare().
@@ -2821,6 +2872,9 @@ void uwrap_constructor(void)
* for main process.
*/
uwrap_init();
+
+ /* Let socket_wrapper handle syscall() */
+ uwrap_handle_syscall = true;
}
/****************************
diff --git a/third_party/uid_wrapper/wscript b/third_party/uid_wrapper/wscript
index 7b65d93..5af7690 100644
--- a/third_party/uid_wrapper/wscript
+++ b/third_party/uid_wrapper/wscript
@@ -3,13 +3,15 @@
from waflib import Options
import os, sys
-VERSION="1.3.0"
+VERSION="1.3.1"
def configure(conf):
if conf.CHECK_UID_WRAPPER():
conf.DEFINE('USING_SYSTEM_UID_WRAPPER', 1)
libuid_wrapper_so_path = 'libuid_wrapper.so'
else:
+ conf.CHECK_HEADERS('gnu/lib-names.h')
+
# check HAVE_GCC_ATOMIC_BUILTINS
conf.CHECK_CODE('''
#include <stdbool.h>
diff --git a/wscript b/wscript
index 770b9bc..167a3a7 100644
--- a/wscript
+++ b/wscript
@@ -140,7 +140,27 @@ def options(opt):
dest='with_smb1server',
help=("Build smbd with SMB1 support (default=yes)."))
+ opt.add_option('--vendor-name',
+ help=('Specify a vendor (or packager) name to include in the version string'),
+ type="string",
+ dest='SAMBA_VERSION_VENDOR_SUFFIX',
+ default=None)
+
+ opt.add_option('--vendor-patch-revision',
+ help=('Specify a vendor (or packager) patch revision number include in the version string (requires --vendor-name)'),
+ type="int",
+ dest='SAMBA_VERSION_VENDOR_PATCH',
+ default=None)
+
def configure(conf):
+ if Options.options.SAMBA_VERSION_VENDOR_SUFFIX:
+ conf.env.SAMBA_VERSION_VENDOR_SUFFIX = Options.options.SAMBA_VERSION_VENDOR_SUFFIX
+
+ if Options.options.SAMBA_VERSION_VENDOR_PATCH:
+ if not Options.options.SAMBA_VERSION_VENDOR_SUFFIX:
+ raise conf.fatal('--vendor-patch-revision requires --vendor-version')
+ conf.env.SAMBA_VERSION_VENDOR_PATCH = Options.options.SAMBA_VERSION_VENDOR_PATCH
+
version = samba_version.load_version(env=conf.env)
conf.DEFINE('CONFIG_H_IS_FROM_SAMBA', 1)