[SCM] Samba Shared Repository - branch v4-13-test updated

Stefan Metzmacher metze at samba.org
Thu Sep 3 14:56:02 UTC 2020


The branch, v4-13-test has been updated
       via  df1ff55deb9 s3:share_mode_lock: remove unused reproducer for bug #14428
       via  0a682a18986 s3:share_mode_lock: make sure share_mode_cleanup_disconnected() removes the record
       via  b83efaec198 s3:share_mode_lock: add missing 'goto done' in share_mode_cleanup_disconnected()
       via  8a8b90eba76 s3:share_mode_lock: consistently debug share_mode_entry records
       via  4aa4f12f533 s3:share_mode_lock: let share_mode_forall_entries/share_entry_forall evaluate e.stale first
       via  e62a37e9748 s3:share_mode_lock: reproduce problem with stale disconnected share mode entries
       via  431192896a2 s3:selftest: also run durable_v2_reconnect_delay_msec in samba3.blackbox.durable_v2_delay
       via  1549dc56280 tldap: Receiving "msgid == 0" means the connection is dead
       via  c785fc601de test: Test winbind idmap_ad ticket expiry behaviour
       via  725dda2b809 idmap_ad: Pass tldap debug messages on to DEBUG()
       via  4a4af2c2534 tldap: Add PRINTF_ATTRIBUTE declaration to tldap_debug()
       via  4f695a62055 tldap: Make sure all requests are cancelled on rundown
       via  468286f4c8a tldap: Centralize connection rundown on error
       via  4b02185ecc1 tldap: Maintain the ldap read request in tldap_context
       via  a3758fa56ec tldap: Always remove ourselves from ld->pending at cleanup time
       via  73deb8332a5 tldap: Fix tldap_msg_received()
       via  67676bc4f5e tldap: Only free() ld->pending if "req" is part of it
       via  3824ce0de3b ldap_server: Terminate LDAP connections on krb ticket expiry
       via  caf9cfa8653 ldap_server: Add the krb5 expiry to conn->limits
       via  6179ac98e6f torture: Test ldap session expiry
       via  fa74a0a2f66 build: Wrap a long line
      from  04630942058 VERSION: Bump version up to 4.13.0rc4...

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-13-test


- Log -----------------------------------------------------------------
commit df1ff55deb92827eb502c1857a0039743752c6b3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 16:28:41 2020 +0200

    s3:share_mode_lock: remove unused reproducer for bug #14428
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    
    Autobuild-User(master): Volker Lendecke <vl at samba.org>
    Autobuild-Date(master): Mon Aug 31 13:34:17 UTC 2020 on sn-devel-184
    
    (cherry picked from commit b02f1d676f6e62a0a4b33b9b08f8f51a68b561ca)
    
    Autobuild-User(v4-13-test): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(v4-13-test): Thu Sep  3 14:55:14 UTC 2020 on sn-devel-184

commit 0a682a1898695839fe4933af61c8a1d4068005a3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 16:28:41 2020 +0200

    s3:share_mode_lock: make sure share_mode_cleanup_disconnected() removes the record
    
    This fixes one possible trigger for "PANIC: assert failed in get_lease_type()"
    https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    This is no longer enough to remove the record:
    
       d->have_share_modes = false;
       d->modified = true;
    
    Note that we can remove it completely from
    share_mode_cleanup_disconnected() as
    share_mode_forall_entries() already sets it
    when there are no entries left.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit b5c0874fd5d31e252cf9ac8b84bde5c536b1e8ef)

commit b83efaec1981600668fae5f67a483c2c698b6e68
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 15:56:35 2020 +0200

    s3:share_mode_lock: add missing 'goto done' in share_mode_cleanup_disconnected()
    
    When cleanup_disconnected_lease() fails we should stop,
    at least we do that if brl_cleanup_disconnected() fails.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit 1aa1ac97082f81f6dc62f345823d2dd345e0afd7)

