[PATCH] Make cli_full_connection async

Volker Lendecke Volker.Lendecke at SerNet.DE
Wed Apr 10 05:11:09 MDT 2013


Hi!

Attached find a patchset to make cli_full_connection async
to a certain extent. Notable exceptions: Name lookup is not
async, so it is only truly async if passed an IP address,
and acquiring Kerberos tickets is not async. It has some
minor cleanup patches embedded.

Please review & push.

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 9cd691df9e1137f92e0461335edb76b56b47decb Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 14:58:02 +0200
Subject: [PATCH 01/22] libsmbclient: Use tevent_req_poll_ntstatus in
 cli_tcon_andx

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ec5c273..8bfaa2c 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2530,8 +2530,7 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
 		goto fail;
 	}
 
-	if (!tevent_req_poll(req, ev)) {
-		status = map_nt_error_from_unix(errno);
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
 		goto fail;
 	}
 
-- 
1.7.9.5


From 8336b13297060039abe880aeb7b6d0c8e1165157 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 15:02:51 +0200
Subject: [PATCH 02/22] libsmbclient: Streamline cli_tcon_andx a bit

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 8bfaa2c..fc994dd 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2508,7 +2508,7 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
 	TALLOC_CTX *frame = talloc_stackframe();
 	struct tevent_context *ev;
 	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_OK;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
 		/*
@@ -2520,13 +2520,11 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
 
 	ev = samba_tevent_context_init(frame);
 	if (ev == NULL) {
-		status = NT_STATUS_NO_MEMORY;
 		goto fail;
 	}
 
 	req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
 	if (req == NULL) {
-		status = NT_STATUS_NO_MEMORY;
 		goto fail;
 	}
 
-- 
1.7.9.5


From affdad6448d252d3d9463e3bc88fd5565ac89e3b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 15:08:22 +0200
Subject: [PATCH 03/22] libsmbclient: Use tevent_req_poll_ntstatus in
 cli_openx

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/clifile.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 43218bf..a248a46 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -2293,8 +2293,7 @@ NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
 		goto fail;
 	}
 
-	if (!tevent_req_poll(req, ev)) {
-		status = map_nt_error_from_unix(errno);
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
 		goto fail;
 	}
 
-- 
1.7.9.5


From 1f46a857f1157148b92a75d4b8e567e96cb61571 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 15:09:02 +0200
Subject: [PATCH 04/22] libsmbclient: Streamline cli_openx a bit

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/clifile.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index a248a46..4b4e1a0 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -2271,7 +2271,7 @@ NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
 	TALLOC_CTX *frame = talloc_stackframe();
 	struct tevent_context *ev;
 	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_OK;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
 		/*
@@ -2283,13 +2283,11 @@ NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
 
 	ev = samba_tevent_context_init(frame);
 	if (ev == NULL) {
-		status = NT_STATUS_NO_MEMORY;
 		goto fail;
 	}
 
 	req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
 	if (req == NULL) {
-		status = NT_STATUS_NO_MEMORY;
 		goto fail;
 	}
 
-- 
1.7.9.5


From b364dbd78dff0bb48e6369992a47393aedf321bc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 8 Mar 2013 17:40:54 +0100
Subject: [PATCH 05/22] libsmbclient: Fix a leak on talloc_tos()

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index fc994dd..31dd677 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2015,7 +2015,9 @@ ntlmssp:
 		account[PTR_DIFF(p,user)] = '\0';
 	}
 
-	return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
+	status = cli_session_setup_ntlmssp(cli, account, pass, user_domain);
+	TALLOC_FREE(account);
+	return ADS_ERROR_NT(status);
 }
 
 /****************************************************************************
-- 
1.7.9.5


From 57bac714138aa8819bbad15fc2994c98c6fda6d8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 8 Mar 2013 15:55:51 +0100
Subject: [PATCH 06/22] libsmbclient: Avoid a data copy

spnego_parse_negTokenInit does a asn_load of that blob, which does a data copy
itself. So we don't have to had it a copy as well.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 31dd677..bfa31d3 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1875,20 +1875,17 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	char *OIDs[ASN1_MAX_OIDS];
 	int i;
 	const DATA_BLOB *server_blob;
-	DATA_BLOB blob = data_blob_null;
 	const char *p = NULL;
 	char *account = NULL;
 	NTSTATUS status;
 
 	server_blob = smbXcli_conn_server_gss_blob(cli->conn);
-	if (server_blob) {
-		blob = data_blob(server_blob->data, server_blob->length);
-	}
 
-	DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
+	DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
+		 (unsigned long)server_blob->length));
 
 	/* the server might not even do spnego */
