From 9a54a70d94e2b7a85dba62295b84ef994a75a9aa Mon Sep 17 00:00:00 2001 From: Noel Kuntze Date: Thu, 30 Jan 2025 02:54:10 +0100 Subject: [PATCH] main/samba: upgrade to 4.21.3 --- main/samba/APKBUILD | 210 ++++- main/samba/disable-compile-error-test.patch | 21 + main/samba/ldb-tests.patch | 13 + main/samba/pycrypt.patch | 945 ++++++++++++++++++++ main/samba/s3-notifyd.patch | 513 +++++++++++ main/samba/smbreadline.patch | 112 +++ 6 files changed, 1789 insertions(+), 25 deletions(-) create mode 100644 main/samba/disable-compile-error-test.patch create mode 100644 main/samba/ldb-tests.patch create mode 100644 main/samba/pycrypt.patch create mode 100644 main/samba/s3-notifyd.patch create mode 100644 main/samba/smbreadline.patch diff --git a/main/samba/APKBUILD b/main/samba/APKBUILD index c5046edd63b..2afea360fc3 100644 --- a/main/samba/APKBUILD +++ b/main/samba/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa pkgname=samba -pkgver=4.20.6 -pkgrel=1 +pkgver=4.21.3 +pkgrel=0 pkgdesc="Tools to access a server's filespace and printers via SMB" url="https://www.samba.org/" arch="all" @@ -13,6 +13,9 @@ subpackages=" $pkgname-server-openrc libwbclient $pkgname-util-libs:_util_libs + ldb + ldb-tools:_ldb_tools + py3-ldb:_py3_ldb $pkgname-common:_common:noarch $pkgname-common-tools:_common_tools @@ -62,19 +65,18 @@ makedepends=" icu-dev iniparser-dev jansson-dev - ldb-dev libarchive-dev libcap-dev libtirpc-dev liburing-dev linux-pam-dev + lmdb-dev musl-nscd-dev ncurses-dev openldap-dev perl perl-parse-yapp popt-dev - py3-ldb py3-tdb py3-tevent python3-dev @@ -97,8 +99,13 @@ makedepends=" # " source=" https://download.samba.org/pub/samba/stable/samba-$pkgver.tar.gz + disable-compile-error-test.patch + ldb-tests.patch musl_uintptr.patch default-config.patch + s3-notifyd.patch + pycrypt.patch + smbreadline.patch $pkgname.initd $pkgname.confd @@ -212,7 +219,7 @@ build() { local _vfs_modules=vfs_dfs_samba4 # pclose, .. - export CFLAGS="$CFLAGS -O2 -D_BSD_SOURCE -flto=auto" + export CFLAGS="$CFLAGS -O2 -flto=auto" ./configure \ --prefix=/usr \ --sysconfdir=/etc/$pkgname \ @@ -229,7 +236,8 @@ build() { --with-shared-modules=$_idmap_modules,$_pdb_modules,$_auth_modules,$_vfs_modules \ --enable-cups \ --without-gettext \ - --bundled-libraries=!talloc,!pytalloc,!pytalloc-util,!tdb,!pytdb,!ldb,!pyldb,!pyldb-util,!tevent,!pytevent,!popt \ + --private-libraries=!ldb \ + --bundled-libraries=!talloc,!pytalloc,!pytalloc-util,!tdb,!pytdb,!tevent,!pytevent,!popt \ --disable-rpath-install \ --without-gpgme \ --disable-fault-handling @@ -277,16 +285,30 @@ _common() { # samba-libs-py3 is an attempt to avoid libpython dependency for libsmbclient _libs_py3() { pkgdesc="Libraries that require libpython" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-client-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + py3-ldb=$pkgver-r$pkgrel + " amove \ usr/lib/$pkgname/libsamba-net*private-samba.so \ - usr/lib/$pkgname/libsamba-python*private-samba.so + usr/lib/$pkgname/libsamba-python*private-samba.so \ + usr/lib/$pkgname/libpyldb-util*private-samba.so } # may depend on samba-common-server-libs but not samba-server-libs _common_tools() { pkgdesc="Tools for Samba servers and clients" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-client-libs=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove \ usr/bin/net \ usr/bin/pdbedit \ @@ -302,7 +324,12 @@ _common_tools() { # should not depend on client libs _common_server_libs() { pkgdesc="Samba libraries shared by common-tools and servers" # not shared with clients - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel + " amove \ usr/lib/libdcerpc-server-core.so.* \ usr/lib/libnetapi.so.* \ @@ -316,7 +343,10 @@ _common_server_libs() { libsmbclient() { pkgdesc="The SMB client library" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + " amove \ usr/lib/libsmbclient.so.* } @@ -324,7 +354,12 @@ libsmbclient() { # should only depend on samba-util-libs, libwbclient and samba-libs _client_libs() { pkgdesc="Samba libraries used by clients" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel + " amove \ usr/lib/$pkgname/libad-claims-private-samba.so \ usr/lib/$pkgname/libauthn-policy-util-private-samba.so \ @@ -345,8 +380,13 @@ _client_libs() { client() { pkgdesc="Samba client programs" depends=" - $pkgname-libs=$pkgver-r$pkgrel + $pkgname-client-libs=$pkgver-r$pkgrel $pkgname-common=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libsmbclient=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel " amove \ usr/bin/cifsdd \ @@ -378,7 +418,10 @@ client() { # should not pull in samba-client-libs _server_libs() { pkgdesc="Samba libraries shared by server and windbind" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + " amove \ usr/lib/$pkgname/libdcerpc-samba4-private-samba.so \ usr/lib/$pkgname/libidmap-private-samba.so \ @@ -389,8 +432,13 @@ _server_libs() { winbind() { pkgdesc="Samba user and group resolver" depends=" - $pkgname-libs=$pkgver-r$pkgrel $pkgname-common=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-server-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel " install="winbind.pre-install winbind.pre-upgrade winbind.post-install winbind.post-upgrade" @@ -419,6 +467,55 @@ _util_libs() { usr/lib/$pkgname/libstable-sort-private-samba.so } +# ldb is provided as a separate library for dependant packages such as sssd +ldb() { + pkgdesc="Schema-less, ldap like, API and database" + depends="$pkgname-util-libs=$pkgver-r$pkgrel" + amove \ + usr/lib/libldb.so.* \ + usr/lib/$pkgname/libldb-key-value-private-samba.so \ + usr/lib/$pkgname/libldb-tdb-err-map-private-samba.so \ + usr/lib/$pkgname/libldb-tdb-int-private-samba.so \ + usr/lib/$pkgname/ldb/asq.so \ + usr/lib/$pkgname/ldb/ldb.so \ + usr/lib/$pkgname/ldb/paged_searches.so \ + usr/lib/$pkgname/ldb/rdn_name.so \ + usr/lib/$pkgname/ldb/sample.so \ + usr/lib/$pkgname/ldb/server_sort.so \ + usr/lib/$pkgname/ldb/skel.so \ + usr/lib/$pkgname/ldb/tdb.so + + # only on 64 bit hosts + if [ -e "$pkgdir/usr/lib/$pkgname/libldb-mdb-int-private-samba.so" ]; then + amove usr/lib/$pkgname/libldb-mdb-int-private-samba.so + fi + + if [ -e "$pkgdir/usr/lib/$pkgname/ldb/mdb.so" ]; then + amove usr/lib/$pkgname/ldb/mdb.so + fi +} + +_ldb_tools() { + pkgdesc="Tools to manage LDB files" + depends="ldb=$pkgver-r$pkgrel" + amove \ + usr/bin/ldbadd \ + usr/bin/ldbdel \ + usr/bin/ldbedit \ + usr/bin/ldbmodify \ + usr/bin/ldbrename \ + usr/bin/ldbsearch \ + usr/lib/$pkgname/libldb-cmdline-private-samba.so +} + +_py3_ldb() { + pkgdesc="Python 3 binding for the ldb library" + depends="ldb=$pkgver-r$pkgrel" + amove \ + usr/lib/python3*/site-packages/_ldb_text.py \ + usr/lib/python3*/site-packages/ldb.* +} + # should only depend on samba-util-libs libwbclient() { pkgdesc="Samba winbind client libraries" @@ -428,7 +525,11 @@ libwbclient() { _winbind_clients() { pkgdesc="Samba winbind client tools" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove \ usr/bin/ntlm_auth \ usr/bin/wbinfo @@ -444,7 +545,11 @@ _libnss_winbind() { _winbind_krb5_locator() { pkgdesc="Samba winbind krb5 locator" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove \ usr/lib/samba/krb5 } @@ -459,10 +564,17 @@ _pam_winbind() { dc() { pkgdesc="Samba AD Domain Controller" depends=" - $pkgname-libs=$pkgver-r$pkgrel + $pkgname-client-libs=$pkgver-r$pkgrel $pkgname-common=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-common-tools=$pkgver-r$pkgrel + $pkgname-dc-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel $pkgname-server=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel $pkgname-winbind=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel py3-$pkgname=$pkgver-r$pkgrel $_dc_deps " @@ -479,7 +591,15 @@ dc() { _dc_libs() { pkgdesc="Samba AD Domain Controller libraries" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-client-libs=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-server-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove \ usr/lib/libdcerpc-samr.so.* \ usr/lib/libdcerpc-server.so.* \ @@ -507,8 +627,13 @@ _dc_libs() { server() { pkgdesc="Samba server" depends=" - $pkgname-libs=$pkgver-r$pkgrel + $pkgname-client-libs=$pkgver-r$pkgrel $pkgname-common=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel acl " amove \ @@ -539,7 +664,14 @@ pidl() { _py3() { pkgdesc="Samba python libraries" depends=" + $pkgname-client-libs=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-dc-libs=$pkgver-r$pkgrel $pkgname-libs=$pkgver-r$pkgrel + $pkgname-libs-py3=$pkgver-r$pkgrel + $pkgname-server-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel py3-tdb " mkdir -p "$subpkgdir"/usr/lib @@ -548,7 +680,20 @@ _py3() { _test() { pkgdesc="Samba server and client testing tools" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-client-libs=$pkgver-r$pkgrel + $pkgname-common-server-libs=$pkgver-r$pkgrel + $pkgname-dc=$pkgver-r$pkgrel + $pkgname-dc-libs=$pkgver-r$pkgrel + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-libs-py3=$pkgver-r$pkgrel + $pkgname-server-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel + libauth-$pkgname=$pkgver-r$pkgrel + libsmbclient=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove \ usr/bin/gentest \ usr/bin/locktest \ @@ -562,16 +707,21 @@ _test() { # avoid samba-libs and libsmbclient depending on pam _libauth() { pkgdesc="Samba auth library shared by common-tools, server and clients" - depends="$pkgname-libs=$pkgver-r$pkgrel" + depends=" + $pkgname-libs=$pkgver-r$pkgrel + $pkgname-util-libs=$pkgver-r$pkgrel + libwbclient=$pkgver-r$pkgrel + " amove usr/lib/$pkgname/libauth-private-samba.so } -# should only depend on samba-util-libs and libwbclient +# should only depend on samba-util-libs, ldb and libwbclient libs() { pkgdesc="Samba core libraries shared by common-tools, server and clients" depends=" $pkgname-util-libs=$pkgver-r$pkgrel + ldb=$pkgver-r$pkgrel libwbclient=$pkgver-r$pkgrel " # heimdal libs @@ -639,7 +789,7 @@ libs() { usr/lib/$pkgname/libtalloc-report-printf-private-samba.so \ usr/lib/$pkgname/libtalloc-report-private-samba.so \ usr/lib/$pkgname/libtdb-wrap-private-samba.so \ - usr/lib/$pkgname/libtrusts-util-private-samba.so \ + usr/lib/$pkgname/libutil-crypt-private-samba.so \ usr/lib/$pkgname/libutil-reg-private-samba.so \ usr/lib/$pkgname/libutil-setid-private-samba.so \ usr/lib/$pkgname/libutil-tdb-private-samba.so \ @@ -666,10 +816,20 @@ libs() { fi } +depends_dev() { + provides="ldb-dev" + amove usr/include/$pkgname +} + sha512sums=" -3cc45a9391ea9f8522e45bd6429109d118297e0da2fbd7d86f2625516b5ef5b2dc8d22173b9bd763ea97f754467766cc123eab28b56f9b62c1a14a078ac71e14 samba-4.20.6.tar.gz +b030e4a9749742bfa31b6ef03a3327f1b77b8db388a2d1d591bc8cf26db365ac773c1aa1f2710e7c94585685cdba6c0769af7ba0e0175db33e9d2552c97601ae samba-4.21.3.tar.gz +ef26ef5d6e45c40e8752739cc5a7968a4b9371bb17a7b76fd69cde0b163956a70c893a482c72dc17ab1dd55b695f229b9250195cdca8cd50f75ba02d48058cb5 disable-compile-error-test.patch +102469afc438985809543bf906655ddcbdb059455ab9dca301f7a2254f4740adfde4f8eed69c6b7a18a080b622d0a317cd34ef13d49d772543848ec605263fab ldb-tests.patch b7906d66fe55a980a54161ee3f311b51bcbce76b8d4c8cc1ba6d0c5bdf98232cb192b9d2c1aa7b3e2742f5b9848c6cf429347940eefe66c3e0eda1d5aac1bf93 musl_uintptr.patch 14666954aec4a0bc7a6730ba3a9afdbd4e27c083a038d9a1f5a033e4f0a42bc8408906612ea51f74bf743ff8a225242e54b0a518367fe526b110639bfbfdd071 default-config.patch +a07aaf2520e8f3f8938913c38ebfe3a518048f2d1b95413edbb194b071af678b5dd3853c4443f3ada1ad7f6f5ccef51cc634adce24f41476ed423795a47e2499 s3-notifyd.patch +c4bc1ea224f14028f5034eb28cc41b8a2a491dd9f20fc5e97836c65e8c4d8fd88be286fe5de94cbf54c125879c807d2414d02246ec4ca6207bdd5fd719b55443 pycrypt.patch +1a0bb3c0c022d3aa2e843bd38066cd149448495e20247327d70d69231a79c7490729e86350e00c79c7e2d2f62464c133237117013edd117afac35dcdd9f3f2ba smbreadline.patch fdd31d53cd96bf4f67f74abd770493d04f6330f31654ad445e69f4c445b97e211db30049ddf51591e3ab733c4b62bef3436725da89c566c5d8e17e1b26b1fb19 samba.initd e5a4022aad21be7ad6bd067d60dd7bf447ae7191aecdd4081ccf5f08565ee5e13f592777749bc460773a20a830ef59c47faa322c55253b6ce4160f8285f74c46 samba.confd ec6b47d452c53cdac973d0bdd926e5c07a4f8dafb04033ec1e778de8c2ca34525cd494cc00cf87492058a5fad014473abf37e9f6f3399bba165dfb67fcba877b samba.logrotate diff --git a/main/samba/disable-compile-error-test.patch b/main/samba/disable-compile-error-test.patch new file mode 100644 index 00000000000..62777f8ac32 --- /dev/null +++ b/main/samba/disable-compile-error-test.patch @@ -0,0 +1,21 @@ +--- a/lib/ldb/tests/ldb_match_test.c ++++ b/lib/ldb/tests/ldb_match_test.c +@@ -32,6 +32,8 @@ + * This allows test applications to use custom definitions of C standard + * library functions and types. + */ ++// disabled on alpine ++#if 0 + #include + #include + #include +@@ -189,3 +191,9 @@ + + return cmocka_run_group_tests(tests, NULL, NULL); + } ++#else ++int main(int argc, const char **argv) ++{ ++ return 0; ++} ++#endif diff --git a/main/samba/ldb-tests.patch b/main/samba/ldb-tests.patch new file mode 100644 index 00000000000..3cc81c7bffb --- /dev/null +++ b/main/samba/ldb-tests.patch @@ -0,0 +1,13 @@ +diff --git a/lib/ldb/tests/test_ldb_comparison_fold.c b/lib/ldb/tests/test_ldb_comparison_fold.c +index 601cfe6..4fbb455 100644 +--- a/lib/ldb/tests/test_ldb_comparison_fold.c ++++ b/lib/ldb/tests/test_ldb_comparison_fold.c +@@ -52,7 +52,7 @@ struct ranked_value { + int rank; + }; + +-#define STR_VAL(s, r) { { discard_const(s), sizeof(s) - 1 }, r} ++#define STR_VAL(s, r) { { s, sizeof(s) - 1 }, r} + + static const struct ranked_value values_common[] = { + STR_VAL("", 0), diff --git a/main/samba/pycrypt.patch b/main/samba/pycrypt.patch new file mode 100644 index 00000000000..c92ace59b91 --- /dev/null +++ b/main/samba/pycrypt.patch @@ -0,0 +1,945 @@ +From 07fe7b437c695c7a715418d4414c930b72758dab Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Thu, 5 Dec 2024 16:35:51 +1300 +Subject: [PATCH 01/11] util: add a crypt wrapper, derived from + dsdb:password_hash + +This is going to be used by the dsdb password_hash module, and exposed +to Python via pyglue. + +We're doing this because Python 3.13 has dropped crypt from the Python +standard library. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(backported from commit 833455c7f9f71583d567e3a53e854567cd8c3b0b, +Signed-off-by added) +--- + lib/util/util_crypt.c | 90 ++++++++++++++++++++++++++++++++++++++++++ + lib/util/util_crypt.h | 5 +++ + lib/util/wscript_build | 6 +++ + 3 files changed, 101 insertions(+) + create mode 100644 lib/util/util_crypt.c + create mode 100644 lib/util/util_crypt.h + +diff --git a/lib/util/util_crypt.c b/lib/util/util_crypt.c +new file mode 100644 +index 00000000000..0f7b2d0fd31 +--- /dev/null ++++ b/lib/util/util_crypt.c +@@ -0,0 +1,90 @@ ++#include ++#include "data_blob.h" ++#include ++#include ++#include "util_crypt.h" ++ ++ ++static int crypt_as_best_we_can(const char *phrase, ++ const char *setting, ++ const char **hashp) ++{ ++ int ret = 0; ++ const char *hash = NULL; ++ ++#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN) ++ struct crypt_data crypt_data = { ++ .initialized = 0 /* working storage used by crypt */ ++ }; ++#endif ++ ++ /* ++ * crypt_r() and crypt() may return a null pointer upon error ++ * depending on how libcrypt was configured, so we prefer ++ * crypt_rn() from libcrypt / libxcrypt which always returns ++ * NULL on error. ++ * ++ * POSIX specifies returning a null pointer and setting ++ * errno. ++ * ++ * RHEL 7 (which does not use libcrypt / libxcrypt) returns a ++ * non-NULL pointer from crypt_r() on success but (always?) ++ * sets errno during internal processing in the NSS crypto ++ * subsystem. ++ * ++ * By preferring crypt_rn we avoid the 'return non-NULL but ++ * set-errno' that we otherwise cannot tell apart from the ++ * RHEL 7 behaviour. ++ */ ++ errno = 0; ++ ++#ifdef HAVE_CRYPT_RN ++ hash = crypt_rn(phrase, setting, ++ &crypt_data, ++ sizeof(crypt_data)); ++#elif HAVE_CRYPT_R ++ hash = crypt_r(phrase, setting, &crypt_data); ++#else ++ /* ++ * No crypt_r falling back to crypt, which is NOT thread safe ++ * Thread safety MT-Unsafe race:crypt ++ */ ++ hash = crypt(phrase, setting); ++#endif ++ /* ++ * On error, crypt() and crypt_r() may return a null pointer, ++ * or a pointer to an invalid hash beginning with a '*'. ++ */ ++ ret = errno; ++ errno = 0; ++ if (hash == NULL || hash[0] == '*') { ++ if (ret == 0) { ++ /* this is annoying */ ++ ret = ENOTRECOVERABLE; ++ } ++ } ++ ++ *hashp = hash; ++ return ret; ++} ++ ++ ++int talloc_crypt_blob(TALLOC_CTX *mem_ctx, ++ const char *phrase, ++ const char *setting, ++ DATA_BLOB *blob) ++{ ++ const char *hash = NULL; ++ int ret = crypt_as_best_we_can(phrase, setting, &hash); ++ if (ret != 0) { ++ blob->data = NULL; ++ blob->length = 0; ++ return ret; ++ } ++ blob->length = strlen(hash); ++ blob->data = talloc_memdup(mem_ctx, hash, blob->length); ++ if (blob->data == NULL) { ++ return ENOMEM; ++ } ++ return 0; ++} +diff --git a/lib/util/util_crypt.h b/lib/util/util_crypt.h +new file mode 100644 +index 00000000000..8c289e489e8 +--- /dev/null ++++ b/lib/util/util_crypt.h +@@ -0,0 +1,5 @@ ++ ++int talloc_crypt_blob(TALLOC_CTX *mem_ctx, ++ const char *phrase, ++ const char *cmd, ++ DATA_BLOB *blob); +diff --git a/lib/util/wscript_build b/lib/util/wscript_build +index b4fcfeaba07..7de9c0b7b17 100644 +--- a/lib/util/wscript_build ++++ b/lib/util/wscript_build +@@ -253,6 +253,12 @@ else: + private_library=True, + local_include=False) + ++ bld.SAMBA_LIBRARY('util_crypt', ++ source='util_crypt.c', ++ deps='talloc crypt', ++ private_library=True, ++ local_include=False) ++ + + bld.SAMBA_SUBSYSTEM('UNIX_PRIVS', + source='unix_privs.c', +-- +2.48.1 + + +From adf180613e4172292090d4c3573a439388a09788 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 14:29:21 +1300 +Subject: [PATCH 02/11] dsdb:password_hash: move hash_blob allocation up + +This will make the next patch simpler. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 1edb12f79593d0b2aac36d5acdaaae6f495772f6) +--- + source4/dsdb/samdb/ldb_modules/password_hash.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c +index 1d1267624e2..c1902126a72 100644 +--- a/source4/dsdb/samdb/ldb_modules/password_hash.c ++++ b/source4/dsdb/samdb/ldb_modules/password_hash.c +@@ -1649,6 +1649,13 @@ static int setup_primary_userPassword_hash( + } + } + ++ hash_blob = talloc_zero(ctx, DATA_BLOB); ++ ++ if (hash_blob == NULL) { ++ TALLOC_FREE(frame); ++ return ldb_oom(ldb); ++ } ++ + /* + * Relies on the assertion that cleartext_utf8->data is a zero + * terminated UTF-8 string +@@ -1712,15 +1719,10 @@ static int setup_primary_userPassword_hash( + scheme, + reason); + TALLOC_FREE(frame); ++ TALLOC_FREE(hash_blob); + return LDB_ERR_OPERATIONS_ERROR; + } + +- hash_blob = talloc_zero(ctx, DATA_BLOB); +- +- if (hash_blob == NULL) { +- TALLOC_FREE(frame); +- return ldb_oom(ldb); +- } + + *hash_blob = data_blob_talloc(hash_blob, + (const uint8_t *)hash, +-- +2.48.1 + + +From 9d43e4d649db23549bbb230ed60426fa286b7ab7 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Thu, 12 Dec 2024 11:16:22 +1300 +Subject: [PATCH 03/11] dsdb:password_hash: use talloc_crypt_blob() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit c7597380b479208e33a403211cec9b3c7bd3f034) +--- + .../dsdb/samdb/ldb_modules/password_hash.c | 68 ++++--------------- + .../samdb/ldb_modules/wscript_build_server | 2 +- + 2 files changed, 13 insertions(+), 57 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c +index c1902126a72..7a7114c1caa 100644 +--- a/source4/dsdb/samdb/ldb_modules/password_hash.c ++++ b/source4/dsdb/samdb/ldb_modules/password_hash.c +@@ -51,6 +51,7 @@ + #include "auth/common_auth.h" + #include "lib/messaging/messaging.h" + #include "lib/param/loadparm.h" ++#include "lib/util/util_crypt.h" + + #include "lib/crypto/gnutls_helpers.h" + #include +@@ -1592,16 +1593,11 @@ static int setup_primary_userPassword_hash( + struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module); + const char *salt = NULL; /* Randomly generated salt */ + const char *cmd = NULL; /* command passed to crypt */ +- const char *hash = NULL; /* password hash generated by crypt */ + int algorithm = 0; /* crypt hash algorithm number */ + int rounds = 0; /* The number of hash rounds */ ++ int ret; + DATA_BLOB *hash_blob = NULL; + TALLOC_CTX *frame = talloc_stackframe(); +-#if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT_RN) +- struct crypt_data crypt_data = { +- .initialized = 0 /* working storage used by crypt */ +- }; +-#endif + + /* Generate a random password salt */ + salt = generate_random_str_list(frame, +@@ -1660,52 +1656,20 @@ static int setup_primary_userPassword_hash( + * Relies on the assertion that cleartext_utf8->data is a zero + * terminated UTF-8 string + */ +- +- /* +- * crypt_r() and crypt() may return a null pointer upon error +- * depending on how libcrypt was configured, so we prefer +- * crypt_rn() from libcrypt / libxcrypt which always returns +- * NULL on error. +- * +- * POSIX specifies returning a null pointer and setting +- * errno. +- * +- * RHEL 7 (which does not use libcrypt / libxcrypt) returns a +- * non-NULL pointer from crypt_r() on success but (always?) +- * sets errno during internal processing in the NSS crypto +- * subsystem. +- * +- * By preferring crypt_rn we avoid the 'return non-NULL but +- * set-errno' that we otherwise cannot tell apart from the +- * RHEL 7 behaviour. +- */ +- errno = 0; +- +-#ifdef HAVE_CRYPT_RN +- hash = crypt_rn((char *)io->n.cleartext_utf8->data, +- cmd, +- &crypt_data, +- sizeof(crypt_data)); +-#elif HAVE_CRYPT_R +- hash = crypt_r((char *)io->n.cleartext_utf8->data, cmd, &crypt_data); +-#else +- /* +- * No crypt_r falling back to crypt, which is NOT thread safe +- * Thread safety MT-Unsafe race:crypt +- */ +- hash = crypt((char *)io->n.cleartext_utf8->data, cmd); +-#endif +- /* +- * On error, crypt() and crypt_r() may return a null pointer, +- * or a pointer to an invalid hash beginning with a '*'. +- */ +- if (hash == NULL || hash[0] == '*') { ++ ret = talloc_crypt_blob(hash_blob, ++ (char *)io->n.cleartext_utf8->data, ++ cmd, ++ hash_blob); ++ if (ret != 0) { + char buf[1024]; + const char *reason = NULL; +- if (errno == ERANGE) { ++ if (ret == ERANGE) { + reason = "Password exceeds maximum length allowed for crypt() hashing"; ++ } else if (ret == ENOTRECOVERABLE) { ++ /* probably weird RHEL7 crypt, see talloc_crypt_blob() */ ++ reason = "Unknown error"; + } else { +- int err = strerror_r(errno, buf, sizeof(buf)); ++ int err = strerror_r(ret, buf, sizeof(buf)); + if (err == 0) { + reason = buf; + } else { +@@ -1723,14 +1687,6 @@ static int setup_primary_userPassword_hash( + return LDB_ERR_OPERATIONS_ERROR; + } + +- +- *hash_blob = data_blob_talloc(hash_blob, +- (const uint8_t *)hash, +- strlen(hash)); +- if (hash_blob->data == NULL) { +- TALLOC_FREE(frame); +- return ldb_oom(ldb); +- } + hash_value->value = hash_blob; + TALLOC_FREE(frame); + return LDB_SUCCESS; +diff --git a/source4/dsdb/samdb/ldb_modules/wscript_build_server b/source4/dsdb/samdb/ldb_modules/wscript_build_server +index 9c1eb12a7c2..16d9b31a982 100644 +--- a/source4/dsdb/samdb/ldb_modules/wscript_build_server ++++ b/source4/dsdb/samdb/ldb_modules/wscript_build_server +@@ -195,7 +195,7 @@ bld.SAMBA_MODULE('ldb_password_hash', + init_function='ldb_password_hash_module_init', + module_init_name='ldb_init_module', + internal_module=False, +- deps='talloc samdb LIBCLI_AUTH NDR_DRSBLOBS authkrb5 krb5 gpgme DSDB_MODULE_HELPERS crypt db-glue' ++ deps='talloc samdb LIBCLI_AUTH NDR_DRSBLOBS authkrb5 krb5 gpgme DSDB_MODULE_HELPERS util_crypt db-glue' + ) + + +-- +2.48.1 + + +From 1c94645881bd5130c67bfee96aa463f360df300a Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 14:30:04 +1300 +Subject: [PATCH 04/11] util: add a crypt strerror helper + +This will be used by Python also. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 5f365e71c1fa8cdc533159283a5977164b5d39f2) +--- + lib/util/util_crypt.c | 24 +++++++++++++++++++ + lib/util/util_crypt.h | 2 ++ + .../dsdb/samdb/ldb_modules/password_hash.c | 16 +------------ + 3 files changed, 27 insertions(+), 15 deletions(-) + +diff --git a/lib/util/util_crypt.c b/lib/util/util_crypt.c +index 0f7b2d0fd31..09cd47597d1 100644 +--- a/lib/util/util_crypt.c ++++ b/lib/util/util_crypt.c +@@ -88,3 +88,27 @@ int talloc_crypt_blob(TALLOC_CTX *mem_ctx, + } + return 0; + } ++ ++ ++char *talloc_crypt_errstring(TALLOC_CTX *mem_ctx, int error) ++{ ++ char buf[1024]; ++ int err; ++ if (error == ERANGE) { ++ return talloc_strdup( ++ mem_ctx, ++ "Password exceeds maximum length allowed for crypt() hashing"); ++ } ++ if (error == ENOTRECOVERABLE) { ++ /* probably weird RHEL7 crypt, see crypt_as_best_we_can() */ ++ goto unknown; ++ } ++ ++ err = strerror_r(error, buf, sizeof(buf)); ++ if (err != 0) { ++ goto unknown; ++ } ++ return talloc_strndup(mem_ctx, buf, sizeof(buf)); ++unknown: ++ return talloc_strdup(mem_ctx, "Unknown error"); ++} +diff --git a/lib/util/util_crypt.h b/lib/util/util_crypt.h +index 8c289e489e8..ca1a58e922c 100644 +--- a/lib/util/util_crypt.h ++++ b/lib/util/util_crypt.h +@@ -3,3 +3,5 @@ int talloc_crypt_blob(TALLOC_CTX *mem_ctx, + const char *phrase, + const char *cmd, + DATA_BLOB *blob); ++ ++char *talloc_crypt_errstring(TALLOC_CTX *mem_ctx, int error); +diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c +index 7a7114c1caa..6949a92fc3e 100644 +--- a/source4/dsdb/samdb/ldb_modules/password_hash.c ++++ b/source4/dsdb/samdb/ldb_modules/password_hash.c +@@ -1661,21 +1661,7 @@ static int setup_primary_userPassword_hash( + cmd, + hash_blob); + if (ret != 0) { +- char buf[1024]; +- const char *reason = NULL; +- if (ret == ERANGE) { +- reason = "Password exceeds maximum length allowed for crypt() hashing"; +- } else if (ret == ENOTRECOVERABLE) { +- /* probably weird RHEL7 crypt, see talloc_crypt_blob() */ +- reason = "Unknown error"; +- } else { +- int err = strerror_r(ret, buf, sizeof(buf)); +- if (err == 0) { +- reason = buf; +- } else { +- reason = "Unknown error"; +- } +- } ++ const char *reason = talloc_crypt_errstring(frame, ret); + ldb_asprintf_errstring( + ldb, + "setup_primary_userPassword: generation of a %s " +-- +2.48.1 + + +From ce70e852783ec69104d274def931e7d39f17576a Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 14:30:15 +1300 +Subject: [PATCH 05/11] pyglue: add crypt() function + +This wraps talloc_crypt_blob() from lib/util/util_crypt.c which in +turn wraps the system crypt[_r[n]]. + +We want this because the Python standard library crypt module is going +away. That one also wrapped the system crypt or crypt_r, so there +should be no change. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(backported from commit 88e3c82d88a68cf972f8189e1c3718698b49974a) +--- + python/pyglue.c | 41 +++++++++++++++++++++++++++++++++++++++++ + python/wscript | 1 + + 2 files changed, 42 insertions(+) + +diff --git a/python/pyglue.c b/python/pyglue.c +index 042bf9e14f3..fcccb849f5e 100644 +--- a/python/pyglue.c ++++ b/python/pyglue.c +@@ -18,6 +18,7 @@ + */ + + #include "lib/replace/system/python.h" ++#include "pyerrors.h" + #include "python/py3compat.h" + #include "includes.h" + #include "python/modules.h" +@@ -25,6 +26,7 @@ + #include "param/pyparam.h" + #include "lib/socket/netif.h" + #include "lib/util/debug.h" ++#include "lib/util/util_crypt.h" + #include "librpc/ndr/ndr_private.h" + #include "lib/cmdline/cmdline.h" + #include "lib/crypto/gkdi.h" +@@ -519,6 +521,42 @@ static PyObject *py_get_burnt_commandline(PyObject *self, PyObject *args) + return ret; + } + ++static PyObject *py_crypt(PyObject *self, PyObject *args) ++{ ++ PyObject *py_hash = NULL; ++ char *phrase = NULL; ++ char *setting = NULL; ++ TALLOC_CTX *frame = NULL; ++ int ret; ++ DATA_BLOB hash = {}; ++ ++ if (!PyArg_ParseTuple(args, "ss", &phrase, &setting)) { ++ TALLOC_FREE(frame); ++ return NULL; ++ } ++ frame = talloc_stackframe(); ++ ret = talloc_crypt_blob(frame, phrase, setting, &hash); ++ if (ret != 0) { ++ const char *errstr = talloc_crypt_errstring(frame, ret); ++ if (ret == EINVAL || ret == ERANGE || ret == ENOTRECOVERABLE) { ++ PyErr_Format(PyExc_ValueError, ++ "could not crypt(): %s", ++ errstr); ++ } else { ++ PyErr_Format(PyExc_OSError, ++ "could not crypt(): %s", ++ errstr); ++ } ++ TALLOC_FREE(frame); ++ return NULL; ++ } ++ ++ py_hash = PyUnicode_FromStringAndSize((char *)hash.data, hash.length); ++ TALLOC_FREE(frame); ++ return py_hash; ++} ++ ++ + static PyMethodDef py_misc_methods[] = { + { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS, + "generate_random_str(len) -> string\n" +@@ -580,6 +618,9 @@ static PyMethodDef py_misc_methods[] = { + METH_NOARGS, "How many NDR internal tokens is too many for this build?" }, + { "get_burnt_commandline", (PyCFunction)py_get_burnt_commandline, + METH_VARARGS, "Return a redacted commandline to feed to setproctitle (None if no redaction required)" }, ++ { "crypt", (PyCFunction)py_crypt, ++ METH_VARARGS, ++ "encrypt as phrase, per crypt(3), as determined by setting." }, + {0} + }; + +diff --git a/python/wscript b/python/wscript +index 3e6439930e9..7c17e390dc7 100644 +--- a/python/wscript ++++ b/python/wscript +@@ -119,6 +119,7 @@ def build(bld): + ndr + cmdline + gkdi ++ util_crypt + %s + ''' % (pyparam_util, pytalloc_util), + realname='samba/_glue.so') +-- +2.48.1 + + +From 9a0dc2db7cde22f36583159c0d697a3de6640990 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Thu, 12 Dec 2024 10:44:07 +1300 +Subject: [PATCH 06/11] pytest: test that _glue.crypt works + +The test vectors were generated via Python 3.10 crypt module, which +directly wraps crypt(3), which in this case is from glibc 2.39-0ubuntu8.3. + +We mainly test the sha256 and sha512 vectors, which seems to be all we +use, and which are said to be widely supported. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 5636d30c0959fd4a211ee7b8d1b267dcdbf0b963) +--- + python/samba/tests/glue.py | 65 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/python/samba/tests/glue.py b/python/samba/tests/glue.py +index ac504b3f366..824f5ca0c81 100644 +--- a/python/samba/tests/glue.py ++++ b/python/samba/tests/glue.py +@@ -88,3 +88,68 @@ class GlueTests(samba.tests.TestCase): + self.assertEqual(_glue.strstr_m(string, '_'), '_string_num__one') + self.assertEqual(_glue.strstr_m(string, '__'), '__one') + self.assertEqual(_glue.strstr_m(string, 'ring'), 'ring_num__one') ++ ++ def test_crypt(self): ++ # We hopefully only use schemes 5 and 6 (sha256 and sha512), ++ # which are OK and also quite widely supported according to ++ # https://en.wikipedia.org/wiki/Crypt_(C) ++ for phrase, setting, expected in [ ++ ("a", "$5$aaaaaa", ++ "$5$aaaaaa$F4lxguL7mZR7TGlvukPTJIxoRhVmHMZs8ZdH8oDP0.6"), ++ # with scheme 5, 5000 rounds is default, so hash is the same as above ++ ('a', '$5$rounds=5000$aaaaaa', ++ '$5$rounds=5000$aaaaaa$F4lxguL7mZR7TGlvukPTJIxoRhVmHMZs8ZdH8oDP0.6'), ++ ('a', ++ '$5$rounds=4999$aaaaaa', ++ '$5$rounds=4999$aaaaaa$FiP70gtxOJUFLokUJvET06E7jbL6aNmF6Wtv2ddzjY8'), ++ ('a', '$5$aaaaab', ++ '$5$aaaaab$e9qR2F833/JyuMu.nkQc9kn184vBWLo0ODqnCe./mj0'), ++ ++ ('', '$5$aaaaaa', '$5$aaaaaa$5B4WTdWp5n/v/aNUw2N8RsEitqvlZJEaAKhH/pOkGg4'), ++ ++ ("a", "$6$aaaaaa", ++ "$6$aaaaaa$KHs/Ez7X/I5/K.V8FR7kEsx9rOvjXnEDUmGC.dLBWP87XWy.oUEAM7QYcZQRVhiDwGepOF2pKrCVETYLyASh60"), ++ ++ ('', '$5$', '$5$$3c2QQ0KjIU1OLtB29cl8Fplc2WN7X89bnoEjaR7tWu.'), ++ ++ # scheme 1 (md5) should be supported if not used ++ ('a', '$1$aaaaaa', ++ '$1$aaaaaa$MUMWPbGfzrHFCNm7ZHg31.'), ++ ++ ('', '$6$', ++ '$6$$/chiBau24cE26QQVW3IfIe68Xu5.JQ4E8Ie7lcRLwqxO5cxGuBhqF2HmTL.zWJ9zjChg3yJYFXeGBQ2y3Ba1d1'), ++ (' ', ++ '$6$6', ++ '$6$6$asLnbxf0obyuv3ybNvDE9ZcdwGFkDhLe7uW.wzdOdKCm4/M3vGFKq4Ttk1tBQrOn4wALZ3tj1L8IarIu5i8hR/'), ++ ++ # original DES scheme, 12 bits of salt ++ ("a", "lalala", "laKGbFzgh./R2"), ++ ("a", "lalalaLALALAla", "laKGbFzgh./R2"), ++ ("a", "arrgh", "ar7VUiUvDhX2c"), ++ ("a", "arrggghhh", "ar7VUiUvDhX2c"), ++ ]: ++ hash = _glue.crypt(phrase, setting) ++ self.assertEqual(hash, expected) ++ ++ def test_crypt_bad(self): ++ # We can't be too strident in our assertions, because every ++ # system allows a different set of algorithms, and some have ++ # different ideas of how to parse. ++ for phrase, setting, exception in [ ++ ("a", "$5", ValueError), ++ ("a", "$0$", ValueError), ++ ("a", None, TypeError), ++ (None, "", TypeError), ++ ('a', '$66$', ValueError), ++ ('a', '$$', ValueError), ++ ('a', '*0', ValueError), ++ ('a', '*', ValueError), ++ ('a', '++', ValueError), ++ # this next one is too long, except on Rocky Linux 8. ++ #('a' * 10000, '$5$5', ValueError), ++ # this is invalid, except on Debian 11. ++ # (' ', '$6$ ', ValueError), ++ ]: ++ with self.assertRaises(exception, ++ msg=f"crypt({phrase!r}, {setting!r}) didn't fail"): ++ _glue.crypt(phrase, setting) +-- +2.48.1 + + +From 6425e2514052027ee2269e15e0e0dff1686fa34e Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 15:54:48 +1300 +Subject: [PATCH 07/11] samba-tool user: use _glue.crypt, not crypt.crypt + +Because we know we have _glue.crypt, and we know it raises exceptions +rather than returning None, we can simplify the checks. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 405187d2ef4920a9a284649c9c3287f5844d5180) +--- + .../samba/netcmd/user/readpasswords/common.py | 21 ++++++------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/python/samba/netcmd/user/readpasswords/common.py b/python/samba/netcmd/user/readpasswords/common.py +index 7944d4e1682..68befb3f356 100644 +--- a/python/samba/netcmd/user/readpasswords/common.py ++++ b/python/samba/netcmd/user/readpasswords/common.py +@@ -37,6 +37,7 @@ from samba.netcmd import Command, CommandError + from samba.samdb import SamDB + from samba.nt_time import timedelta_from_nt_time_delta, nt_time_from_datetime + from samba.gkdi import MAX_CLOCK_SKEW ++from samba._glue import crypt + + # python[3]-gpgme is abandoned since ubuntu 1804 and debian 9 + # have to use python[3]-gpg instead +@@ -132,9 +133,7 @@ def get_crypt_value(alg, utf8pw, rounds=0): + else: + crypt_salt = "$%s$%s$" % (alg, b64salt) + +- crypt_value = crypt.crypt(utf8pw, crypt_salt) +- if crypt_value is None: +- raise NotImplementedError("crypt.crypt(%s) returned None" % (crypt_salt)) ++ crypt_value = crypt(utf8pw, crypt_salt) + expected_len = len(crypt_salt) + algs[alg]["length"] + if len(crypt_value) != expected_len: + raise NotImplementedError("crypt.crypt(%s) returned a value with length %d, expected length is %d" % ( +@@ -156,21 +155,13 @@ except ImportError as e: + + for (alg, attr) in [("5", "virtualCryptSHA256"), ("6", "virtualCryptSHA512")]: + try: +- import crypt + get_crypt_value(alg, "") +- virtual_attributes[attr] = { +- } +- except ImportError as e: +- reason = "crypt" +- reason += " required" +- disabled_virtual_attributes[attr] = { +- "reason": reason, +- } +- except NotImplementedError as e: +- reason = "modern '$%s$' salt in crypt(3) required" % (alg) ++ except (ValueError, OSError): + disabled_virtual_attributes[attr] = { +- "reason": reason, ++ "reason": f"modern '${alg}$' salt in crypt(3) required" + } ++ continue ++ virtual_attributes[attr] = {} + + # Add the wDigest virtual attributes, virtualWDigest01 to virtualWDigest29 + for x in range(1, 30): +-- +2.48.1 + + +From a2a04286e13676177c952e67363fc7502f544861 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 15:56:20 +1300 +Subject: [PATCH 08/11] samba-tool user: hashlib.sha1 is always present + +We maybe thought we were checking that sha1 was in hashlib, but we were +only checking that hashlib is in the Python library (`hashlib.sha1()` +would not raise ImportError). + +The documentation says hashlib always contains sha1 -- if that +changes, it is better we know by failing noisily with the import error +at the top of the file. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 4af4dd8135e8edbe2a16cfdfc7ded8c145c82e98) +--- + python/samba/netcmd/user/readpasswords/common.py | 16 ++++------------ + 1 file changed, 4 insertions(+), 12 deletions(-) + +diff --git a/python/samba/netcmd/user/readpasswords/common.py b/python/samba/netcmd/user/readpasswords/common.py +index 68befb3f356..3043525874e 100644 +--- a/python/samba/netcmd/user/readpasswords/common.py ++++ b/python/samba/netcmd/user/readpasswords/common.py +@@ -26,6 +26,7 @@ import datetime + import errno + import io + import os ++from hashlib import sha1 + + import ldb + from samba import credentials, nttime2float +@@ -141,17 +142,8 @@ def get_crypt_value(alg, utf8pw, rounds=0): + return crypt_value + + +-try: +- import hashlib +- hashlib.sha1() +- virtual_attributes["virtualSSHA"] = { +- } +-except ImportError as e: +- reason = "hashlib.sha1()" +- reason += " required" +- disabled_virtual_attributes["virtualSSHA"] = { +- "reason": reason, +- } ++ ++virtual_attributes["virtualSSHA"] = {} + + for (alg, attr) in [("5", "virtualCryptSHA256"), ("6", "virtualCryptSHA512")]: + try: +@@ -736,7 +728,7 @@ class GetPasswordCommand(Command): + if u8 is None: + continue + salt = os.urandom(4) +- h = hashlib.sha1() ++ h = sha1() + h.update(u8) + h.update(salt) + bv = h.digest() + salt +-- +2.48.1 + + +From e9a8748f3cc4ba74f8b0d75e7a01866e7c12a0a4 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Thu, 12 Dec 2024 10:46:16 +1300 +Subject: [PATCH 09/11] pytest: password_hash uses internal _glue.crypt + +This will remove an external dependency. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider +(cherry picked from commit 552053b6445611ecef6ac4c11c55ebf92f03571d) +--- + python/samba/tests/password_hash.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/python/samba/tests/password_hash.py b/python/samba/tests/password_hash.py +index 1b7af7de7b8..39ef13fd7b2 100644 +--- a/python/samba/tests/password_hash.py ++++ b/python/samba/tests/password_hash.py +@@ -30,11 +30,11 @@ from samba.dcerpc.samr import DOMAIN_PASSWORD_STORE_CLEARTEXT + from samba.dsdb import UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED + from samba.tests import delete_force + from samba.tests.password_test import PasswordCommon ++from samba._glue import crypt + import ldb + import samba + import binascii + from hashlib import md5 +-import crypt + + + USER_NAME = "PasswordHashTestUser" +@@ -321,7 +321,7 @@ class PassWordHashTests(TestCase): + cmd = "$%s$rounds=%d$%s" % (alg, rounds, data[3]) + + # Calculate the expected hash value +- expected = crypt.crypt(USER_PASS, cmd) ++ expected = crypt(USER_PASS, cmd) + self.assertEqual(expected, up.hashes[i].value.decode('utf8')) + i += 1 + +-- +2.48.1 + + +From 0e01dc4f1fabfd2c3f21f724c05d94227a278b20 Mon Sep 17 00:00:00 2001 +From: Douglas Bagnall +Date: Wed, 11 Dec 2024 14:31:18 +1300 +Subject: [PATCH 10/11] util:datablob: data_blob_pad checks its alignment + assumption + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15756 + +Signed-off-by: Douglas Bagnall +Reviewed-by: Andreas Schneider + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Fri Dec 20 07:59:51 UTC 2024 on atb-devel-224 + +(cherry picked from commit 8b84282008dc372d67ba01c8fe256ef756c3dcfb) +--- + lib/util/data_blob.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/util/data_blob.c b/lib/util/data_blob.c +index b5b78bc7a8a..0522e7755af 100644 +--- a/lib/util/data_blob.c ++++ b/lib/util/data_blob.c +@@ -286,7 +286,7 @@ _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + size_t old_len = blob->length; + size_t new_len = (old_len + pad - 1) & ~(pad - 1); + +- if (new_len < old_len) { ++ if (new_len < old_len || (pad & (pad - 1)) != 0) { + return false; + } + +-- +2.48.1 + + +From 8cfae9f33fb1c170c3fe937be200490597e9e4c2 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Fri, 17 Jan 2025 13:28:30 +0100 +Subject: [PATCH 11/11] lib:util: Fix stack-use-after-return in + crypt_as_best_we_can() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15784 + +Signed-off-by: Andreas Schneider +Reviewed-by: Douglas Bagnall +Reviewed-by: Pavel Filipenský + +Autobuild-User(master): Douglas Bagnall +Autobuild-Date(master): Fri Jan 17 23:21:13 UTC 2025 on atb-devel-224 + +(cherry picked from commit 6cd9849b58ec653cbffc602e3c96996a082faf53) +--- + lib/util/util_crypt.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/lib/util/util_crypt.c b/lib/util/util_crypt.c +index 09cd47597d1..9ac6e1cfd0e 100644 +--- a/lib/util/util_crypt.c ++++ b/lib/util/util_crypt.c +@@ -1,11 +1,13 @@ + #include + #include "data_blob.h" ++#include "discard.h" + #include + #include + #include "util_crypt.h" + + +-static int crypt_as_best_we_can(const char *phrase, ++static int crypt_as_best_we_can(TALLOC_CTX *mem_ctx, ++ const char *phrase, + const char *setting, + const char **hashp) + { +@@ -63,8 +65,14 @@ static int crypt_as_best_we_can(const char *phrase, + ret = ENOTRECOVERABLE; + } + } ++ if (ret != 0) { ++ return ret; ++ } + +- *hashp = hash; ++ *hashp = talloc_strdup(mem_ctx, hash); ++ if (*hashp == NULL) { ++ ret = -1; ++ } + return ret; + } + +@@ -75,14 +83,14 @@ int talloc_crypt_blob(TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) + { + const char *hash = NULL; +- int ret = crypt_as_best_we_can(phrase, setting, &hash); ++ int ret = crypt_as_best_we_can(mem_ctx, phrase, setting, &hash); + if (ret != 0) { + blob->data = NULL; + blob->length = 0; + return ret; + } + blob->length = strlen(hash); +- blob->data = talloc_memdup(mem_ctx, hash, blob->length); ++ blob->data = discard_const_p(uint8_t, hash); + if (blob->data == NULL) { + return ENOMEM; + } +-- +2.48.1 + diff --git a/main/samba/s3-notifyd.patch b/main/samba/s3-notifyd.patch new file mode 100644 index 00000000000..31463fd8884 --- /dev/null +++ b/main/samba/s3-notifyd.patch @@ -0,0 +1,513 @@ +From c9a7bc3e8f36cb9d6746e23ea56f9c27b82dcf49 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 22 Jul 2024 12:26:55 +0200 +Subject: [PATCH] s3:notifyd: Use a watcher per db record +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes a O(n²) performance regression in notifyd. The problem was +that we had a watcher per notify instance. This changes the code to have +a watcher per notify db entry. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14430 + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit af011b987a4ad0d3753d83cc0b8d97ad64ba874a) +--- + source3/smbd/notifyd/notifyd.c | 214 ++++++++++++++++++------- + source3/smbd/notifyd/notifyd_db.c | 5 +- + source3/smbd/notifyd/notifyd_entry.c | 51 ++++-- + source3/smbd/notifyd/notifyd_private.h | 46 ++++-- + 4 files changed, 228 insertions(+), 88 deletions(-) + +diff --git a/source3/smbd/notifyd/notifyd.c b/source3/smbd/notifyd/notifyd.c +index 64dd26a7e11..0b07ab3e435 100644 +--- a/source3/smbd/notifyd/notifyd.c ++++ b/source3/smbd/notifyd/notifyd.c +@@ -337,6 +337,7 @@ static bool notifyd_apply_rec_change( + struct messaging_context *msg_ctx) + { + struct db_record *rec = NULL; ++ struct notifyd_watcher watcher = {}; + struct notifyd_instance *instances = NULL; + size_t num_instances; + size_t i; +@@ -344,6 +345,7 @@ static bool notifyd_apply_rec_change( + TDB_DATA value; + NTSTATUS status; + bool ok = false; ++ bool new_watcher = false; + + if (pathlen == 0) { + DBG_WARNING("pathlen==0\n"); +@@ -374,8 +376,12 @@ static bool notifyd_apply_rec_change( + value = dbwrap_record_get_value(rec); + + if (value.dsize != 0) { +- if (!notifyd_parse_entry(value.dptr, value.dsize, NULL, +- &num_instances)) { ++ ok = notifyd_parse_entry(value.dptr, ++ value.dsize, ++ &watcher, ++ NULL, ++ &num_instances); ++ if (!ok) { + goto fail; + } + } +@@ -390,8 +396,22 @@ static bool notifyd_apply_rec_change( + goto fail; + } + +- if (value.dsize != 0) { +- memcpy(instances, value.dptr, value.dsize); ++ if (num_instances > 0) { ++ struct notifyd_instance *tmp = NULL; ++ size_t num_tmp = 0; ++ ++ ok = notifyd_parse_entry(value.dptr, ++ value.dsize, ++ NULL, ++ &tmp, ++ &num_tmp); ++ if (!ok) { ++ goto fail; ++ } ++ ++ memcpy(instances, ++ tmp, ++ sizeof(struct notifyd_instance) * num_tmp); + } + + for (i=0; ifilter, +- .internal_subdir_filter = chg->subdir_filter + }; + + num_instances += 1; + } + +- if ((instance->instance.filter != 0) || +- (instance->instance.subdir_filter != 0)) { +- int ret; ++ /* ++ * Calculate an intersection of the instances filters for the watcher. ++ */ ++ if (instance->instance.filter > 0) { ++ uint32_t filter = instance->instance.filter; ++ ++ if ((watcher.filter & filter) != filter) { ++ watcher.filter |= filter; ++ ++ new_watcher = true; ++ } ++ } ++ ++ /* ++ * Calculate an intersection of the instances subdir_filters for the ++ * watcher. ++ */ ++ if (instance->instance.subdir_filter > 0) { ++ uint32_t subdir_filter = instance->instance.subdir_filter; + +- TALLOC_FREE(instance->sys_watch); ++ if ((watcher.subdir_filter & subdir_filter) != subdir_filter) { ++ watcher.subdir_filter |= subdir_filter; + +- ret = sys_notify_watch(entries, sys_notify_ctx, path, +- &instance->internal_filter, +- &instance->internal_subdir_filter, +- notifyd_sys_callback, msg_ctx, +- &instance->sys_watch); +- if (ret != 0) { +- DBG_WARNING("sys_notify_watch for [%s] returned %s\n", +- path, strerror(errno)); ++ new_watcher = true; + } + } + + if ((instance->instance.filter == 0) && + (instance->instance.subdir_filter == 0)) { ++ uint32_t tmp_filter = 0; ++ uint32_t tmp_subdir_filter = 0; ++ + /* This is a delete request */ +- TALLOC_FREE(instance->sys_watch); + *instance = instances[num_instances-1]; + num_instances -= 1; ++ ++ for (i = 0; i < num_instances; i++) { ++ struct notifyd_instance *tmp = &instances[i]; ++ ++ tmp_filter |= tmp->instance.filter; ++ tmp_subdir_filter |= tmp->instance.subdir_filter; ++ } ++ ++ /* ++ * If the filter has changed, register a new watcher with the ++ * changed filter. ++ */ ++ if (watcher.filter != tmp_filter || ++ watcher.subdir_filter != tmp_subdir_filter) ++ { ++ watcher.filter = tmp_filter; ++ watcher.subdir_filter = tmp_subdir_filter; ++ ++ new_watcher = true; ++ } ++ } ++ ++ if (new_watcher) { ++ /* ++ * In case we removed all notify instances, we want to remove ++ * the watcher. We won't register a new one, if no filters are ++ * set anymore. ++ */ ++ ++ TALLOC_FREE(watcher.sys_watch); ++ ++ watcher.sys_filter = watcher.filter; ++ watcher.sys_subdir_filter = watcher.subdir_filter; ++ ++ /* ++ * Only register a watcher if we have filter. ++ */ ++ if (watcher.filter != 0 || watcher.subdir_filter != 0) { ++ int ret = sys_notify_watch(entries, ++ sys_notify_ctx, ++ path, ++ &watcher.sys_filter, ++ &watcher.sys_subdir_filter, ++ notifyd_sys_callback, ++ msg_ctx, ++ &watcher.sys_watch); ++ if (ret != 0) { ++ DBG_WARNING("sys_notify_watch for [%s] " ++ "returned %s\n", ++ path, ++ strerror(errno)); ++ } ++ } + } + + DBG_DEBUG("%s has %zu instances\n", path, num_instances); + + if (num_instances == 0) { ++ TALLOC_FREE(watcher.sys_watch); ++ + status = dbwrap_record_delete(rec); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("dbwrap_record_delete returned %s\n", +@@ -456,13 +541,21 @@ static bool notifyd_apply_rec_change( + goto fail; + } + } else { +- value = make_tdb_data( +- (uint8_t *)instances, +- sizeof(struct notifyd_instance) * num_instances); ++ struct TDB_DATA iov[2] = { ++ { ++ .dptr = (uint8_t *)&watcher, ++ .dsize = sizeof(struct notifyd_watcher), ++ }, ++ { ++ .dptr = (uint8_t *)instances, ++ .dsize = sizeof(struct notifyd_instance) * ++ num_instances, ++ }, ++ }; + +- status = dbwrap_record_store(rec, value, 0); ++ status = dbwrap_record_storev(rec, iov, ARRAY_SIZE(iov), 0); + if (!NT_STATUS_IS_OK(status)) { +- DBG_WARNING("dbwrap_record_store returned %s\n", ++ DBG_WARNING("dbwrap_record_storev returned %s\n", + nt_errstr(status)); + goto fail; + } +@@ -706,12 +799,18 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data, + .when = tstate->msg->when }; + struct iovec iov[2]; + size_t path_len = key.dsize; ++ struct notifyd_watcher watcher = {}; + struct notifyd_instance *instances = NULL; + size_t num_instances = 0; + size_t i; ++ bool ok; + +- if (!notifyd_parse_entry(data.dptr, data.dsize, &instances, +- &num_instances)) { ++ ok = notifyd_parse_entry(data.dptr, ++ data.dsize, ++ &watcher, ++ &instances, ++ &num_instances); ++ if (!ok) { + DBG_DEBUG("Could not parse notifyd_entry\n"); + return; + } +@@ -734,9 +833,11 @@ static void notifyd_trigger_parser(TDB_DATA key, TDB_DATA data, + + if (tstate->covered_by_sys_notify) { + if (tstate->recursive) { +- i_filter = instance->internal_subdir_filter; ++ i_filter = watcher.sys_subdir_filter & ++ instance->instance.subdir_filter; + } else { +- i_filter = instance->internal_filter; ++ i_filter = watcher.sys_filter & ++ instance->instance.filter; + } + } else { + if (tstate->recursive) { +@@ -1146,46 +1247,39 @@ static int notifyd_add_proxy_syswatches(struct db_record *rec, + struct db_context *db = dbwrap_record_get_db(rec); + TDB_DATA key = dbwrap_record_get_key(rec); + TDB_DATA value = dbwrap_record_get_value(rec); +- struct notifyd_instance *instances = NULL; +- size_t num_instances = 0; +- size_t i; ++ struct notifyd_watcher watcher = {}; + char path[key.dsize+1]; + bool ok; ++ int ret; + + memcpy(path, key.dptr, key.dsize); + path[key.dsize] = '\0'; + +- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances, +- &num_instances); ++ /* This is a remote database, we just need the watcher. */ ++ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL); + if (!ok) { + DBG_WARNING("Could not parse notifyd entry for %s\n", path); + return 0; + } + +- for (i=0; iinstance.filter; +- uint32_t subdir_filter = instance->instance.subdir_filter; +- int ret; ++ watcher.sys_watch = NULL; ++ watcher.sys_filter = watcher.filter; ++ watcher.sys_subdir_filter = watcher.subdir_filter; + +- /* +- * This is a remote database. Pointers that we were +- * given don't make sense locally. Initialize to NULL +- * in case sys_notify_watch fails. +- */ +- instances[i].sys_watch = NULL; +- +- ret = state->sys_notify_watch( +- db, state->sys_notify_ctx, path, +- &filter, &subdir_filter, +- notifyd_sys_callback, state->msg_ctx, +- &instance->sys_watch); +- if (ret != 0) { +- DBG_WARNING("inotify_watch returned %s\n", +- strerror(errno)); +- } ++ ret = state->sys_notify_watch(db, ++ state->sys_notify_ctx, ++ path, ++ &watcher.filter, ++ &watcher.subdir_filter, ++ notifyd_sys_callback, ++ state->msg_ctx, ++ &watcher.sys_watch); ++ if (ret != 0) { ++ DBG_WARNING("inotify_watch returned %s\n", strerror(errno)); + } + ++ memcpy(value.dptr, &watcher, sizeof(struct notifyd_watcher)); ++ + return 0; + } + +@@ -1193,21 +1287,17 @@ static int notifyd_db_del_syswatches(struct db_record *rec, void *private_data) + { + TDB_DATA key = dbwrap_record_get_key(rec); + TDB_DATA value = dbwrap_record_get_value(rec); +- struct notifyd_instance *instances = NULL; +- size_t num_instances = 0; +- size_t i; ++ struct notifyd_watcher watcher = {}; + bool ok; + +- ok = notifyd_parse_entry(value.dptr, value.dsize, &instances, +- &num_instances); ++ ok = notifyd_parse_entry(value.dptr, value.dsize, &watcher, NULL, NULL); + if (!ok) { + DBG_WARNING("Could not parse notifyd entry for %.*s\n", + (int)key.dsize, (char *)key.dptr); + return 0; + } +- for (i=0; ientries database + */ + +-bool notifyd_parse_entry( +- uint8_t *buf, +- size_t buflen, +- struct notifyd_instance **instances, +- size_t *num_instances) ++/** ++ * @brief Parse a notifyd database entry. ++ * ++ * The memory we pass down needs to be aligned. If it isn't aligned we can run ++ * into obscure errors as we just point into the data buffer. ++ * ++ * @param data The data to parse ++ * @param data_len The length of the data to parse ++ * @param watcher A pointer to store the watcher data or NULL. ++ * @param instances A pointer to store the array of notify instances or NULL. ++ * @param pnum_instances The number of elements in the array. If you just want ++ * the number of elements pass NULL for the watcher and instances pointers. ++ * ++ * @return true on success, false if an error occurred. ++ */ ++bool notifyd_parse_entry(uint8_t *data, ++ size_t data_len, ++ struct notifyd_watcher *watcher, ++ struct notifyd_instance **instances, ++ size_t *pnum_instances) + { +- if ((buflen % sizeof(struct notifyd_instance)) != 0) { +- DBG_WARNING("invalid buffer size: %zu\n", buflen); ++ size_t ilen; ++ ++ if (data_len < sizeof(struct notifyd_watcher)) { + return false; + } + +- if (instances != NULL) { +- *instances = (struct notifyd_instance *)buf; ++ if (watcher != NULL) { ++ *watcher = *((struct notifyd_watcher *)(uintptr_t)data); + } +- if (num_instances != NULL) { +- *num_instances = buflen / sizeof(struct notifyd_instance); ++ ++ ilen = data_len - sizeof(struct notifyd_watcher); ++ if ((ilen % sizeof(struct notifyd_instance)) != 0) { ++ return false; ++ } ++ ++ if (pnum_instances != NULL) { ++ *pnum_instances = ilen / sizeof(struct notifyd_instance); + } ++ if (instances != NULL) { ++ /* The (uintptr_t) cast removes a warning from -Wcast-align. */ ++ *instances = ++ (struct notifyd_instance *)(uintptr_t) ++ (data + sizeof(struct notifyd_watcher)); ++ } ++ + return true; + } +diff --git a/source3/smbd/notifyd/notifyd_private.h b/source3/smbd/notifyd/notifyd_private.h +index 36c08f47c54..db8e6e1c005 100644 +--- a/source3/smbd/notifyd/notifyd_private.h ++++ b/source3/smbd/notifyd/notifyd_private.h +@@ -20,30 +20,48 @@ + #include "lib/util/server_id.h" + #include "notifyd.h" + ++ + /* +- * notifyd's representation of a notify instance ++ * Representation of a watcher for a path ++ * ++ * This will be stored in the db. + */ +-struct notifyd_instance { +- struct server_id client; +- struct notify_instance instance; +- +- void *sys_watch; /* inotify/fam/etc handle */ ++struct notifyd_watcher { ++ /* ++ * This is an intersections of the filter the watcher is listening for. ++ */ ++ uint32_t filter; ++ uint32_t subdir_filter; + + /* +- * Filters after sys_watch took responsibility of some bits ++ * Those are inout variables passed to the sys_watcher. The sys_watcher ++ * will remove the bits it can't handle. + */ +- uint32_t internal_filter; +- uint32_t internal_subdir_filter; ++ uint32_t sys_filter; ++ uint32_t sys_subdir_filter; ++ ++ /* The handle for inotify/fam etc. */ ++ void *sys_watch; ++}; ++ ++/* ++ * Representation of a notifyd instance ++ * ++ * This will be stored in the db. ++ */ ++struct notifyd_instance { ++ struct server_id client; ++ struct notify_instance instance; + }; + + /* + * Parse an entry in the notifyd_context->entries database + */ + +-bool notifyd_parse_entry( +- uint8_t *buf, +- size_t buflen, +- struct notifyd_instance **instances, +- size_t *num_instances); ++bool notifyd_parse_entry(uint8_t *data, ++ size_t data_len, ++ struct notifyd_watcher *watcher, ++ struct notifyd_instance **instances, ++ size_t *num_instances); + + #endif +-- +2.46.1 + diff --git a/main/samba/smbreadline.patch b/main/samba/smbreadline.patch new file mode 100644 index 00000000000..0932541208c --- /dev/null +++ b/main/samba/smbreadline.patch @@ -0,0 +1,112 @@ +From 645dd19208e9374ea8c950cc51f894ab6efabfee Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 21 Jan 2025 17:59:12 +0100 +Subject: [PATCH 1/2] lib:replace: Remove trailing spaces from readline.h + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15788 + +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy +(cherry picked from commit dbff53f77680f0ccd022f2d864ba6ae7585a34b7) +--- + lib/replace/system/readline.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/replace/system/readline.h b/lib/replace/system/readline.h +index 29379626e0d..9a9af266ca6 100644 +--- a/lib/replace/system/readline.h ++++ b/lib/replace/system/readline.h +@@ -1,14 +1,14 @@ + #ifndef _system_readline_h + #define _system_readline_h +-/* ++/* + Unix SMB/CIFS implementation. + + Readline wrappers +- ++ + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL +- ++ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either +-- +2.48.1 + + +From 54821d943892c028116104fe113bf18c2e9db55f Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 21 Jan 2025 17:59:27 +0100 +Subject: [PATCH 2/2] lib:replace: Don't use deprecated readline CPPFunction + cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +HAVE_RL_COMPLETION_FUNC_T was unused and not checking for the right +function. + +libcli/smbreadline/smbreadline.c: In function ‘smb_readline’: +libcli/smbreadline/smbreadline.c:139:17: warning: ‘CPPFunction’ is deprecated [-Wdeprecated-declarations] + 139 | rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +libcli/smbreadline/smbreadline.c:139:50: error: assignment to ‘char ** (*)(const char *, int, int)’ from incompatible pointer type ‘char ** (*)(void)’ [-Wincompatible-pointer-types] + 139 | rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn; + | ^ + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15788 + +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Tue Jan 21 19:38:37 UTC 2025 on atb-devel-224 + +(cherry picked from commit 9aa5c43315d83c19514251a11c4fba5a137f2821) +--- + lib/replace/system/readline.h | 4 +++- + libcli/smbreadline/wscript_configure | 8 +++++--- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/lib/replace/system/readline.h b/lib/replace/system/readline.h +index 9a9af266ca6..ac3604fc12e 100644 +--- a/lib/replace/system/readline.h ++++ b/lib/replace/system/readline.h +@@ -46,7 +46,9 @@ + #endif + + #ifdef HAVE_NEW_LIBREADLINE +-#ifdef HAVE_CPPFUNCTION ++#if defined(HAVE_RL_COMPLETION_FUNC_T) ++# define RL_COMPLETION_CAST (rl_completion_func_t *) ++#elif defined(HAVE_CPPFUNCTION) + # define RL_COMPLETION_CAST (CPPFunction *) + #elif defined(HAVE_RL_COMPLETION_T) + # define RL_COMPLETION_CAST (rl_completion_t *) +diff --git a/libcli/smbreadline/wscript_configure b/libcli/smbreadline/wscript_configure +index 912ff53a150..f5a401ebae0 100644 +--- a/libcli/smbreadline/wscript_configure ++++ b/libcli/smbreadline/wscript_configure +@@ -51,10 +51,12 @@ conf.CHECK_CODE(''' + # endif + # endif + #endif +-int main(void) {rl_completion_t f; return 0;} ++int main(void) {rl_completion_func_t f; return 0;} + ''', +-'HAVE_RL_COMPLETION_FUNC_T', execute=False, addmain=False, +-msg='Checking for rl_completion_t') ++ 'HAVE_RL_COMPLETION_FUNC_T', ++ execute=False, ++ addmain=False, ++ msg='Checking for rl_completion_func_t') + + conf.CHECK_CODE(''' + #ifdef HAVE_READLINE_READLINE_H +-- +2.48.1 +