The branch, v4-18-test has been updated via 64161923b6d rpcd_mdssvc: initialize POSIX locking via 5cc3c1b5f6b net_ads: fill ads->auth.realm from c->creds via 4f1d674aa92 testprogs/blackbox: add test_net_ads_search_server.sh via 50d90531fae smbXsrv_tcon: avoid storing temporary (invalid!) records. from 31d4b337cb7 smbd: Fix case normalization in for directories
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-18-test - Log ----------------------------------------------------------------- commit 64161923b6d35a3e79a00fceaf115e2afdd7d643 Author: Ralph Boehme <s...@samba.org> Date: Thu Apr 6 10:16:46 2023 +0200 rpcd_mdssvc: initialize POSIX locking Otherwise the posix_pending_close_db is NULL and we crash when trying to close a file descriptor: #4 /usr/lib64/samba/libdbwrap-samba4.so(dbwrap_parse_record+0xe) [0x7fbc5d05c8ae] #5 /usr/lib64/samba/libdbwrap-samba4.so(dbwrap_fetch_int32+0x38) [0x7fbc5d05d438] #6 /usr/lib64/samba/libsmbd-base-samba4.so(fd_close_posix+0x7b) [0x7fbc5e276f8b] #7 /usr/lib64/samba/libsmbd-base-samba4.so(+0x57900) [0x7fbc5e28a900] #8 /usr/lib64/samba/libsmbd-base-samba4.so(fd_close+0x68) [0x7fbc5e2b7ea8] #9 /usr/lib64/samba/libsmbd-base-samba4.so(+0x62608) [0x7fbc5e295608] #10 /usr/lib64/samba/libtalloc-samba4.so(_talloc_free+0x51b) [0x7fbc5d9f439b] #11 /usr/lib64/samba/vfs/fruit.so(+0xcac2) [0x7fbc45fcdac2] #12 /usr/lib64/samba/vfs/fruit.so(+0xcbdd) [0x7fbc45fcdbdd] #13 /usr/lib64/samba/vfs/fruit.so(+0xf603) [0x7fbc45fd0603] #14 /usr/lib64/samba/libsmbd-base-samba4.so(+0x56375) [0x7fbc5e289375] #15 /usr/lib64/samba/vfs/nothingtoseeherereally.so(+0x196c) [0x7fbc467f996c] #16 /usr/lib64/samba/vfs/streams_xattr.so(+0x51fc) [0x7fbc461e71fc] #17 /usr/lib64/samba/libsmbd-base-samba4.so(+0xade3a) [0x7fbc5e2e0e3a] #18 /usr/lib64/samba/libsmbd-base-samba4.so(create_conn_struct_cwd+0x44) [0x7fbc5e2e1cf4] #19 /usr/libexec/samba/rpcd_mdssvc(mds_init_ctx+0x2c3) [0x563fdac08f03] #20 /usr/libexec/samba/rpcd_mdssvc(_mdssvc_open+0x141) [0x563fdac0b4d1] The corresponding open is done as part of initializing a connection_struct object, where we chdir() and stat() the root path of the share. The stat() in vfs_fruit causes an expensive metadata request on the path which triggers an internal open of a pathref handle. Note that this only affects servers that have fruit:metadata = netatalk set, which is the default unfortunately. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15354 Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Fri Apr 7 21:12:21 UTC 2023 on atb-devel-224 (cherry picked from commit 3633027e49aec064e7d890a1f7ec4d81711a5de7) Autobuild-User(v4-18-test): Jule Anger <jan...@samba.org> Autobuild-Date(v4-18-test): Sun Apr 16 16:39:24 UTC 2023 on atb-devel-224 commit 5cc3c1b5f6b0289f91c01b20989558badc28fd61 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 2 14:46:25 2023 +0100 net_ads: fill ads->auth.realm from c->creds We get the realm we use for authentication needs to the realm belonging to the username we use. We derive the username from c->creds, so we need to do the same for the realm. Otherwise we try to authenticate as the wrong user. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15323 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> (cherry picked from commit 0ef53b948e13eb36b536228cccd89aa4c2adbb90) commit 4f1d674aa929208a9d623ce933da3d38692f68b8 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Apr 5 16:45:21 2023 +0200 testprogs/blackbox: add test_net_ads_search_server.sh This reproduces a regression with 'net ads search -P --server server.of.trusted.domain' BUG: https://bugzilla.samba.org/show_bug.cgi?id=15323 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> (cherry picked from commit 3b585f9e8cc320841fab4cd5c3be53788d0a87ac) commit 50d90531fae36f54c2d6a5e6cf1aba133473a29c Author: Stefan Metzmacher <me...@samba.org> Date: Wed Apr 5 16:59:44 2023 +0200 smbXsrv_tcon: avoid storing temporary (invalid!) records. We used to store smbXsrv_tcon_global.tdb records in two steps, first we created a record in order to allocate the tcon id. The temporary record had a NULL share_name, which translated into 0 bytes for the string during ndr_push_smbXsrv_tcon_global0. The problem is that ndr_pull_smbXsrv_tcon_global0 fails on this with something like: Invalid record in smbXsrv_tcon_global.tdb:key '2CA0ED4A' ndr_pull_struct_blob(length=85) - Buffer Size Error The blob looks like this: [0000] 00 00 00 00 01 00 00 00 00 00 00 00 00 00 02 00 ........ ........ [0010] 00 00 00 00 4A ED A0 2C 4A ED A0 2C 00 00 00 00 ....J.., J..,.... [0020] F8 4B 00 00 00 00 00 00 00 00 00 00 FF FF FF FF .K...... ........ [0030] 4D 59 9B 9F 83 F4 35 20 36 D2 B0 82 62 68 D9 01 MY....5 6...bh.. [0040] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ [0050] 00 00 00 00 00 ..... The reason for having a temporary entry was just based on the fact, that it was easier to keep the logic in make_connection_snum() untouched. But we have all information available in order to store the final record directly. We only need to do the "max connections" check first. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15353 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> (cherry picked from commit e0e58ed0e2429f01265d544b444bf0e4075549e2) ----------------------------------------------------------------------- Summary of changes: source3/rpc_server/rpcd_mdssvc.c | 8 ++++ source3/smbd/globals.h | 5 ++ source3/smbd/smb1_service.c | 48 ++++++++++++-------- source3/smbd/smb2_service.c | 15 ------ source3/smbd/smb2_tcon.c | 58 ++++++++++++++---------- source3/smbd/smbXsrv_tcon.c | 29 +++++++++++- source3/utils/net_ads.c | 10 +++- source4/selftest/tests.py | 11 +++++ testprogs/blackbox/test_net_ads_search_server.sh | 37 +++++++++++++++ 9 files changed, 160 insertions(+), 61 deletions(-) create mode 100755 testprogs/blackbox/test_net_ads_search_server.sh Changeset truncated at 500 lines: diff --git a/source3/rpc_server/rpcd_mdssvc.c b/source3/rpc_server/rpcd_mdssvc.c index c5b632099fa..4040ae9e0d8 100644 --- a/source3/rpc_server/rpcd_mdssvc.c +++ b/source3/rpc_server/rpcd_mdssvc.c @@ -16,6 +16,7 @@ */ #include "includes.h" +#include "source3/locking/proto.h" #include "rpc_worker.h" #include "librpc/gen_ndr/ndr_mdssvc.h" #include "librpc/gen_ndr/ndr_mdssvc_scompat.h" @@ -38,9 +39,16 @@ static size_t mdssvc_servers( void *private_data) { static const struct dcesrv_endpoint_server *ep_servers[1] = { NULL }; + bool ok; lp_load_with_shares(get_dyn_CONFIGFILE()); + ok = posix_locking_init(false); + if (!ok) { + DBG_ERR("posix_locking_init() failed\n"); + exit(1); + } + ep_servers[0] = mdssvc_get_ep_server(); *_ep_servers = ep_servers; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 5fb9f2e647c..9d588066548 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -644,6 +644,8 @@ NTSTATUS smbXsrv_tcon_update(struct smbXsrv_tcon *tcon); NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid); NTSTATUS smb1srv_tcon_table_init(struct smbXsrv_connection *conn); NTSTATUS smb1srv_tcon_create(struct smbXsrv_connection *conn, + uint32_t session_global_id, + const char *share_name, NTTIME now, struct smbXsrv_tcon **_tcon); NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn, @@ -652,6 +654,9 @@ NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn, NTSTATUS smb1srv_tcon_disconnect_all(struct smbXsrv_client *client); NTSTATUS smb2srv_tcon_table_init(struct smbXsrv_session *session); NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session, + uint32_t session_global_id, + uint8_t encryption_flags, + const char *share_name, NTTIME now, struct smbXsrv_tcon **_tcon); NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session, diff --git a/source3/smbd/smb1_service.c b/source3/smbd/smb1_service.c index ed18f298f5b..df26b9fa9d8 100644 --- a/source3/smbd/smb1_service.c +++ b/source3/smbd/smb1_service.c @@ -48,17 +48,43 @@ static connection_struct *make_connection_smb1(struct smb_request *req, { const struct loadparm_substitution *lp_sub = loadparm_s3_global_substitution(); + uint32_t session_global_id; + char *share_name = NULL; struct smbXsrv_tcon *tcon; NTSTATUS status; struct connection_struct *conn; - status = smb1srv_tcon_create(req->xconn, now, &tcon); + session_global_id = req->session->global->session_global_id; + share_name = lp_servicename(talloc_tos(), lp_sub, snum); + if (share_name == NULL) { + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; + } + + if ((lp_max_connections(snum) > 0) + && (count_current_connections(lp_const_servicename(snum), true) >= + lp_max_connections(snum))) { + + DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n", + lp_max_connections(snum), + lp_const_servicename(snum), share_name); + TALLOC_FREE(share_name); + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; + return NULL; + } + + status = smb1srv_tcon_create(req->xconn, + session_global_id, + share_name, + now, &tcon); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n", - nt_errstr(status))); + DEBUG(0,("make_connection_smb1: Couldn't find free tcon for [%s] - %s\n", + share_name, nt_errstr(status))); + TALLOC_FREE(share_name); *pstatus = status; return NULL; } + TALLOC_FREE(share_name); conn = conn_new(req->sconn); if (!conn) { @@ -83,24 +109,10 @@ static connection_struct *make_connection_smb1(struct smb_request *req, return NULL; } - tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn)); - if (tcon->global->share_name == NULL) { - conn_free(conn); - TALLOC_FREE(tcon); - *pstatus = NT_STATUS_NO_MEMORY; - return NULL; - } - tcon->global->session_global_id = - req->session->global->session_global_id; - tcon->compat = talloc_move(tcon, &conn); tcon->status = NT_STATUS_OK; - *pstatus = smbXsrv_tcon_update(tcon); - if (!NT_STATUS_IS_OK(*pstatus)) { - TALLOC_FREE(tcon); - return NULL; - } + *pstatus = NT_STATUS_OK; return tcon->compat; } diff --git a/source3/smbd/smb2_service.c b/source3/smbd/smb2_service.c index 6670b8a5a13..53ed90f038d 100644 --- a/source3/smbd/smb2_service.c +++ b/source3/smbd/smb2_service.c @@ -620,21 +620,6 @@ NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, * in the logs. */ widelinks_warning(snum); - /* - * Enforce the max connections parameter. - */ - - if ((lp_max_connections(snum) > 0) - && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >= - lp_max_connections(snum))) { - - DBG_WARNING("Max connections (%d) exceeded for %s\n", - lp_max_connections(snum), - lp_const_servicename(snum)); - status = NT_STATUS_INSUFFICIENT_RESOURCES; - goto err_root_exit; - } - /* Invoke VFS make connection hook - this must be the first filesystem operation that we do. */ diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index 14229366efa..5bd01c77e05 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -217,6 +217,9 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, bool encryption_required = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED; bool guest_session = false; bool require_signed_tcon = false; + uint32_t session_global_id; + char *share_name = NULL; + uint8_t encryption_flags = 0; *disconnect = false; @@ -328,17 +331,39 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, } } - /* create a new tcon as child of the session */ - status = smb2srv_tcon_create(req->session, now, &tcon); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (encryption_desired) { - tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED; + encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED; } if (encryption_required) { - tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED; + encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED; + } + + session_global_id = req->session->global->session_global_id; + share_name = lp_servicename(talloc_tos(), lp_sub, snum); + if (share_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if ((lp_max_connections(snum) > 0) + && (count_current_connections(lp_const_servicename(snum), true) >= + lp_max_connections(snum))) { + + DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n", + lp_max_connections(snum), + lp_const_servicename(snum), share_name); + TALLOC_FREE(share_name); + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + /* create a new tcon as child of the session */ + status = smb2srv_tcon_create(req->session, + session_global_id, + encryption_flags, + share_name, + now, &tcon); + TALLOC_FREE(share_name); + if (!NT_STATUS_IS_OK(status)) { + return status; } compat_conn = make_connection_smb2(req, @@ -350,27 +375,10 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req, return status; } - tcon->global->share_name = lp_servicename(tcon->global, - lp_sub, - SNUM(compat_conn)); - if (tcon->global->share_name == NULL) { - conn_free(compat_conn); - TALLOC_FREE(tcon); - return NT_STATUS_NO_MEMORY; - } - tcon->global->session_global_id = - req->session->global->session_global_id; - tcon->compat = talloc_move(tcon, &compat_conn); tcon->status = NT_STATUS_OK; - status = smbXsrv_tcon_update(tcon); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(tcon); - return status; - } - if (IS_PRINT(tcon->compat)) { *out_share_type = SMB2_SHARE_TYPE_PRINT; } else if (IS_IPC(tcon->compat)) { diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c index 7d98b987a63..27e6e1286b9 100644 --- a/source3/smbd/smbXsrv_tcon.c +++ b/source3/smbd/smbXsrv_tcon.c @@ -737,6 +737,9 @@ static NTSTATUS smbXsrv_tcon_create(struct smbXsrv_tcon_table *table, enum protocol_types protocol, struct server_id server_id, NTTIME now, + uint32_t session_global_id, + uint8_t encryption_flags, + const char *share_name, struct smbXsrv_tcon **_tcon) { struct db_record *local_rec = NULL; @@ -766,6 +769,14 @@ static NTSTATUS smbXsrv_tcon_create(struct smbXsrv_tcon_table *table, } tcon->global = global; + global->session_global_id = session_global_id; + global->encryption_flags = encryption_flags; + global->share_name = talloc_strdup(global, share_name); + if (global->share_name == NULL) { + TALLOC_FREE(tcon); + return NT_STATUS_NO_MEMORY; + } + if (protocol >= PROTOCOL_SMB2_02) { uint64_t id = global->tcon_global_id; @@ -1097,14 +1108,21 @@ NTSTATUS smb1srv_tcon_table_init(struct smbXsrv_connection *conn) } NTSTATUS smb1srv_tcon_create(struct smbXsrv_connection *conn, + uint32_t session_global_id, + const char *share_name, NTTIME now, struct smbXsrv_tcon **_tcon) { struct server_id id = messaging_server_id(conn->client->msg_ctx); + const uint8_t encryption_flags = 0; return smbXsrv_tcon_create(conn->client->tcon_table, conn->protocol, - id, now, _tcon); + id, now, + session_global_id, + encryption_flags, + share_name, + _tcon); } NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn, @@ -1153,6 +1171,9 @@ NTSTATUS smb2srv_tcon_table_init(struct smbXsrv_session *session) } NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session, + uint32_t session_global_id, + uint8_t encryption_flags, + const char *share_name, NTTIME now, struct smbXsrv_tcon **_tcon) { @@ -1160,7 +1181,11 @@ NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session, return smbXsrv_tcon_create(session->tcon_table, PROTOCOL_SMB2_02, - id, now, _tcon); + id, now, + session_global_id, + encryption_flags, + share_name, + _tcon); } NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session, diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 4bca90d5c8c..9ec884394eb 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -710,7 +710,15 @@ retry: TALLOC_FREE(ads); return ADS_ERROR(LDAP_NO_MEMORY); } - } + } else if (ads->auth.realm == NULL) { + const char *c_realm = cli_credentials_get_realm(c->creds); + + ads->auth.realm = talloc_strdup(ads, c_realm); + if (ads->auth.realm == NULL) { + TALLOC_FREE(ads); + return ADS_ERROR(LDAP_NO_MEMORY); + } + } status = ads_connect(ads); diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 052058383f7..823ada7a5dc 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -666,6 +666,17 @@ plantestsuite("samba4.blackbox.client_etypes_strong(ad_dc:client)", "ad_dc:clien plantestsuite("samba4.blackbox.net_ads_dns(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_net_ads_dns.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$USERNAME', '$PASSWORD']) plantestsuite("samba4.blackbox.samba-tool_ntacl(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_samba-tool_ntacl.sh"), '$PREFIX', '$DOMSID']) +env = "ad_member:local" +plantestsuite("samba4.blackbox.net_ads_search_server_P.primary", env, + [os.path.join(bbdir, "test_net_ads_search_server.sh"), + '$DC_SERVER', '$REALM']) +plantestsuite("samba4.blackbox.net_ads_search_server_P.trust_e_both", env, + [os.path.join(bbdir, "test_net_ads_search_server.sh"), + '$TRUST_E_BOTH_SERVER', '$TRUST_E_BOTH_REALM']) +plantestsuite("samba4.blackbox.net_ads_search_server_P.trust_f_both", env, + [os.path.join(bbdir, "test_net_ads_search_server.sh"), + '$TRUST_F_BOTH_SERVER', '$TRUST_F_BOTH_REALM']) + if have_gnutls_fips_mode_support: plantestsuite("samba4.blackbox.weak_crypto.client", "ad_dc", [os.path.join(bbdir, "test_weak_crypto.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc"]) plantestsuite("samba4.blackbox.test_weak_disable_ntlmssp_ldap", "ad_member:local", [os.path.join(bbdir, "test_weak_disable_ntlmssp_ldap.sh"),'$DC_USERNAME', '$DC_PASSWORD']) diff --git a/testprogs/blackbox/test_net_ads_search_server.sh b/testprogs/blackbox/test_net_ads_search_server.sh new file mode 100755 index 00000000000..f8350c9a97a --- /dev/null +++ b/testprogs/blackbox/test_net_ads_search_server.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +if [ $# -lt 2 ]; then +cat <<EOF +Usage: $0 SERVER REALM +EOF +exit 1; +fi + +SERVER=$1 +REALM=$2 +shift 2 + +failed=0 +. `dirname $0`/subunit.sh + +samba_net="$BINDIR/net" + +DN=$(echo "${REALM}" | tr '[:upper:]' '[:lower:]' | sed -e 's!^!DC=!' -e 's!\.!,DC=!g') +testit_grep_count \ + "net_ads_search.ntlmssp" \ + "distinguishedName: ${DN}" \ + 1 \ + $samba_net ads search --use-kerberos=off -P \ + --server "${SERVER}.${REALM}" \ + '(objectClass=domain)' distinguishedName || \ + failed=$((failed + 1)) +testit_grep_count \ + "net_ads_search.krb5" \ + "distinguishedName: ${DN}" \ + 1 \ + $samba_net ads search --use-kerberos=required -P \ + --server "${SERVER}.${REALM}" \ + '(objectClass=domain)' distinguishedName || \ + failed=$((failed + 1)) + +exit $failed -- Samba Shared Repository