-	if (blob.length == 0) {
+	if (server_blob->length == 0) {
 		DEBUG(3,("server didn't supply a full spnego negprot\n"));
 		goto ntlmssp;
 	}
@@ -1901,12 +1898,11 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	 * negprot reply. It is WRONG to depend on the principal sent in the
 	 * negprot reply, but right now we do it. If we don't receive one,
 	 * we try to best guess, then fall back to NTLM.  */
-	if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
+	if (!spnego_parse_negTokenInit(talloc_tos(), *server_blob, OIDs,
+				       &principal, NULL) ||
 			OIDs[0] == NULL) {
-		data_blob_free(&blob);
 		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 	}
-	data_blob_free(&blob);
 
 	/* make sure the server understands kerberos */
 	for (i=0;OIDs[i];i++) {
-- 
1.7.9.5


From 15585b9ef727b603eddde4ce58a61e0f50804581 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 8 Mar 2013 17:21:13 +0100
Subject: [PATCH 07/22] libsmbclient: Factor out
 cli_session_setup_get_principal

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   85 +++++++++++++++++++++++++------------------
 1 file changed, 49 insertions(+), 36 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index bfa31d3..daaf7e3 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1858,6 +1858,50 @@ fail:
 	return status;
 }
 
+#ifdef HAVE_KRB5
+
+static char *cli_session_setup_get_principal(
+	TALLOC_CTX *mem_ctx, const char *spnego_principal,
+	const char *remote_name, const char *dest_realm)
+{
+	char *principal = NULL;
+
+	if (!lp_client_use_spnego_principal() ||
+	    strequal(principal, ADS_IGNORE_PRINCIPAL)) {
+		spnego_principal = NULL;
+	}
+	if (spnego_principal != NULL) {
+		DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
+			  "principal %s\n", spnego_principal));
+		return talloc_strdup(mem_ctx, spnego_principal);
+	}
+	if (is_ipaddress(remote_name) ||
+	    strequal(remote_name, STAR_SMBSERVER)) {
+		return NULL;
+	}
+
+	DEBUG(3, ("cli_session_setup_spnego: using target "
+		  "hostname not SPNEGO principal\n"));
+
+	if (dest_realm) {
+		char *realm = strupper_talloc(talloc_tos(), dest_realm);
+		if (realm == NULL) {
+			return NULL;
+		}
+		principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
+					    remote_name, realm);
+		TALLOC_FREE(realm);
+	} else {
+		principal = kerberos_get_principal_from_service_hostname(
+			talloc_tos(), "cifs", remote_name, lp_realm());
+	}
+	DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
+		  principal ? principal : "<null>"));
+
+	return principal;
+}
+#endif
+
 /****************************************************************************
  Do a spnego encrypted session setup.
 
@@ -1932,6 +1976,7 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
 		ADS_STATUS rc;
 		const char *remote_name = smbXcli_conn_remote_name(cli->conn);
+		char *tmp;
 
 		if (pass && *pass) {
 			int ret;
@@ -1948,42 +1993,10 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 			}
 		}
 
-		/* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
-		 */
-		if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
-			TALLOC_FREE(principal);
-		}
-
-		if (principal == NULL &&
-			!is_ipaddress(remote_name) &&
-			!strequal(STAR_SMBSERVER,
-				  remote_name)) {
-			DEBUG(3,("cli_session_setup_spnego: using target "
-				 "hostname not SPNEGO principal\n"));
-
-			if (dest_realm) {
-				char *realm = strupper_talloc(talloc_tos(), dest_realm);
-				if (realm) {
-					principal = talloc_asprintf(talloc_tos(),
-								    "cifs/%s@%s",
-								    remote_name,
-								    realm);
-					TALLOC_FREE(realm);
-				}
-			} else {
-				principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
-											 "cifs",
-											 remote_name,
-											 lp_realm());
-			}
-
-			if (!principal) {
-				return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-			}
-			DEBUG(3,("cli_session_setup_spnego: guessed "
-				"server principal=%s\n",
-				principal ? principal : "<null>"));
-		}
+		tmp = cli_session_setup_get_principal(
+			talloc_tos(), principal, remote_name, dest_realm);
+		TALLOC_FREE(principal);
+		principal = tmp;
 
 		if (principal) {
 			rc = cli_session_setup_kerberos(cli, principal);
-- 
1.7.9.5


From bd1ecec5246b1ad91848fc478d692e736550349a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 8 Mar 2013 19:41:07 +0100
Subject: [PATCH 08/22] libsmbclient: Slightly simplify
 cli_session_setup_spnego

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index daaf7e3..c1b2ec8 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1919,7 +1919,7 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	char *OIDs[ASN1_MAX_OIDS];
 	int i;
 	const DATA_BLOB *server_blob;
-	const char *p = NULL;
+	char *p;
 	char *account = NULL;
 	NTSTATUS status;
 
@@ -2020,8 +2020,8 @@ ntlmssp:
 	/* when falling back to ntlmssp while authenticating with a machine
 	 * account strip off the realm - gd */
 
-	if ((p = strchr_m(user, '@')) != NULL) {
-		account[PTR_DIFF(p,user)] = '\0';
+	if ((p = strchr_m(account, '@')) != NULL) {
+		*p = '\0';
 	}
 
 	status = cli_session_setup_ntlmssp(cli, account, pass, user_domain);
-- 
1.7.9.5


From 0ca6675a2e34d30ce31b6615de9d98be3a9df5de Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 9 Mar 2013 09:53:42 +0100
Subject: [PATCH 09/22] libsmbclient: Factor out cli_session_setup_get_account

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index c1b2ec8..77053a7 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1902,6 +1902,22 @@ static char *cli_session_setup_get_principal(
 }
 #endif
 
+static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
+					   const char *principal)
+{
+	char *account, *p;
+
+	account = talloc_strdup(mem_ctx, principal);
+	if (account == NULL) {
+		return NULL;
+	}
+	p = strchr_m(account, '@');
+	if (p != NULL) {
+		*p = '\0';
+	}
+	return account;
+}
+
 /****************************************************************************
  Do a spnego encrypted session setup.
 
@@ -1919,7 +1935,6 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	char *OIDs[ASN1_MAX_OIDS];
 	int i;
 	const DATA_BLOB *server_blob;
-	char *p;
 	char *account = NULL;
 	NTSTATUS status;
 
@@ -2012,18 +2027,11 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 
 ntlmssp:
 
-	account = talloc_strdup(talloc_tos(), user);
+	account = cli_session_setup_get_account(talloc_tos(), user);
 	if (!account) {
 		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
 	}
 
-	/* when falling back to ntlmssp while authenticating with a machine
-	 * account strip off the realm - gd */
-
-	if ((p = strchr_m(account, '@')) != NULL) {
-		*p = '\0';
-	}
-
 	status = cli_session_setup_ntlmssp(cli, account, pass, user_domain);
 	TALLOC_FREE(account);
 	return ADS_ERROR_NT(status);
-- 
1.7.9.5


From 9f421dcae227df25698553dc0b0aac68f2486210 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 9 Mar 2013 13:07:57 +0100
Subject: [PATCH 10/22] libsmbclient: Add async cli_session_setup_ntlmssp

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  170 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 146 insertions(+), 24 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 77053a7..905720e 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1925,19 +1925,53 @@ static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
  dest_realm: The realm we're connecting to, if NULL we use our default realm.
 ****************************************************************************/
 
-static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
-			      const char *user,
-			      const char *pass,
-			      const char *user_domain,
-			      const char * dest_realm)
+struct cli_session_setup_spnego_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	const char *user;
+	const char *account;
+	const char *pass;
+	const char *user_domain;
+	const char *dest_realm;
+	ADS_STATUS result;
+};
+
+#ifdef HAVE_KRB5
+static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
+#endif
+
+static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
+
+static struct tevent_req *cli_session_setup_spnego_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+	const char *user, const char *pass, const char *user_domain,
+	const char *dest_realm)
 {
+	struct tevent_req *req, *subreq;
+	struct cli_session_setup_spnego_state *state;
 	char *principal = NULL;
 	char *OIDs[ASN1_MAX_OIDS];
 	int i;
 	const DATA_BLOB *server_blob;
-	char *account = NULL;
 	NTSTATUS status;
 
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_session_setup_spnego_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->cli = cli;
+	state->user = user;
+	state->pass = pass;
+	state->user_domain = user_domain;
+	state->dest_realm = dest_realm;
+
+	state->account = cli_session_setup_get_account(state, user);
+	if (tevent_req_nomem(state->account, req)) {
+		return tevent_req_post(req, ev);
+	}
+
 	server_blob = smbXcli_conn_server_gss_blob(cli->conn);
 
 	DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
@@ -1957,10 +1991,12 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	 * negprot reply. It is WRONG to depend on the principal sent in the
 	 * negprot reply, but right now we do it. If we don't receive one,
 	 * we try to best guess, then fall back to NTLM.  */
-	if (!spnego_parse_negTokenInit(talloc_tos(), *server_blob, OIDs,
+	if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
 				       &principal, NULL) ||
 			OIDs[0] == NULL) {
-		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+		state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
 	}
 
 	/* make sure the server understands kerberos */
@@ -1980,8 +2016,9 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 
 	status = cli_set_username(cli, user);
 	if (!NT_STATUS_IS_OK(status)) {
-		TALLOC_FREE(principal);
-		return ADS_ERROR_NT(status);
+		state->result = ADS_ERROR_NT(status);
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
 	}
 
 #ifdef HAVE_KRB5
@@ -1989,7 +2026,6 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 	 * and do not store results */
 
 	if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
-		ADS_STATUS rc;
 		const char *remote_name = smbXcli_conn_remote_name(cli->conn);
 		char *tmp;
 
@@ -2004,7 +2040,9 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 				DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
 				if (cli->fallback_after_kerberos)
 					goto ntlmssp;
-				return ADS_ERROR_KRB5(ret);
+				state->result = ADS_ERROR_KRB5(ret);
+				tevent_req_done(req);
+				return tevent_req_post(req, ev);
 			}
 		}
 
