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

Karolin Seeger kseeger at samba.org
Mon Aug 31 09:27:01 UTC 2020


The branch, v4-11-test has been updated
       via  7d0bb8cbced tldap: Receiving "msgid == 0" means the connection is dead
       via  6fca7ca8977 test: Test winbind idmap_ad ticket expiry behaviour
       via  df35c04f46f idmap_ad: Pass tldap debug messages on to DEBUG()
       via  e3b951241cf tldap: Add PRINTF_ATTRIBUTE declaration to tldap_debug()
       via  bf7dfed4f90 tldap: Make sure all requests are cancelled on rundown
       via  ec8e422f6ea tldap: Centralize connection rundown on error
       via  61b337dfb7b tldap: Maintain the ldap read request in tldap_context
       via  5cc2ac271d1 tldap: Always remove ourselves from ld->pending at cleanup time
       via  31a8c24a5d1 tldap: Fix tldap_msg_received()
       via  90e0feb0a35 tldap: Only free() ld->pending if "req" is part of it
       via  74fef4bc2ce ldap_server: Terminate LDAP connections on krb ticket expiry
       via  e2e0be0a312 ldap_server: Add the krb5 expiry to conn->limits
       via  1df2076dd47 torture: Test ldap session expiry
       via  8c0e5ddedf5 build: Wrap a long line
      from  3d7572b4032 ctdb-recoverd: Rename update_local_flags() -> update_flags()

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


- Log -----------------------------------------------------------------
commit 7d0bb8cbcede8514edd4baa243817352e417416d
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)
    
    Autobuild-User(v4-11-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-11-test): Mon Aug 31 09:26:18 UTC 2020 on sn-devel-184

commit 6fca7ca8977918500c7c307dfc32e52a27bc83e2
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 df35c04f46fb7b0d9cb8d3899ef8f39c2ecad81f
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 e3b951241cfe6e325741be9b8dd6dd89f54ab7a1
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 bf7dfed4f9075efb4ff5d9347c496631865b5e8b
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 ec8e422f6eae2c7a68d04d52dd09145ab0acfdc5
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 61b337dfb7bc2a455de17d7f42495697a3df70c7
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 5cc2ac271d1eab79f9716f8c685dd7f67ecb40d8
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 31a8c24a5d197a5e19788ea4a089c9016bcbc1cc
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 90e0feb0a35ddcb0b92a0055d7d5815e66b17505
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 74fef4bc2ce656ac7516951b9e32ebefb783d5a0
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 e2e0be0a312f651215748d505144037a35bc99ca
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 1df2076dd478a038c0d5d4c50815f0c62fbd7d19
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 8c0e5ddedf5d079af61945375a377b98289c9578
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/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             |   7 +-
 source4/torture/ldap/common.c         |   2 +
 source4/torture/ldap/session_expiry.c | 121 ++++++++++++++++++++++++++++
 source4/torture/wscript_build         |  13 ++-
 14 files changed, 480 insertions(+), 51 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 a15979199f0..c22c567cd65 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -728,6 +728,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($prefix, $dcvars->{DOMAIN},
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index a599099c59d..4758a5513d1 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1709,7 +1709,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 = ["--use-ntvfs", "--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/selftest/tests.py b/source3/selftest/tests.py
index 817fc783062..430a7e327f2 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -719,6 +719,11 @@ for t in tests:
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
 
+plantestsuite(
+    "idmap_ad.ticket_expiry",
+    "ad_member_idmap_ad:local",
+    [os.path.join(samba3srcdir, "../nsswitch/tests/test_ticket_expiry.sh"),
+     '$DOMAIN'])
 
 test = 'rpc.lsa.lookupsids'
 auth_options = ["", "ntlm", "spnego", "spnego,ntlm", "spnego,smb1", "spnego,smb2"]
diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index 6d879cdf4d7..3bfeeee2d74 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -254,6 +254,41 @@ static TLDAPRC get_posix_schema_names(struct tldap_context *ld,
 	return TLDAP_SUCCESS;
 }
 
+static void idmap_ad_tldap_debug(void *log_private,
+				 enum tldap_debug_level level,
+				 const char *fmt,
+				 va_list ap)
+{
+       int samba_level = -1;
+
+       switch (level) {
+       case TLDAP_DEBUG_FATAL:
+               samba_level = DBGLVL_ERR;
+               break;
+       case TLDAP_DEBUG_ERROR:
+               samba_level = DBGLVL_ERR;
+               break;
+       case TLDAP_DEBUG_WARNING:
+               samba_level = DBGLVL_WARNING;
+               break;
+       case TLDAP_DEBUG_TRACE:
+               samba_level = DBGLVL_DEBUG;
+               break;
+       }
+
+       if (CHECK_DEBUGLVL(samba_level)) {
+               char *s = NULL;
+               int ret;
+
+               ret = vasprintf(&s, fmt, ap);
+               if (ret == -1) {
+                       return;
+               }
+               DEBUG(samba_level, ("idmap_ad_tldap: %s", s));
+               free(s);
+       }
+}
+
 static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
 				       const char *domname,
 				       struct tldap_context **pld)
@@ -307,6 +342,7 @@ static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
 		TALLOC_FREE(dcinfo);
 		return NT_STATUS_NO_MEMORY;
 	}
+	tldap_set_debug(ld, idmap_ad_tldap_debug, NULL);
 
 	/*
 	 * Here we use or own machine account as
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index bf724335a25..2839082daef 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -1384,11 +1384,48 @@ static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS ldapsrv_expired(struct ldapsrv_call *call)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list