commit 8a8b90eba76b94f3d7291ccc86fe1e80d4423ff3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 15:56:35 2020 +0200

    s3:share_mode_lock: consistently debug share_mode_entry records
    
    share_mode_entry_do(), share_mode_forall_entries() and
    share_entry_forall() print the record before the callback is called
    and when it was modified or deleted.
    
    This makes it much easier to debug problems.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit 4d740ac2084a68c6d4836cd83ea5d5f1ee9d37a2)

commit 4aa4f12f5333bd4913989ae1f54027e480535eb4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 15:56:35 2020 +0200

    s3:share_mode_lock: let share_mode_forall_entries/share_entry_forall evaluate e.stale first
    
    It's not really clear why e.stale would be ignored if *modified is set
    to true.
    
    This matches the behavior of share_mode_entry_do()
    
    This also makes sure we see the removed entry in level 10 logs again.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit deb2f782c95a5e59a0a5da4272239c2d31bc2b6d)

commit e62a37e9748839f8f474b5a28c607f6630b66c71
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 14:37:59 2020 +0200

    s3:share_mode_lock: reproduce problem with stale disconnected share mode entries
    
    This reproduces the origin of "PANIC: assert failed in get_lease_type()"
    (https://bugzilla.samba.org/show_bug.cgi?id=14428).
    
    share_mode_cleanup_disconnected() removes disconnected entries from
    leases.tdb and brlock.tdb but not from locking.tdb.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit 444f2bedf723b89bb9f493c47812bff2154c4113)

commit 431192896a2e31487dcd5155e35ac333bb4dd472
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 28 15:33:43 2020 +0200

    s3:selftest: also run durable_v2_reconnect_delay_msec in samba3.blackbox.durable_v2_delay
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit 560fe7b38f0c8d53079fabf3f984b11748270035)

commit 1549dc562806a0c3b4ef39303cf5089e3a891892
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 18:09:14 2020 +0200

    tldap: Receiving "msgid == 0" means the connection is dead
    
    We never use msgid=0, see tldap_next_msgid(). RFC4511 section 4.4.1
    says that the unsolicited disconnect response uses msgid 0. We don't
    parse this message, which supposedly is an extended response: Windows
    up to 2019 sends an extended response in an ASN.1 encoding that does
    not match RFC4511.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Volker Lendecke <vl at samba.org>
    Autobuild-Date(master): Fri Aug 21 20:37:25 UTC 2020 on sn-devel-184
    
    (cherry picked from commit ccaf661f7c75717341140e3fbfb2a48f96ea952c)

commit c785fc601dee4eea76aa7bc6046812ae99860a74
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Aug 13 14:59:58 2020 +0200

    test: Test winbind idmap_ad ticket expiry behaviour
    
    We need to make sure that winbind's idmap_ad deals fine with an
    expired krb ticket used to connect to AD via LDAP. In a customer
    situation we have seen the RFC4511 section 4.4.1 unsolicited ldap exop
    response coming through, but the TCP disconnect that Windows seems to
    do after that did not make it. Winbind deals fine with a TCP
    disconnect, but right now it does not handle just the section 4.4.1
    response properly: It completely hangs.
    
    This test requests a ticket valid for 5 seconds and makes the LDAP
    server postpone the TCP disconnect after the ticket expiry for 10
    seconds. The tests that winbind reacts to the ticket expiry exop
    response by making sure in this situation the wbinfo call running into
    the issue takes less than 8 seconds. If it did not look at the expiry
    exop response, it would take more than 10 seconds.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit a4ecd112e7754ab25bcae749594952a28c4c8905)

commit 725dda2b80987aa3b730d1909419b648b1e3a495
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Aug 11 18:24:39 2020 +0200

    idmap_ad: Pass tldap debug messages on to DEBUG()
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    (cherry picked from commit 7af2df01dff62d6d9ca572f320ef60dea41d6064)