@@ -2014,27 +2052,111 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
 		principal = tmp;
 
 		if (principal) {
-			rc = cli_session_setup_kerberos(cli, principal);
-			if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
-				TALLOC_FREE(principal);
-				return rc;
+			subreq = cli_session_setup_kerberos_send(
+				state, ev, cli, principal);
+			if (tevent_req_nomem(subreq, req)) {
+				return tevent_req_post(req, ev);
 			}
+			tevent_req_set_callback(
+				subreq, cli_session_setup_spnego_done_krb,
+				req);
+			return req;
 		}
 	}
 #endif
 
-	TALLOC_FREE(principal);
-
 ntlmssp:
+	subreq = cli_session_setup_ntlmssp_send(
+		state, ev, cli, state->account, pass, user_domain);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(
+		subreq, cli_session_setup_spnego_done_ntlmssp, req);
+	return req;
+}
+
+#ifdef HAVE_KRB5
+static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_session_setup_spnego_state *state = tevent_req_data(
+		req, struct cli_session_setup_spnego_state);
 
-	account = cli_session_setup_get_account(talloc_tos(), user);
-	if (!account) {
-		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+	state->result = cli_session_setup_kerberos_recv(subreq);
+	TALLOC_FREE(subreq);
+
+	if (ADS_ERR_OK(state->result) ||
+	    !state->cli->fallback_after_kerberos) {
+		tevent_req_done(req);
+		return;
+	}
+
+	subreq = cli_session_setup_ntlmssp_send(
+		state, state->ev, state->cli, state->account, state->pass,
+		state->user_domain);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
 	}
+	tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
+				req);
+}
+#endif
+
+static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_session_setup_spnego_state *state = tevent_req_data(
+		req, struct cli_session_setup_spnego_state);
+	NTSTATUS status;
+
+	status = cli_session_setup_ntlmssp_recv(subreq);
+	TALLOC_FREE(subreq);
+	state->result = ADS_ERROR_NT(status);
+	tevent_req_done(req);
+}
+
+static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
+{
+	struct cli_session_setup_spnego_state *state = tevent_req_data(
+		req, struct cli_session_setup_spnego_state);
+
+	return state->result;
+}
+
+static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
+			      const char *user,
+			      const char *pass,
+			      const char *user_domain,
+			      const char * dest_realm)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	ADS_STATUS result = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+	NTSTATUS status;
 
-	status = cli_session_setup_ntlmssp(cli, account, pass, user_domain);
-	TALLOC_FREE(account);
-	return ADS_ERROR_NT(status);
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+	}
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_session_setup_spnego_send(ev, ev, cli, user, pass,
+					    user_domain, dest_realm);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		result = ADS_ERROR_NT(status);
+		goto fail;
+	}
+	result = cli_session_setup_spnego_recv(req);
+fail:
+	TALLOC_FREE(ev);
+	return result;
 }
 
 /****************************************************************************
-- 
1.7.9.5


From dc665e396b8c05eec2c31310875de6c8b7867b47 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 2 Apr 2013 12:50:43 +0200
Subject: [PATCH 11/22] libsmbclient: Remove unused
 cli_session_setup_ntlmssp()

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   29 -----------------------------
 1 file changed, 29 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 905720e..6befe5b 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1829,35 +1829,6 @@ static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
-					  const char *user,
-					  const char *pass,
-					  const char *domain)
-{
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-	ev = samba_tevent_context_init(talloc_tos());
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		goto fail;
-	}
-	status = cli_session_setup_ntlmssp_recv(req);
-fail:
-	TALLOC_FREE(ev);
-	return status;
-}
-
 #ifdef HAVE_KRB5
 
 static char *cli_session_setup_get_principal(
-- 
1.7.9.5


From c30a7702ed54548f52409a0f82b3ea8a30f254c5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 2 Apr 2013 13:37:30 +0200
Subject: [PATCH 12/22] libsmbclient: Add async cli_session_setup

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  257 ++++++++++++++++++++++++++++++++++++-------
 source3/libsmb/proto.h      |    8 ++
 2 files changed, 223 insertions(+), 42 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 6befe5b..ea47662 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2130,29 +2130,50 @@ fail:
 	return result;
 }
 
+struct cli_session_setup_state {
+	uint8_t dummy;
+};
+
+static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
+static void cli_session_setup_done_spnego(struct tevent_req *subreq);
+static void cli_session_setup_done_guest(struct tevent_req *subreq);
+static void cli_session_setup_done_plain(struct tevent_req *subreq);
+static void cli_session_setup_done_nt1(struct tevent_req *subreq);
+
 /****************************************************************************
  Send a session setup. The username and workgroup is in UNIX character
  format and must be converted to DOS codepage format before sending. If the
  password is in plaintext, the same should be done.
 ****************************************************************************/
 
-NTSTATUS cli_session_setup(struct cli_state *cli,
-			   const char *user,
-			   const char *pass, int passlen,
-			   const char *ntpass, int ntpasslen,
-			   const char *workgroup)
+struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
+					  struct tevent_context *ev,
+					  struct cli_state *cli,
+					  const char *user,
+					  const char *pass, int passlen,
+					  const char *ntpass, int ntpasslen,
+					  const char *workgroup)
 {
+	struct tevent_req *req, *subreq;
+	struct cli_session_setup_state *state;
 	char *p;
 	char *user2;
 	uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
 
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_session_setup_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
 	if (user) {
-		user2 = talloc_strdup(talloc_tos(), user);
+		user2 = talloc_strdup(state, user);
 	} else {
-		user2 = talloc_strdup(talloc_tos(), "");
+		user2 = talloc_strdup(state, "");
 	}
 	if (user2 == NULL) {
-		return NT_STATUS_NO_MEMORY;
+		tevent_req_oom(req);
+		return tevent_req_post(req, ev);
 	}
 
 	if (!workgroup) {
@@ -2165,13 +2186,15 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
 		*p = 0;
 		user = p+1;
 		if (!strupper_m(user2)) {
-			return NT_STATUS_INVALID_PARAMETER;
+			tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+			return tevent_req_post(req, ev);
 		}
 		workgroup = user2;
 	}
 
 	if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
-		return NT_STATUS_OK;
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
 	}
 
 	/* now work out what sort of session setup we are going to
@@ -2184,44 +2207,68 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
 		if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
 			DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
 				  " or 'client ntlmv2 auth = yes'\n"));
-			return NT_STATUS_ACCESS_DENIED;
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return tevent_req_post(req, ev);
 		}
 
 		if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
 		    !lp_client_plaintext_auth() && (*pass)) {
 			DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
 				  " or 'client ntlmv2 auth = yes'\n"));
-			return NT_STATUS_ACCESS_DENIED;
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return tevent_req_post(req, ev);
 		}
 
-		return cli_session_setup_lanman2(cli, user, pass, passlen,
-						 workgroup);
+		subreq = cli_session_setup_lanman2_send(
+			state, ev, cli, user, pass, passlen, workgroup);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
+					req);
+		return req;
 	}
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
 		const char *remote_realm = cli_state_remote_realm(cli);
-		ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
-							     workgroup,
-							     remote_realm);
-		if (!ADS_ERR_OK(status)) {
-			DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
-			return ads_ntstatus(status);
+
+		subreq = cli_session_setup_spnego_send(
+			state, ev, cli, user, pass, workgroup, remote_realm);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
 		}
-		return NT_STATUS_OK;
+		tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
+					req);
+		return req;
 	}
 
 	/* if no user is supplied then we have to do an anonymous connection.
 	   passwords are ignored */
 
