[PATCH] Make cli_full_connection async

Volker Lendecke Volker.Lendecke at SerNet.DE
Wed Apr 10 08:49:47 MDT 2013


On Wed, Apr 10, 2013 at 01:11:09PM +0200, Volker Lendecke wrote:
> 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.

Christian did review, found that I had forgotten the
set_socket_options in cli_connect_sock_done. New version
attached...

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 1b33a79c8048b10b4464d32dccac03aab67bb677 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 01/22] libsmbclient: Fix a leak on talloc_tos()

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ec5c273..d0e67db 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.3.4


From a103e234b5a44db0a0757a742943724bc32117b9 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 02/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 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index d0e67db..a67d25f 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.3.4


From 0a8128cd52a895b1db02f728d97becffa57a8ead 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 03/22] libsmbclient: Factor out cli_session_setup_get_principal

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index a67d25f..742921d 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.3.4


From cd16268fd7f3ebdd5919ac14aa3e9d55e171404a 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 04/22] libsmbclient: Slightly simplify cli_session_setup_spnego

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 742921d..253cc70 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.3.4


From 7eac05fa1cab24878b0668119038bcbbe5094e15 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 05/22] libsmbclient: Factor out cli_session_setup_get_account

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 253cc70..212cc3e 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.3.4


From 4eb9e2c0dfe8603f0bc19cee5541417024be3d2d 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 06/22] libsmbclient: Add async cli_session_setup_ntlmssp

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 212cc3e..7d7c55a 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.3.4


From 5e71aeb07f0f639e68a004bbc30747010b1a277c 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 07/22] libsmbclient: Remove unused cli_session_setup_ntlmssp()

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 7d7c55a..233f824 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.3.4


From 8efe9b055c9882cd22df8f7e0168a85cecbb278d 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 08/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 233f824..7ec0653 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.3.4


From 10472b6cfc042dfd7dc8f7a45697fd7da43ae841 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 09/22] libsmbclient: Remove unused sync wrappers

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 7ec0653..baf7931 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.3.4


From 82a12ed15d79bcf24eb854809a845a11d21c73b9 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 10/22] libsmbclient: Make cli_connect_sock async

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index baf7931..255b76a 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2735,75 +2735,161 @@ 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);
 	}
-	called_types = talloc_array(talloc_tos(), int, num_addrs);
-	if (called_types == NULL) {
-		status = NT_STATUS_NO_MEMORY;
+	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);
+	}
+	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;
+	}
+	set_socket_options(state->fd, lp_socket_options());
+	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.3.4


From ff92ab172007047a2499163b4d8b0e87682a7cdb 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 11/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 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 255b76a..1624e7b 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2904,10 +2904,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.3.4


From b330e4db7f04935eb45e6a253b62c923dfc4b134 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 12/22] libsmbclient: Add async cli_connect_nb

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 1624e7b..11b3ee6 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2893,46 +2893,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.3.4


From 5fc97e24090d6b4725e7a7b2c8afb5647e777482 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 13/22] libsmbclient: Remove unused cli_connect_sock

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 11b3ee6..ce4b822 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2861,38 +2861,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.3.4


From ba0e380a590e13d994f21db0ecfe178ae812d0a4 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 14/22] libsmbclient: Make cli_start_connection async

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ce4b822..36970cc 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2974,6 +2974,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
@@ -2981,33 +2989,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.3.4


From 49c784669955517f22a4dbb4560398902e52d991 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 15/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 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 36970cc..0397b48 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2614,8 +2614,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.3.4


From 1376f4573990999f45227c94b647435e46ed5a5b 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 16/22] libsmbclient: Streamline cli_tcon_andx a bit

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

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 0397b48..bcc95ba 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2592,7 +2592,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)) {
 		/*
@@ -2604,13 +2604,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.3.4


From 98d69fd07a0a2490c02845a725d57e65f1719ff6 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 17/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 files changed, 1 insertions(+), 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.3.4


From 9faf06d7b1ceeec15769dff0d05e496df2afd704 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 18/22] libsmbclient: Streamline cli_openx a bit

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/libsmb/clifile.c |    4 +---
 1 files changed, 1 insertions(+), 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.3.4


From 0dcade18f4cd300787f39c332d2b6e46e8313ac8 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 files changed, 83 insertions(+), 15 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index bcc95ba..f196941 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -3178,22 +3178,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);
@@ -3204,19 +3215,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.3.4


From 91aefb0881ade9f3afb976b7fca67298d89c368e 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 files changed, 109 insertions(+), 14 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index f196941..b5055cc 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.3.4


From 55d64a46013e97a8b85c67b4e2cd730594f823d6 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 b5055cc..3242d8c 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -3186,7 +3186,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
@@ -3200,76 +3199,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.3.4


From 97d03ac62610aeb457b897d0773fcdd4b56166e2 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 files 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.3.4



More information about the samba-technical mailing list