commit 4a4af2c2534ca1a8d31f448bcc1a2fa15c8509ac
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Aug 12 13:26:18 2020 +0200

    tldap: Add PRINTF_ATTRIBUTE declaration to tldap_debug()
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit a2b281bed022c04427ef478529462ff84fe42908)

commit 4f695a620550ba8ef32436b1a142e49e56450044
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 17:44:42 2020 +0200

    tldap: Make sure all requests are cancelled on rundown
    
    Put messages into the ld->pending array before sending them out, not
    after they have been sent.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit 2a2a6b27cccb2409d321c7e03feb8baa047d1bf4)

commit 468286f4c8a77465d9e7bb3d058219f5a20024b2
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 17:30:22 2020 +0200

    tldap: Centralize connection rundown on error
    
    Whenever send or recv return -1, we have to cancel all pending
    requests and our transport stream is no longer usable: Discard it upon
    such an error.
    
    To avoid duplicate state, tldap_connection_ok() now looks at whether
    we have a tstream_context around.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit f745f5b12560dbcb7be6f3ffb3bc10704c87149c)

commit 4b02185ecc11f096a47be5630f0f0b273ba2cd90
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 17:14:14 2020 +0200

    tldap: Maintain the ldap read request in tldap_context
    
    Required for proper connection rundown, we need to TALLOC_FREE() the
    read request before shutting down the tstream
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit cb852c9dc0d0fa1d3e7473082ad6b460106b314b)

commit a3758fa56eccc7034b3c859f010b0fb709162229
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Aug 17 21:59:48 2020 +0200

    tldap: Always remove ourselves from ld->pending at cleanup time
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit 14f6d1996ec38620b1c05a3b6c0e26dd21801fac)

commit 73deb8332a540b174868b5cc401c912cf55286ba
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 16:54:34 2020 +0200

    tldap: Fix tldap_msg_received()
    
    The callback of "req" might have destroyed "ld", we can't reference
    this anymore after calling tevent_req_done(req). Defer calling the
    callbacks, which also means that the callbacks can't have added
    anything to ld->pending.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit f816ccb8f4d212fe7f6bf36f90cbb9297c899786)

commit 67676bc4f5e22dfb2a0ef7704c5b3135b3b1d46e
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Aug 11 16:16:12 2020 +0200

    tldap: Only free() ld->pending if "req" is part of it
    
    Best reviewed with "git show -U10". We need to check that "req" is
    actually the last request that is being freed before freeing the whole
    array.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit b85dbc9ccf80d8c19aff33c1da83954e5d6a37ef)

commit 3824ce0de3bc53a35f414685dc78719429abfc19
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Aug 10 16:24:04 2020 +0200

    ldap_server: Terminate LDAP connections on krb ticket expiry
    
    See RFC4511 section 4.4.1 and
    
    https://lists.samba.org/archive/cifs-protocol/2020-August/003515.html
    
    for details: Windows terminates LDAP connections when the krb5 ticket
    expires, Samba should do the same. This patch slightly deviates from
    Windows behaviour by sending a LDAP exop response with msgid 0 that is
    ASN1-encoded conforming to RFC4511.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit eb72f887b0bf91c050fd5d911f58a1b3ff9b8bcc)

commit caf9cfa86530865e8eb1aa03742139567de29863
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Aug 7 13:40:58 2020 +0200

    ldap_server: Add the krb5 expiry to conn->limits
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit 77f72fb01faba45babfe6080f805361492ce49e5)

commit 6179ac98e6f3ad0cf268905f54b8d86c39c7a7d9
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Aug 12 15:50:58 2020 +0200

    torture: Test ldap session expiry
    
    LDAP connections should time out when the kerberos ticket used to authenticate
    expires. Windows does this with a RFC4511 section 4.4.1 message (that as of
    August 2020 is encoded not according to the RFC) followed by a TCP disconnect.
    
    ldb sees the section 4.4.1 as a protocol violation and returns
    LDB_ERR_PROTOCOL_ERROR.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit 35c4bb0b0c55a65490fe199edb1a534548104e95)