-	if (!user || !*user)
-		return cli_session_setup_guest(cli);
+	if (!user || !*user) {
+		subreq = cli_session_setup_guest_send(state, ev, cli);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, cli_session_setup_done_guest,
+					req);
+		return req;
+	}
 
 	/* if the server is share level then send a plaintext null
            password at this point. The password is sent in the tree
            connect */
 
-	if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
-		return cli_session_setup_plain(cli, user, "", workgroup);
+	if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
+		subreq = cli_session_setup_plain_send(
+			state, ev, cli, user, "", workgroup);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, cli_session_setup_done_plain,
+					req);
+		return req;
+	}
 
 	/* if the server doesn't support encryption then we have to use 
 	   plaintext. The second password is ignored */
@@ -2230,36 +2277,162 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
 		if (!lp_client_plaintext_auth() && (*pass)) {
 			DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
 				  " or 'client ntlmv2 auth = yes'\n"));
-			return NT_STATUS_ACCESS_DENIED;
+			tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+			return tevent_req_post(req, ev);
+		}
+		subreq = cli_session_setup_plain_send(
+			state, ev, cli, user, pass, workgroup);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
 		}
-		return cli_session_setup_plain(cli, user, pass, workgroup);
+		tevent_req_set_callback(subreq, cli_session_setup_done_plain,
+					req);
+		return req;
 	}
 
 	/* if the server supports extended security then use SPNEGO */
 
 	if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
 		const char *remote_realm = cli_state_remote_realm(cli);
-		ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
-							     workgroup,
-							     remote_realm);
-		if (!ADS_ERR_OK(status)) {
-			DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
-			return ads_ntstatus(status);
+
+		subreq = cli_session_setup_spnego_send(
+			state, ev, cli, user, pass, workgroup, remote_realm);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
 		}
+		tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
+					req);
+		return req;
 	} else {
-		NTSTATUS status;
-
 		/* otherwise do a NT1 style session setup */
-		status = cli_session_setup_nt1(cli, user, pass, passlen,
-					       ntpass, ntpasslen, workgroup);
-		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(3,("cli_session_setup: NT1 session setup "
-				 "failed: %s\n", nt_errstr(status)));
-			return status;
+
+		subreq = cli_session_setup_nt1_send(
+			state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
+			workgroup);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
 		}
+		tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
+					req);
+		return req;
 	}
 
-	return NT_STATUS_OK;
+	tevent_req_done(req);
+	return tevent_req_post(req, ev);
+}
+
+static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_session_setup_lanman2_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static void cli_session_setup_done_spnego(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	ADS_STATUS status;
+
+	status = cli_session_setup_spnego_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
+		tevent_req_nterror(req, ads_ntstatus(status));
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static void cli_session_setup_done_guest(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_session_setup_guest_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static void cli_session_setup_done_plain(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_session_setup_plain_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static void cli_session_setup_done_nt1(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_session_setup_nt1_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(3, ("cli_session_setup: NT1 session setup "
+			  "failed: %s\n", nt_errstr(status)));
+		tevent_req_nterror(req, status);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+NTSTATUS cli_session_setup_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_session_setup(struct cli_state *cli,
+			   const char *user,
+			   const char *pass, int passlen,
+			   const char *ntpass, int ntpasslen,
+			   const char *workgroup)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
+				     ntpass, ntpasslen, workgroup);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_session_setup_recv(req);
+ fail:
+	TALLOC_FREE(ev);
+	return status;
 }
 
 /****************************************************************************
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 2d0e782..182750c 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -33,6 +33,14 @@ struct smb_trans_enc_state;
 
 /* The following definitions come from libsmb/cliconnect.c  */
 
+struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
+					  struct tevent_context *ev,
+					  struct cli_state *cli,
+					  const char *user,
+					  const char *pass, int passlen,
+					  const char *ntpass, int ntpasslen,
+					  const char *workgroup);
+NTSTATUS cli_session_setup_recv(struct tevent_req *req);
 NTSTATUS cli_session_setup(struct cli_state *cli,
 			   const char *user,
 			   const char *pass, int passlen,
-- 
1.7.9.5


From 69e511766cbe879e0d8c2411ae35b0f5198b465e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 2 Apr 2013 13:39:05 +0200
Subject: [PATCH 13/22] libsmbclient: Remove unused sync wrappers

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  201 -------------------------------------------
 1 file changed, 201 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ea47662..042205b 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -293,40 +293,6 @@ static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
 	return tevent_req_simple_recv_ntstatus(req);
 }
 
-static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
-					  const char *pass, size_t passlen,
-					  const char *workgroup)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		/*
-		 * Can't use sync call while an async call is in flight
-		 */
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto fail;
-	}
-	ev = samba_tevent_context_init(frame);
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
-					     workgroup);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		goto fail;
-	}
-	status = cli_session_setup_lanman2_recv(req);
- fail:
-	TALLOC_FREE(frame);
-	return status;
-}
-
 /****************************************************************************
  Work out suitable capabilities to offer the server.
 ****************************************************************************/
@@ -536,44 +502,6 @@ NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
 	return tevent_req_simple_recv_ntstatus(req);
 }
 
-static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_OK;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		/*
-		 * Can't use sync call while an async call is in flight
-		 */
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto fail;
-	}
-
-	ev = samba_tevent_context_init(frame);
-	if (ev == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto fail;
-	}
-
-	req = cli_session_setup_guest_send(frame, ev, cli);
-	if (req == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto fail;
-	}
-
-	if (!tevent_req_poll(req, ev)) {
-		status = map_nt_error_from_unix(errno);
-		goto fail;
-	}
-
-	status = cli_session_setup_guest_recv(req);
- fail:
-	TALLOC_FREE(frame);
-	return status;
-}
-
 /****************************************************************************
  Do a NT1 plaintext session setup.
 ****************************************************************************/
@@ -739,40 +667,6 @@ static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
 	return tevent_req_simple_recv_ntstatus(req);
 }
 
