[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Fri Aug 21 20:38:02 UTC 2020


The branch, master has been updated
       via  ccaf661f7c7 tldap: Receiving "msgid == 0" means the connection is dead
       via  a4ecd112e77 test: Test winbind idmap_ad ticket expiry behaviour
       via  7af2df01dff idmap_ad: Pass tldap debug messages on to DEBUG()
       via  a2b281bed02 tldap: Add PRINTF_ATTRIBUTE declaration to tldap_debug()
       via  2a2a6b27ccc tldap: Make sure all requests are cancelled on rundown
       via  f745f5b1256 tldap: Centralize connection rundown on error
       via  cb852c9dc0d tldap: Maintain the ldap read request in tldap_context
       via  14f6d1996ec tldap: Always remove ourselves from ld->pending at cleanup time
       via  f816ccb8f4d tldap: Fix tldap_msg_received()
       via  b85dbc9ccf8 tldap: Only free() ld->pending if "req" is part of it
       via  eb72f887b0b ldap_server: Terminate LDAP connections on krb ticket expiry
       via  77f72fb01fa ldap_server: Add the krb5 expiry to conn->limits
       via  35c4bb0b0c5 torture: Test ldap session expiry
       via  c8c2f8ba733 build: Wrap a long line
      from  4dbe8d11316 python: Remove remaining references to third_party python libs

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ccaf661f7c75717341140e3fbfb2a48f96ea952c
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

commit a4ecd112e7754ab25bcae749594952a28c4c8905
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>

commit 7af2df01dff62d6d9ca572f320ef60dea41d6064
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>

commit a2b281bed022c04427ef478529462ff84fe42908
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>

commit 2a2a6b27cccb2409d321c7e03feb8baa047d1bf4
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>

commit f745f5b12560dbcb7be6f3ffb3bc10704c87149c
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>

commit cb852c9dc0d0fa1d3e7473082ad6b460106b314b
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>

commit 14f6d1996ec38620b1c05a3b6c0e26dd21801fac
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>

commit f816ccb8f4d212fe7f6bf36f90cbb9297c899786
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>

commit b85dbc9ccf80d8c19aff33c1da83954e5d6a37ef
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>

commit eb72f887b0bf91c050fd5d911f58a1b3ff9b8bcc
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>

commit 77f72fb01faba45babfe6080f805361492ce49e5
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>

commit 35c4bb0b0c55a65490fe199edb1a534548104e95
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>

commit c8c2f8ba73324ba43ccef9f6d1c0c726d7ec0d25
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>

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

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             |   4 +
 source4/torture/ldap/common.c         |   2 +
 source4/torture/ldap/session_expiry.c | 121 ++++++++++++++++++++++++++++
 source4/torture/wscript_build         |  13 ++-
 14 files changed, 478 insertions(+), 50 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 753af49cf67..0a8cefa811d 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1061,6 +1061,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/selftest/tests.py b/source3/selftest/tests.py
index 5e4fbf8a603..556b50c38f5 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -887,6 +887,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