[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_don