-static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
-					const char *user, const char *pass,
-					const char *workgroup)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		/*
-		 * Can't use sync call while an async call is in flight
-		 */
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto fail;
-	}
-	ev = samba_tevent_context_init(frame);
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
-					   workgroup);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		goto fail;
-	}
-	status = cli_session_setup_plain_recv(req);
- fail:
-	TALLOC_FREE(frame);
-	return status;
-}
-
 /****************************************************************************
    do a NT1 NTLM/LM encrypted session setup - for when extended security
    is not negotiated.
@@ -1100,41 +994,6 @@ static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
 	return tevent_req_simple_recv_ntstatus(req);
 }
 
-static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
-				      const char *pass, size_t passlen,
-				      const char *ntpass, size_t ntpasslen,
-				      const char *workgroup)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		/*
-		 * Can't use sync call while an async call is in flight
-		 */
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto fail;
-	}
-	ev = samba_tevent_context_init(frame);
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
-					 ntpass, ntpasslen, workgroup);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		goto fail;
-	}
-	status = cli_session_setup_nt1_recv(req);
- fail:
-	TALLOC_FREE(frame);
-	return status;
-}
-
 /* The following is calculated from :
  * (smb_size-4) = 35
  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
@@ -1554,33 +1413,6 @@ static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
 	return state->ads_status;
 }
 
-static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
-					     const char *principal)
-{
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-	}
-	ev = samba_tevent_context_init(talloc_tos());
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll(req, ev)) {
-		status = ADS_ERROR_SYSTEM(errno);
-		goto fail;
-	}
-	status = cli_session_setup_kerberos_recv(req);
-fail:
-	TALLOC_FREE(ev);
-	return status;
-}
 #endif	/* HAVE_KRB5 */
 
 /****************************************************************************
@@ -2097,39 +1929,6 @@ static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
 	return state->result;
 }
 
-static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
-			      const char *user,
-			      const char *pass,
-			      const char *user_domain,
-			      const char * dest_realm)
-{
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	ADS_STATUS result = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-	NTSTATUS status;
-
-	if (smbXcli_conn_has_async_calls(cli->conn)) {
-		return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-	}
-	ev = samba_tevent_context_init(talloc_tos());
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_session_setup_spnego_send(ev, ev, cli, user, pass,
-					    user_domain, dest_realm);
-	if (req == NULL) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		result = ADS_ERROR_NT(status);
-		goto fail;
-	}
-	result = cli_session_setup_spnego_recv(req);
-fail:
-	TALLOC_FREE(ev);
-	return result;
-}
-
 struct cli_session_setup_state {
 	uint8_t dummy;
 };
-- 
1.7.9.5


From d544b921dfcd4b0f9cffaa3cccb5f7845204b02a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 4 Apr 2013 14:36:51 +0200
Subject: [PATCH 14/22] libsmbclient: Make cli_connect_sock async

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  165 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 125 insertions(+), 40 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 042205b..37b38ba 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2732,75 +2732,160 @@ fail:
 	return status;
 }
 
-static NTSTATUS cli_connect_sock(const char *host, int name_type,
-				 const struct sockaddr_storage *pss,
-				 const char *myname, uint16_t port,
-				 int sec_timeout, int *pfd, uint16_t *pport)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	const char *prog;
-	unsigned int i, num_addrs;
+struct cli_connect_sock_state {
 	const char **called_names;
 	const char **calling_names;
 	int *called_types;
-	NTSTATUS status;
 	int fd;
+	uint16_t port;
+};
+
+static void cli_connect_sock_done(struct tevent_req *subreq);
+
+/*
+ * Async only if we don't have to look up the name, i.e. "pss" is set with a
+ * nonzero address.
+ */
+
+static struct tevent_req *cli_connect_sock_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	const char *host, int name_type, const struct sockaddr_storage *pss,
+	const char *myname, uint16_t port)
+{
+	struct tevent_req *req, *subreq;
+	struct cli_connect_sock_state *state;
+	const char *prog;
+	unsigned i, num_addrs;
+	NTSTATUS status;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_connect_sock_state);
+	if (req == NULL) {
+		return NULL;
+	}
 
 	prog = getenv("LIBSMB_PROG");
 	if (prog != NULL) {
-		fd = sock_exec(prog);
-		if (fd == -1) {
-			return map_nt_error_from_unix(errno);
+		state->fd = sock_exec(prog);
+		if (state->fd == -1) {
+			status = map_nt_error_from_unix(errno);
+			tevent_req_nterror(req, status);
+		} else {
+			state->port = 0;
+			tevent_req_done(req);
 		}
-		port = 0;
-		goto done;
+		return tevent_req_post(req, ev);
 	}
 
 	if ((pss == NULL) || is_zero_addr(pss)) {
 		struct sockaddr_storage *addrs;
-		status = resolve_name_list(talloc_tos(), host, name_type,
+
+		/*
+		 * Here we cheat. resolve_name_list is not async at all. So
+		 * this call will only be really async if the name lookup has
+		 * been done externally.
+		 */
+
+		status = resolve_name_list(state, host, name_type,
 					   &addrs, &num_addrs);
 		if (!NT_STATUS_IS_OK(status)) {
-			goto fail;
+			tevent_req_nterror(req, status);
+			return tevent_req_post(req, ev);
 		}
 		pss = addrs;
 	} else {
 		num_addrs = 1;
 	}
 
-	called_names = talloc_array(talloc_tos(), const char *, num_addrs);
-	if (called_names == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto fail;
+	state->called_names = talloc_array(state, const char *, num_addrs);
+	if (tevent_req_nomem(state->called_names, req)) {
+		return tevent_req_post(req, ev);
+	}
+	state->called_types = talloc_array(state, int, num_addrs);
+	if (tevent_req_nomem(state->called_types, req)) {
+		return tevent_req_post(req, ev);
+	}
+	state->calling_names = talloc_array(state, const char *, num_addrs);
+	if (tevent_req_nomem(state->calling_names, req)) {
+		return tevent_req_post(req, ev);
+	}
+	for (i=0; i<num_addrs; i++) {
+		state->called_names[i] = host;
+		state->called_types[i] = name_type;
+		state->calling_names[i] = myname;
+	}
+
+	subreq = smbsock_any_connect_send(
+		state, ev, pss, state->called_names, state->called_types,
+		state->calling_names, NULL, num_addrs, port);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
 	}
-	called_types = talloc_array(talloc_tos(), int, num_addrs);
-	if (called_types == NULL) {
-		status = NT_STATUS_NO_MEMORY;
+	tevent_req_set_callback(subreq, cli_connect_sock_done, req);
+	return req;
+}
+
+static void cli_connect_sock_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_connect_sock_state *state = tevent_req_data(
+		req, struct cli_connect_sock_state);
+	NTSTATUS status;
+
+	status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
+					  &state->port);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
+				      int *pfd, uint16_t *pport)
+{
+	struct cli_connect_sock_state *state = tevent_req_data(
+		req, struct cli_connect_sock_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*pfd = state->fd;
+	*pport = state->port;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS cli_connect_sock(const char *host, int name_type,
+				 const struct sockaddr_storage *pss,
+				 const char *myname, uint16_t port,
+				 int sec_timeout, int *pfd, uint16_t *pport)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
 		goto fail;
 	}
-	calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
-	if (calling_names == NULL) {
-		status = NT_STATUS_NO_MEMORY;
+	req = cli_connect_sock_send(ev, ev, host, name_type, pss, myname,
+				    port);
+	if (req == NULL) {
 		goto fail;
 	}
-	for (i=0; i<num_addrs; i++) {
-		called_names[i] = host;
-		called_types[i] = name_type;
-		calling_names[i] = myname;
+	if ((sec_timeout != 0) &&
+	    !tevent_req_set_endtime(
+		    req, ev, timeval_current_ofs(sec_timeout, 0))) {
+		goto fail;
 	}
-	status = smbsock_any_connect(pss, called_names, called_types,
-				     calling_names, NULL, num_addrs, port,
-				     sec_timeout, &fd, NULL, &port);
-	if (!NT_STATUS_IS_OK(status)) {
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
 		goto fail;
 	}
-	set_socket_options(fd, lp_socket_options());
-done:
-	*pfd = fd;
-	*pport = port;
-	status = NT_STATUS_OK;
+	status = cli_connect_sock_recv(req, pfd, pport);
 fail:
-	TALLOC_FREE(frame);
+	TALLOC_FREE(ev);
 	return status;
 }
 
-- 
1.7.9.5


From bb214008081f44009a100a83fc2a1b3f156c77eb Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 4 Apr 2013 15:01:25 +0200
Subject: [PATCH 15/22] libsmbclient: Avoid a talloc_strdup in cli_connect_nb

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 37b38ba..b800773 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2900,10 +2900,8 @@ NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss
 	char *desthost;
 	char *p;
 
-	desthost = talloc_strdup(talloc_tos(), host);
-	if (desthost == NULL) {
-		goto fail;
-	}
+	/* Save the original host definition for cli_state_create */
+	desthost = host;
 
 	p = strchr(host, '#');
 	if (p != NULL) {
-- 
1.7.9.5


From d62375259dc0b17d6cf517d0842bf4ba80526e43 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 4 Apr 2013 16:55:48 +0200
Subject: [PATCH 16/22] libsmbclient: Add async cli_connect_nb

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  118 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 94 insertions(+), 24 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index b800773..1873e7a 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2889,46 +2889,116 @@ fail:
 	return status;
 }
 
-NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
-			uint16_t port, int name_type, const char *myname,
-			int signing_state, int flags, struct cli_state **pcli)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
+struct cli_connect_nb_state {
+	const char *desthost;
+	int signing_state;
+	int flags;
 	struct cli_state *cli;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-	int fd = -1;
-	char *desthost;
+};
+
+static void cli_connect_nb_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_connect_nb_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	const char *host, const struct sockaddr_storage *dest_ss,
+	uint16_t port, int name_type, const char *myname,
+	int signing_state, int flags)
+{
+	struct tevent_req *req, *subreq;
+	struct cli_connect_nb_state *state;
 	char *p;
 
-	/* Save the original host definition for cli_state_create */
-	desthost = host;
+	req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->desthost = host;
+	state->signing_state = signing_state;
+	state->flags = flags;
 
 	p = strchr(host, '#');
 	if (p != NULL) {
 		name_type = strtol(p+1, NULL, 16);
-		host = talloc_strndup(talloc_tos(), host, p - host);
-		if (host == NULL) {
-			goto fail;
+		host = talloc_strndup(state, host, p - host);
+		if (tevent_req_nomem(host, req)) {
+			return tevent_req_post(req, ev);
 		}
 	}
 
-	status = cli_connect_sock(host, name_type, dest_ss, myname, port,
-				  20, &fd, &port);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
+	subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
+				       myname, port);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
 	}