commit fa74a0a2f661f89c821aeb7840597d8193a45189
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Aug 12 15:48:01 2020 +0200

    build: Wrap a long line
    
    There will be another entry in the next commit
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=14465
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit c8c2f8ba73324ba43ccef9f6d1c0c726d7ec0d25)

-----------------------------------------------------------------------

Summary of changes:
 nsswitch/tests/test_ticket_expiry.sh               |  74 +++++++++++
 selftest/target/Samba3.pm                          |   1 +
 selftest/target/Samba4.pm                          |   6 +-
 source3/lib/tldap.c                                | 146 ++++++++++++++-------
 source3/locking/share_mode_lock.c                  | 104 ++++++++++++---
 .../script/tests/test_durable_handle_reconnect.sh  |  12 ++
 source3/selftest/tests.py                          |   5 +
 source3/winbindd/idmap_ad.c                        |  36 +++++
 source4/ldap_server/ldap_backend.c                 |  37 ++++++
 source4/ldap_server/ldap_bind.c                    |  15 +++
 source4/ldap_server/ldap_server.c                  |  66 ++++++++++
 source4/ldap_server/ldap_server.h                  |   2 +
 source4/selftest/tests.py                          |   4 +
 source4/torture/ldap/common.c                      |   2 +
 source4/torture/ldap/session_expiry.c              | 121 +++++++++++++++++
 source4/torture/wscript_build                      |  13 +-
 16 files changed, 578 insertions(+), 66 deletions(-)
 create mode 100755 nsswitch/tests/test_ticket_expiry.sh
 create mode 100644 source4/torture/ldap/session_expiry.c


Changeset truncated at 500 lines:

diff --git a/nsswitch/tests/test_ticket_expiry.sh b/nsswitch/tests/test_ticket_expiry.sh
new file mode 100755
index 00000000000..3b98b0fe87a
--- /dev/null
+++ b/nsswitch/tests/test_ticket_expiry.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Test winbind ad backend behaviour when the kerberos ticket expires
+
+if [ $# -ne 1 ]; then
+    echo Usage: $0 DOMAIN
+    exit 1
+fi
+
+DOMAIN="$1"
+
+wbinfo="$VALGRIND $BINDIR/wbinfo"
+net="$VALGRIND $BINDIR/net"
+
+failed=0
+
+. `dirname $0`/../../testprogs/blackbox/subunit.sh
+
+DOMAIN_SID=$($wbinfo -n "$DOMAIN/" | cut -f 1 -d " ")
+if [ $? -ne 0 ] ; then
+    echo "Could not find domain SID" | subunit_fail_test "test_idmap_ad"
+    exit 1
+fi
+ADMINS_SID="$DOMAIN_SID-512"
+
+# Previous tests might have put in a mapping
+$net cache del IDMAP/SID2XID/"$ADMINS_SID"
+
+# Trigger a winbind ad connection with a 5-second ticket lifetime,
+# see the smb.conf for the ad_member_idmap_ad environment we're in
+#
+# We expect failure here because there are no mappings in AD. In this
+# test we are only interested in the winbind LDAP connection as such,
+# we don't really care whether idmap_ad works fine. This is done in
+# different tests. And a negative lookup also triggers the LDAP
+# connection.
+
+testit_expect_failure "Deleting0 IDMAP/SID2XID/$ADMINS_SID" $net cache del IDMAP/SID2XID/"$ADMINS_SID" ||
+    failed=$(expr $failed + 1)
+
+testit_expect_failure "Expecting failure1, no mapping in AD" $wbinfo --sid-to-gid "$ADMINS_SID" ||
+    failed=$(expr $failed + 1)
+
+testit "Deleting1 IDMAP/SID2XID/$ADMINS_SID" $net cache del IDMAP/SID2XID/"$ADMINS_SID" ||
+    failed=$(expr $failed + 1)
+
+# allow our kerberos ticket to expire
+testit "Sleeping for 6 seconds" sleep 6 || failed=$(expr $failed + 1)
+
+# Try again, check how long it took to recover from ticket expiry
+#
+# On the LDAP connection two things happen: First we get an
+# unsolicited exop response telling us the network session was
+# abandoned, and secondly the LDAP server will kill the TCP
+# connection. Our ldap server is configured to defer the TCP
+# disconnect by 10 seconds. We need to make sure that winbind already
+# reacts to the unsolicited exop reply, discarding the connection. The
+# only way is to make sure the following wbinfo does not take too
+# long.
+
+# We need to do the test command in this funny way as on gitlab we're
+# using the bash builtin
+
+START=$(date +%s)
+testit_expect_failure "Expecting failure2, no mapping in AD" $wbinfo --sid-to-gid "$ADMINS_SID" ||
+    failed=$(expr $failed + 1)
+END=$(date +%s)
+DURATION=$(expr $END - $START)
+testit "timeout DURATION[$DURATION] < 8" test "$DURATION" -le 8 ||
+    failed=$(expr $failed + 1)
+
+testit "Deleting2 IDMAP/SID2XID/$ADMINS_SID" $net cache del IDMAP/SID2XID/"$ADMINS_SID" ||
+    failed=$(expr $failed + 1)
+
+exit $failed
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 79feaa188ed..6c31694a748 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1057,6 +1057,7 @@ sub setup_ad_member_idmap_ad
 	idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
 	idmap config $dcvars->{TRUST_DOMAIN} : backend = ad
 	idmap config $dcvars->{TRUST_DOMAIN} : range = 2000000-2999999
+	gensec_gssapi:requested_life_time = 5
 ";
 
 	my $ret = $self->provision(
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 88c95c3a078..649e923ff9a 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1728,7 +1728,11 @@ sub provision_fl2008r2dc($$$)
 	my ($self, $prefix, $dcvars) = @_;
 
 	print "PROVISIONING DC WITH FOREST LEVEL 2008r2...\n";
-        my $extra_conf_options = "ldap server require strong auth = no";
+        my $extra_conf_options = "
+	ldap server require strong auth = no
+        # delay by 10 seconds, 10^7 usecs
+	ldap_server:delay_expire_disconnect = 10000
+";
 	my $extra_provision_options = ["--base-schema=2008_R2"];
 	my $ret = $self->provision($prefix,
 				   "domain controller",
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index bf5fc05d785..0e39a307728 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -29,6 +29,7 @@
 #include "../lib/util/tevent_unix.h"
 
 static TLDAPRC tldap_simple_recv(struct tevent_req *req);
+static bool tldap_msg_set_pending(struct tevent_req *req);
 
 #define TEVENT_TLDAP_RC_MAGIC (0x87bcd26e)
 
@@ -83,10 +84,10 @@ struct tldap_ctx_attribute {
 struct tldap_context {
 	int ld_version;
 	struct tstream_context *conn;
-	bool server_down;
 	int msgid;
 	struct tevent_queue *outgoing;
 	struct tevent_req **pending;
+	struct tevent_req *read_req;
 
 	/* For the sync wrappers we need something like get_last_error... */
 	struct tldap_message *last_msg;
@@ -132,6 +133,11 @@ void tldap_set_debug(struct tldap_context *ld,
 	ld->log_private = log_private;
 }
 
+static void tldap_debug(
+	struct tldap_context *ld,
+	enum tldap_debug_level level,
+	const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+
 static void tldap_debug(struct tldap_context *ld,
 			 enum tldap_debug_level level,
 			 const char *fmt, ...)
@@ -185,10 +191,22 @@ struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
 
 bool tldap_connection_ok(struct tldap_context *ld)
 {
+	int ret;
+
 	if (ld == NULL) {
 		return false;
 	}
-	return !ld->server_down;
+
+	if (ld->conn == NULL) {
+		return false;
+	}
+
+	ret = tstream_pending_bytes(ld->conn);
+	if (ret == -1) {
+		return false;
+	}
+
+	return true;
 }
 
 static size_t tldap_pending_reqs(struct tldap_context *ld)
@@ -424,6 +442,43 @@ static bool tldap_push_controls(struct asn1_data *data,
 	return asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
 }
 
+#define tldap_context_disconnect(ld, status) \
+	_tldap_context_disconnect(ld, status, __location__)
+
+static void _tldap_context_disconnect(struct tldap_context *ld,
+				      TLDAPRC status,
+				      const char *location)
+{
+	if (ld->conn == NULL) {
+		/*
+		 * We don't need to tldap_debug() on
+		 * a potential 2nd run.
+		 *
+		 * The rest of the function would just
+		 * be a noop for the 2nd run anyway.
+		 */
+		return;
+	}
+
+	tldap_debug(ld, TLDAP_DEBUG_WARNING,
+		    "tldap_context_disconnect: %s at %s\n",
+		    tldap_rc2string(status),
+		    location);
+	tevent_queue_stop(ld->outgoing);
+	TALLOC_FREE(ld->read_req);
+	TALLOC_FREE(ld->conn);
+
+	while (talloc_array_length(ld->pending) > 0) {
+		struct tevent_req *req = NULL;
+		struct tldap_msg_state *state = NULL;
+
+		req = ld->pending[0];
+		state = tevent_req_data(req, struct tldap_msg_state);
+		tevent_req_defer_callback(req, state->ev);
+		tevent_req_ldap_error(req, status);
+	}
+}
+
 static void tldap_msg_sent(struct tevent_req *subreq);
 static void tldap_msg_received(struct tevent_req *subreq);
 
@@ -437,6 +492,7 @@ static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
 	struct tevent_req *req, *subreq;
 	struct tldap_msg_state *state;
 	DATA_BLOB blob;
+	bool ok;
 
 	tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
 		    id);
@@ -449,7 +505,8 @@ static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
 	state->ev = ev;
 	state->id = id;
 
-	if (state->ld->server_down) {
+	ok = tldap_connection_ok(ld);
+	if (!ok) {
 		tevent_req_ldap_error(req, TLDAP_SERVER_DOWN);
 		return tevent_req_post(req, ev);
 	}
@@ -470,6 +527,11 @@ static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	if (!tldap_msg_set_pending(req)) {
+		tevent_req_oom(req);
+		return tevent_req_post(req, ev);;
+	}
+
 	state->iov.iov_base = (void *)blob.data;
 	state->iov.iov_len = blob.length;
 
@@ -492,11 +554,6 @@ static void tldap_msg_unset_pending(struct tevent_req *req)
 
 	tevent_req_set_cleanup_fn(req, NULL);
 
-	if (num_pending == 1) {
-		TALLOC_FREE(ld->pending);
-		return;
-	}
-
 	for (i=0; i<num_pending; i++) {
 		if (req == ld->pending[i]) {
 			break;
@@ -511,6 +568,11 @@ static void tldap_msg_unset_pending(struct tevent_req *req)
 		return;
 	}
 
+	if (num_pending == 1) {
+		TALLOC_FREE(ld->pending);
+		return;
+	}
+
 	/*
 	 * Remove ourselves from the cli->pending array
 	 */
@@ -529,14 +591,7 @@ static void tldap_msg_unset_pending(struct tevent_req *req)
 static void tldap_msg_cleanup(struct tevent_req *req,
 			      enum tevent_req_state req_state)
 {
-	switch (req_state) {
-	case TEVENT_REQ_USER_ERROR:
-	case TEVENT_REQ_RECEIVED:
-		tldap_msg_unset_pending(req);
-		return;
-	default:
-		return;
-	}
+	tldap_msg_unset_pending(req);
 }
 
 static bool tldap_msg_set_pending(struct tevent_req *req)
@@ -546,7 +601,6 @@ static bool tldap_msg_set_pending(struct tevent_req *req)
 	struct tldap_context *ld;
 	struct tevent_req **pending;
 	int num_pending;
-	struct tevent_req *subreq;
 
 	ld = state->ld;
 	num_pending = tldap_pending_reqs(ld);
@@ -560,7 +614,7 @@ static bool tldap_msg_set_pending(struct tevent_req *req)
 	ld->pending = pending;
 	tevent_req_set_cleanup_fn(req, tldap_msg_cleanup);
 
-	if (num_pending > 0) {
+	if (ld->read_req != NULL) {
 		return true;
 	}
 
@@ -568,12 +622,12 @@ static bool tldap_msg_set_pending(struct tevent_req *req)
 	 * We're the first one, add the read_ldap request that waits for the
 	 * answer from the server
 	 */
-	subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
-	if (subreq == NULL) {
+	ld->read_req = read_ldap_send(ld->pending, state->ev, ld->conn);
+	if (ld->read_req == NULL) {
 		tldap_msg_unset_pending(req);
 		return false;
 	}
-	tevent_req_set_callback(subreq, tldap_msg_received, ld);
+	tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
 	return true;
 }
 
@@ -589,13 +643,7 @@ static void tldap_msg_sent(struct tevent_req *subreq)
 	nwritten = tstream_writev_queue_recv(subreq, &err);
 	TALLOC_FREE(subreq);
 	if (nwritten == -1) {
-		state->ld->server_down = true;
-		tevent_req_ldap_error(req, TLDAP_SERVER_DOWN);
-		return;
-	}
-
-	if (!tldap_msg_set_pending(req)) {
-		tevent_req_oom(req);
+		tldap_context_disconnect(state->ld, TLDAP_SERVER_DOWN);
 		return;
 	}
 }
@@ -619,21 +667,25 @@ static void tldap_msg_received(struct tevent_req *subreq)
 	ssize_t received;
 	size_t num_pending;
 	int i, err;
-	TLDAPRC status;
+	TLDAPRC status = TLDAP_PROTOCOL_ERROR;
 	int id;
 	uint8_t type;
 	bool ok;
 
 	received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
 	TALLOC_FREE(subreq);
+	ld->read_req = NULL;
 	if (received == -1) {
-		ld->server_down = true;
 		status = TLDAP_SERVER_DOWN;
 		goto fail;
 	}
 
 	data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
 	if (data == NULL) {
+		/*
+		 * We have to disconnect all, we can't tell which of
+		 * the requests this reply is for.
+		 */
 		status = TLDAP_NO_MEMORY;
 		goto fail;
 	}
@@ -652,6 +704,17 @@ static void tldap_msg_received(struct tevent_req *subreq)
 	tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
 		    "type %d\n", id, (int)type);
 
+	if (id == 0) {
+		tldap_debug(
+			ld,
+			TLDAP_DEBUG_WARNING,
+			"tldap_msg_received: got msgid 0 of "
+			"type %"PRIu8", disconnecting\n",
+			type);
+		tldap_context_disconnect(ld, TLDAP_SERVER_DOWN);
+		return;
+	}
+
 	num_pending = talloc_array_length(ld->pending);
 
 	for (i=0; i<num_pending; i++) {
@@ -677,38 +740,25 @@ static void tldap_msg_received(struct tevent_req *subreq)
 	tldap_msg_unset_pending(req);
 	num_pending = talloc_array_length(ld->pending);
 
+	tevent_req_defer_callback(req, state->ev);
 	tevent_req_done(req);
 
  done:
 	if (num_pending == 0) {
 		return;
 	}
-	if (talloc_array_length(ld->pending) > num_pending) {
-		/*
-		 * The callback functions called from tevent_req_done() above
-		 * have put something on the pending queue. We don't have to
-		 * trigger the read_ldap_send(), tldap_msg_set_pending() has
-		 * done it for us already.
-		 */
-		return;
-	}
 
 	state = tevent_req_data(ld->pending[0],	struct tldap_msg_state);
-	subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
-	if (subreq == NULL) {
+	ld->read_req = read_ldap_send(ld->pending, state->ev, ld->conn);
+	if (ld->read_req == NULL) {
 		status = TLDAP_NO_MEMORY;
 		goto fail;
 	}
-	tevent_req_set_callback(subreq, tldap_msg_received, ld);
+	tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
 	return;
 
  fail:
-	while (talloc_array_length(ld->pending) > 0) {
-		req = ld->pending[0];
-		state = tevent_req_data(req, struct tldap_msg_state);
-		tevent_req_defer_callback(req, state->ev);
-		tevent_req_ldap_error(req, status);
-	}
+	tldap_context_disconnect(ld, status);
 }
 
 static TLDAPRC tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index ba0bc2b1e7b..1c4d3a42221 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -1648,6 +1648,42 @@ static bool share_mode_find_connected_fn(
 	return false;
 }
 
+static bool cleanup_disconnected_share_mode_entry_fn(
+	struct share_mode_entry *e,
+	bool *modified,
+	void *private_data)
+{
+	struct cleanup_disconnected_state *state = private_data;
+	struct share_mode_data *d = state->lck->data;
+
+	bool disconnected;
+
+	disconnected = server_id_is_disconnected(&e->pid);
+	if (!disconnected) {
+		struct file_id_buf tmp1;
+		struct server_id_buf tmp2;
+		DBG_ERR("file (file-id='%s', servicepath='%s', "
+			"base_name='%s%s%s') "
+			"is used by server %s ==> internal error\n",
+			file_id_str_buf(d->id, &tmp1),
+			d->servicepath,
+			d->base_name,
+			(d->stream_name == NULL)
+			? "" : "', stream_name='",
+			(d->stream_name == NULL)
+			? "" : d->stream_name,
+			server_id_str_buf(e->pid, &tmp2));
+		smb_panic(__location__);
+	}
+
+	/*
+	 * Setting e->stale = true is
+	 * the indication to delete the entry.
+	 */
+	e->stale = true;
+	return false;
+}
+
 bool share_mode_cleanup_disconnected(struct file_id fid,
 				     uint64_t open_persistent_id)
 {
@@ -1694,6 +1730,7 @@ bool share_mode_cleanup_disconnected(struct file_id fid,
 			  (data->stream_name == NULL)
 			  ? "" : data->stream_name,
 			  open_persistent_id);
+		goto done;
 	}
 
 	ok = brl_cleanup_disconnected(fid, open_persistent_id);
@@ -1727,8 +1764,24 @@ bool share_mode_cleanup_disconnected(struct file_id fid,
 		  ? "" : data->stream_name,
 		  open_persistent_id);
 
-	data->have_share_modes = false;
-	data->modified = true;
+	ok = share_mode_forall_entries(
+		state.lck, cleanup_disconnected_share_mode_entry_fn, &state);
+	if (!ok) {
+		DBG_DEBUG("failed to clean up %zu entries associated "
+			  "with file (file-id='%s', servicepath='%s', "
+			  "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
+			  "==> do not cleanup\n",
+			  state.num_disconnected,
+			  file_id_str_buf(fid, &idbuf),
+			  data->servicepath,
+			  data->base_name,
+			  (data->stream_name == NULL)
+			  ? "" : "', stream_name='",
+			  (data->stream_name == NULL)
+			  ? "" : data->stream_name,
+			  open_persistent_id);
+		goto done;
+	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list