+	tevent_req_set_callback(subreq, cli_connect_nb_done, req);
+	return req;
+}
 
-	cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
-	if (cli == NULL) {
+static void cli_connect_nb_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_connect_nb_state *state = tevent_req_data(
+		req, struct cli_connect_nb_state);
+	NTSTATUS status;
+	int fd;
+	uint16_t port;
+
+	status = cli_connect_sock_recv(subreq, &fd, &port);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	state->cli = cli_state_create(state, fd, state->desthost, NULL,
+				      state->signing_state, state->flags);
+	if (tevent_req_nomem(state->cli, req)) {
 		close(fd);
-		fd = -1;
-		goto fail;
+		return;
 	}
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
+				    struct cli_state **pcli)
+{
+	struct cli_connect_nb_state *state = tevent_req_data(
+		req, struct cli_connect_nb_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*pcli = talloc_move(NULL, &state->cli);
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
+			uint16_t port, int name_type, const char *myname,
+			int signing_state, int flags, struct cli_state **pcli)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-	*pcli = cli;
-	status = NT_STATUS_OK;
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
+				  myname, signing_state, flags);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_connect_nb_recv(req, pcli);
 fail:
-	TALLOC_FREE(frame);
+	TALLOC_FREE(ev);
 	return status;
 }
 
-- 
1.7.9.5


From 7d8be2a6630545babbf434026b6adfd9ce857bd0 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 4 Apr 2013 16:56:43 +0200
Subject: [PATCH 17/22] libsmbclient: Remove unused cli_connect_sock

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 1873e7a..679a73b 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2857,38 +2857,6 @@ static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS cli_connect_sock(const char *host, int name_type,
-				 const struct sockaddr_storage *pss,
-				 const char *myname, uint16_t port,
-				 int sec_timeout, int *pfd, uint16_t *pport)
-{
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-	ev = samba_tevent_context_init(talloc_tos());
-	if (ev == NULL) {
-		goto fail;
-	}
-	req = cli_connect_sock_send(ev, ev, host, name_type, pss, myname,
-				    port);
-	if (req == NULL) {
-		goto fail;
-	}
-	if ((sec_timeout != 0) &&
-	    !tevent_req_set_endtime(
-		    req, ev, timeval_current_ofs(sec_timeout, 0))) {
-		goto fail;
-	}
-	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
-		goto fail;
-	}
-	status = cli_connect_sock_recv(req, pfd, pport);
-fail:
-	TALLOC_FREE(ev);
-	return status;
-}
-
 struct cli_connect_nb_state {
 	const char *desthost;
 	int signing_state;
-- 
1.7.9.5


From cf4116ba1ff477acec2faf8d39d2a900ca37ef1f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 12:42:01 +0200
Subject: [PATCH 18/22] libsmbclient: Make cli_start_connection async

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  120 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 102 insertions(+), 18 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 679a73b..ee1d9ad 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2970,6 +2970,14 @@ fail:
 	return status;
 }
 
+struct cli_start_connection_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+};
+
+static void cli_start_connection_connected(struct tevent_req *subreq);
+static void cli_start_connection_done(struct tevent_req *subreq);
+
 /**
    establishes a connection to after the negprot. 
    @param output_cli A fully initialised cli structure, non-null only on success
@@ -2977,33 +2985,109 @@ fail:
    @param dest_ss (optional) The the destination IP, NULL for name based lookup
    @param port (optional) The destination port (0 for default)
 */
+
+static struct tevent_req *cli_start_connection_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	const char *my_name, const char *dest_host,
+	const struct sockaddr_storage *dest_ss, int port,
+	int signing_state, int flags)
+{
+	struct tevent_req *req, *subreq;
+	struct cli_start_connection_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_start_connection_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+
+	subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
+				     0x20, my_name, signing_state, flags);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_start_connection_connected, req);
+	return req;
+}
+
+static void cli_start_connection_connected(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_start_connection_state *state = tevent_req_data(
+		req, struct cli_start_connection_state);
+	NTSTATUS status;
+
+	status = cli_connect_nb_recv(subreq, &state->cli);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
+				      state->cli->timeout,
+				      PROTOCOL_CORE, PROTOCOL_NT1);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_start_connection_done, req);
+}
+
+static void cli_start_connection_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = smbXcli_negprot_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
+					  struct cli_state **output_cli)
+{
+	struct cli_start_connection_state *state = tevent_req_data(
+		req, struct cli_start_connection_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*output_cli = state->cli;
+	return NT_STATUS_OK;
+}
+
 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
 			      const char *my_name, 
 			      const char *dest_host, 
 			      const struct sockaddr_storage *dest_ss, int port,
 			      int signing_state, int flags)
 {
-	NTSTATUS nt_status;
-	struct cli_state *cli;
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-	nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
-				   signing_state, flags, &cli);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(10, ("cli_connect_nb failed: %s\n",
-			   nt_errstr(nt_status)));
-		return nt_status;
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
 	}
-
-	nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
-				    PROTOCOL_NT1);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
-		cli_shutdown(cli);
-		return nt_status;
+	req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
+					port, signing_state, flags);
+	if (req == NULL) {
+		goto fail;
 	}
-
-	*output_cli = cli;
-	return NT_STATUS_OK;
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_start_connection_recv(req, output_cli);
+fail:
+	TALLOC_FREE(ev);
+	return status;
 }
 
 
-- 
1.7.9.5


From 1b48bc594f232ed3dd4f3ccf35530e45876a65ed Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 15:29:14 +0200
Subject: [PATCH 19/22] libsmbclient: Make cli_raw_tcon async

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |   98 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 15 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ee1d9ad..96acab5 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -3177,22 +3177,33 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
 /****************************************************************************
  Send an old style tcon.
 ****************************************************************************/
-NTSTATUS cli_raw_tcon(struct cli_state *cli, 
-		      const char *service, const char *pass, const char *dev,
-		      uint16 *max_xmit, uint16 *tid)
-{
-	struct tevent_req *req;
+struct cli_raw_tcon_state {
 	uint16_t *ret_vwv;
+};
+
+static void cli_raw_tcon_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_raw_tcon_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+	const char *service, const char *pass, const char *dev)
+{
+	struct tevent_req *req, *subreq;
+	struct cli_raw_tcon_state *state;
 	uint8_t *bytes;
-	NTSTATUS status;
+
+	req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
+	if (req == NULL) {
+		return NULL;
+	}
 
 	if (!lp_client_plaintext_auth() && (*pass)) {
 		DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
 			  " or 'client ntlmv2 auth = yes'\n"));
-		return NT_STATUS_ACCESS_DENIED;
+		tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+		return tevent_req_post(req, ev);
 	}
 
-	bytes = talloc_array(talloc_tos(), uint8_t, 0);
+	bytes = talloc_array(state, uint8_t, 0);
 	bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
 	bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
 				   service, strlen(service)+1, NULL);
@@ -3203,19 +3214,76 @@ NTSTATUS cli_raw_tcon(struct cli_state *cli,
 	bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
 				   dev, strlen(dev)+1, NULL);
 
-	status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
-			 talloc_get_size(bytes), bytes, &req,
-			 2, NULL, &ret_vwv, NULL, NULL);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
+	if (tevent_req_nomem(bytes, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
+			      talloc_get_size(bytes), bytes);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
+	return req;
+}
+
+static void cli_raw_tcon_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_raw_tcon_state *state = tevent_req_data(
+		req, struct cli_raw_tcon_state);
+	NTSTATUS status;
+
+	status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
+			      NULL, NULL);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
 	}
+	tevent_req_done(req);
+}
 
-	*max_xmit = SVAL(ret_vwv + 0, 0);
-	*tid = SVAL(ret_vwv + 1, 0);
+static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
+				  uint16 *max_xmit, uint16 *tid)
+{
+	struct cli_raw_tcon_state *state = tevent_req_data(
+		req, struct cli_raw_tcon_state);
+	NTSTATUS status;
 
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*max_xmit = SVAL(state->ret_vwv + 0, 0);
+	*tid = SVAL(state->ret_vwv + 1, 0);
 	return NT_STATUS_OK;
 }
 
+NTSTATUS cli_raw_tcon(struct cli_state *cli,
+		      const char *service, const char *pass, const char *dev,
+		      uint16 *max_xmit, uint16 *tid)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_raw_tcon_recv(req, max_xmit, tid);
+fail:
+	TALLOC_FREE(ev);
+	return status;
+}
+
 /* Return a cli_state pointing at the IPC$ share for the given server */
 
 struct cli_state *get_ipc_connect(char *server,
-- 
1.7.9.5


From 47e402941f8a45db4382887598893f9a35df4206 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 6 Apr 2013 10:57:41 +0200
Subject: [PATCH 20/22] libsmbclient: Make cli_tree_connect async

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  123 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 14 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 96acab5..5392de7 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2622,34 +2622,129 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
 	return status;
 }
 
-NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
-			  const char *dev, const char *pass, int passlen)
+struct cli_tree_connect_state {
+	struct cli_state *cli;
+};
+
+static struct tevent_req *cli_raw_tcon_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+	const char *service, const char *pass, const char *dev);
+static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
+				  uint16 *max_xmit, uint16 *tid);
+
+static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
+static void cli_tree_connect_andx_done(struct tevent_req *subreq);
+static void cli_tree_connect_raw_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_tree_connect_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+	const char *share, const char *dev, const char *pass, int passlen)
 {
-	NTSTATUS status;
-	uint16_t max_xmit = 0;
-	uint16_t tid = 0;
+	struct tevent_req *req, *subreq;
+	struct cli_tree_connect_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_tree_connect_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->cli = cli;
 
 	cli->share = talloc_strdup(cli, share);
-	if (!cli->share) {
-		return NT_STATUS_NO_MEMORY;
+	if (tevent_req_nomem(cli->share, req)) {
+		return tevent_req_post(req, ev);
 	}
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		return smb2cli_tcon(cli, share);
+		subreq = smb2cli_tcon_send(state, ev, cli, share);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
+					req);
+		return req;
 	}
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
-		return cli_tcon_andx(cli, share, dev, pass, passlen);
+		subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
+					    pass, passlen);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
+					req);
+		return req;
 	}
 
-	status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
+	subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
 	}
+	tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
 
-	cli_state_set_tid(cli, tid);
+	return req;
+}
 
-	return NT_STATUS_OK;
+static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
+{
+	return tevent_req_simple_finish_ntstatus(
+		subreq, smb2cli_tcon_recv(subreq));
+}
+
+static void cli_tree_connect_andx_done(struct tevent_req *subreq)
+{
+	return tevent_req_simple_finish_ntstatus(
+		subreq, cli_tcon_andx_recv(subreq));
+}
+
+static void cli_tree_connect_raw_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_tree_connect_state *state = tevent_req_data(
+		req, struct cli_tree_connect_state);
+	NTSTATUS status;
+	uint16_t max_xmit = 0;
+	uint16_t tid = 0;
+
+	status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	cli_state_set_tid(state->cli, tid);
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
+			  const char *dev, const char *pass, int passlen)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_tree_connect_recv(req);
+fail:
+	TALLOC_FREE(ev);
+	return status;
 }
 
 /****************************************************************************
-- 
1.7.9.5


From 8726bf02aeb5671504409086d60103e90e1dba38 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Apr 2013 14:55:26 +0200
Subject: [PATCH 21/22] libsmbclient: Make cli_full_connection async

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/cliconnect.c |  240 ++++++++++++++++++++++++++++++++++---------
 source3/libsmb/proto.h      |    9 ++
 2 files changed, 199 insertions(+), 50 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 5392de7..bdfec41 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -3185,7 +3185,6 @@ fail:
 	return status;
 }
 
-
 /**
    establishes a connection right up to doing tconX, password specified.
    @param output_cli A fully initialised cli structure, non-null only on success
@@ -3199,76 +3198,217 @@ fail:
    @param password User's password, unencrypted unix string.
 */
 
-NTSTATUS cli_full_connection(struct cli_state **output_cli, 
-			     const char *my_name, 
-			     const char *dest_host, 
-			     const struct sockaddr_storage *dest_ss, int port,
-			     const char *service, const char *service_type,
-			     const char *user, const char *domain, 
-			     const char *password, int flags,
-			     int signing_state)
+struct cli_full_connection_state {
+	struct tevent_context *ev;
+	const char *service;
+	const char *service_type;
+	const char *user;
+	const char *domain;
+	const char *password;
+	int pw_len;
+	int flags;
+	struct cli_state *cli;
+};
+
+static int cli_full_connection_state_destructor(
+	struct cli_full_connection_state *s);
+static void cli_full_connection_started(struct tevent_req *subreq);
+static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
+static void cli_full_connection_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_full_connection_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	const char *my_name, const char *dest_host,
+	const struct sockaddr_storage *dest_ss, int port,
+	const char *service, const char *service_type,
+	const char *user, const char *domain,
+	const char *password, int flags, int signing_state)
 {
-	NTSTATUS nt_status;
-	struct cli_state *cli = NULL;
-	int pw_len = password ? strlen(password)+1 : 0;
+	struct tevent_req *req, *subreq;
+	struct cli_full_connection_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_full_connection_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	talloc_set_destructor(state, cli_full_connection_state_destructor);
 
-	*output_cli = NULL;
+	state->ev = ev;
+	state->service = service;
+	state->service_type = service_type;
+	state->user = user;
+	state->domain = domain;
+	state->password = password;
+	state->flags = flags;
+
+	state->pw_len = state->password ? strlen(state->password)+1 : 0;
+	if (state->password == NULL) {
+		state->password = "";
+	}
+
+	subreq = cli_start_connection_send(
+		state, ev, my_name, dest_host, dest_ss, port,
+		signing_state, flags);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_full_connection_started, req);
+	return req;
+}
 
-	if (password == NULL) {
-		password = "";
+static int cli_full_connection_state_destructor(
+	struct cli_full_connection_state *s)
+{
+	if (s->cli != NULL) {
+		cli_shutdown(s->cli);
+		s->cli = NULL;
 	}
+	return 0;
+}
 
-	nt_status = cli_start_connection(&cli, my_name, dest_host,
-					 dest_ss, port, signing_state,
-					 flags);
+static void cli_full_connection_started(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_full_connection_state *state = tevent_req_data(
+		req, struct cli_full_connection_state);
+	NTSTATUS status;
 
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
+	status = cli_start_connection_recv(subreq, &state->cli);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
 	}
+	subreq = cli_session_setup_send(
+		state, state->ev, state->cli, state->user,
+		state->password, state->pw_len, state->password, state->pw_len,
+		state->domain);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
+}
+
+static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_full_connection_state *state = tevent_req_data(
+		req, struct cli_full_connection_state);
+	NTSTATUS status;
+
+	status = cli_session_setup_recv(subreq);
+	TALLOC_FREE(subreq);
 
-	nt_status = cli_session_setup(cli, user, password, pw_len, password,
-				      pw_len, domain);
-	if (!NT_STATUS_IS_OK(nt_status)) {
+	if (!NT_STATUS_IS_OK(status) &&
+	    (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
 
-		if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
-			DEBUG(1,("failed session setup with %s\n",
-				 nt_errstr(nt_status)));
-			cli_shutdown(cli);
-			return nt_status;
-		}
+		state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
 
-		nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			DEBUG(1,("anonymous failed session setup with %s\n",
-				 nt_errstr(nt_status)));
-			cli_shutdown(cli);
-			return nt_status;
+		subreq = cli_session_setup_send(
+			state, state->ev, state->cli, "", "", 0, "", 0,
+			state->domain);
+		if (tevent_req_nomem(subreq, req)) {
+			return;
 		}
+		tevent_req_set_callback(
+			subreq, cli_full_connection_sess_set_up, req);
+		return;
 	}
 
-	if (service) {
-		nt_status = cli_tree_connect(cli, service, service_type,
-					     password, pw_len);
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
-			cli_shutdown(cli);
-			if (NT_STATUS_IS_OK(nt_status)) {
-				nt_status = NT_STATUS_UNSUCCESSFUL;
-			}
-			return nt_status;
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	if (state->service != NULL) {
+		subreq = cli_tree_connect_send(
+			state, state->ev, state->cli,
+			state->service, state->service_type,
+			state->password, state->pw_len);
+		if (tevent_req_nomem(subreq, req)) {
+			return;
 		}
+		tevent_req_set_callback(subreq, cli_full_connection_done, req);
+		return;
 	}
 
-	nt_status = cli_init_creds(cli, user, domain, password);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		cli_shutdown(cli);
-		return nt_status;
+	status = cli_init_creds(state->cli, state->user, state->domain,
+				state->password);
+	if (tevent_req_nterror(req, status)) {
+		return;
 	}
+	tevent_req_done(req);
+}
+
+static void cli_full_connection_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_full_connection_state *state = tevent_req_data(
+		req, struct cli_full_connection_state);
+	NTSTATUS status;
+
+	status = cli_tree_connect_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	status = cli_init_creds(state->cli, state->user, state->domain,
+				state->password);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+NTSTATUS cli_full_connection_recv(struct tevent_req *req,
+				  struct cli_state **output_cli)
+{
+	struct cli_full_connection_state *state = tevent_req_data(
+		req, struct cli_full_connection_state);
+	NTSTATUS status;
 
-	*output_cli = cli;
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	*output_cli = state->cli;
+	talloc_set_destructor(state, NULL);
 	return NT_STATUS_OK;
 }
 
+NTSTATUS cli_full_connection(struct cli_state **output_cli,
+			     const char *my_name,
+			     const char *dest_host,
+			     const struct sockaddr_storage *dest_ss, int port,
+			     const char *service, const char *service_type,
+			     const char *user, const char *domain,
+			     const char *password, int flags,
+			     int signing_state)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_full_connection_send(
+		ev, ev, my_name, dest_host, dest_ss, port, service,
+		service_type, user, domain, password, flags, signing_state);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_full_connection_recv(req, output_cli);
+ fail:
+	TALLOC_FREE(ev);
+	return status;
+}
+
 /****************************************************************************
  Send an old style tcon.
 ****************************************************************************/
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 182750c..48496c8 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -88,6 +88,15 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
 			      const char *dest_host,
 			      const struct sockaddr_storage *dest_ss, int port,
 			      int signing_state, int flags);
+struct tevent_req *cli_full_connection_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	const char *my_name, const char *dest_host,
+	const struct sockaddr_storage *dest_ss, int port,
+	const char *service, const char *service_type,
+	const char *user, const char *domain,
+	const char *password, int flags, int signing_state);
+NTSTATUS cli_full_connection_recv(struct tevent_req *req,
+				  struct cli_state **output_cli);
 NTSTATUS cli_full_connection(struct cli_state **output_cli,
 			     const char *my_name,
 			     const char *dest_host,
-- 
1.7.9.5


From b59562f51193db5f5b635a83ab467489158b6fb1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 9 Apr 2013 12:15:02 +0200
Subject: [PATCH 22/22] libsmbclient: Use async cli_full_connection in python
 connection setup

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/pylibsmb.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 2b253f9..ae0d694 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -408,6 +408,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	char *host, *share;
 	PyObject *creds = NULL;
 	struct cli_credentials *cli_creds;
+	struct tevent_req *req;
 	bool ret;
 
 	static const char *kwlist[] = {
@@ -440,12 +441,18 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 		cli_creds = PyCredentials_AsCliCredentials(creds);
 	}
 
-	status = cli_full_connection(
-		&self->cli, "myname", host, NULL, 0, share, "?????",
+	req = cli_full_connection_send(
+		NULL, self->ev, "myname", host, NULL, 0, share, "?????",
 		cli_credentials_get_username(cli_creds),
 		cli_credentials_get_domain(cli_creds),
 		cli_credentials_get_password(cli_creds),
 		0, 0);
+	if (!py_tevent_req_wait_exc(self->ev, req)) {
+		return NULL;
+	}
+	status = cli_full_connection_recv(req, &self->cli);
+	TALLOC_FREE(req);
+
 	if (!NT_STATUS_IS_OK(status)) {
 		PyErr_SetNTSTATUS(status);
 		return -1;
-- 
1.7.9.5



More information about the samba-technical mailing list