diff options
Diffstat (limited to 'source4/libcli/smb2')
-rw-r--r-- | source4/libcli/smb2/connect.c | 448 | ||||
-rw-r--r-- | source4/libcli/smb2/session.c | 234 | ||||
-rw-r--r-- | source4/libcli/smb2/wscript_build | 3 |
3 files changed, 407 insertions, 278 deletions
diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 64ed6c3acc..0e3bf1512b 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -20,6 +20,8 @@ */ #include "includes.h" +#include <tevent.h> +#include "lib/util/tevent_ntstatus.h" #include "libcli/raw/libcliraw.h" #include "libcli/raw/raw_proto.h" #include "libcli/smb2/smb2.h" @@ -29,6 +31,7 @@ #include "param/param.h" struct smb2_connect_state { + struct tevent_context *ev; struct cli_credentials *credentials; struct resolve_context *resolve_ctx; const char *host; @@ -43,67 +46,167 @@ struct smb2_connect_state { struct smb2_tree *tree; }; +static void smb2_connect_resolve_done(struct composite_context *creq); + /* - continue after tcon reply -*/ -static void continue_tcon(struct smb2_request *req) + a composite function that does a full negprot/sesssetup/tcon, returning + a connected smb2_tree + */ +struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *host, + const char **ports, + const char *share, + struct resolve_context *resolve_ctx, + struct cli_credentials *credentials, + struct smbcli_options *options, + const char *socket_options, + struct gensec_settings *gensec_settings) { - struct composite_context *c = talloc_get_type(req->async.private_data, - struct composite_context); - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - - c->status = smb2_tree_connect_recv(req, &state->tcon); - if (!composite_is_ok(c)) return; - - state->tree->tid = state->tcon.out.tid; + struct tevent_req *req; + struct smb2_connect_state *state; + struct nbt_name name; + struct composite_context *creq; + + req = tevent_req_create(mem_ctx, &state, + struct smb2_connect_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->credentials = credentials; + state->options = *options; + state->host = host; + state->ports = ports; + state->share = share; + state->resolve_ctx = resolve_ctx; + state->socket_options = socket_options; + state->gensec_settings = gensec_settings; + + ZERO_STRUCT(name); + name.name = host; - composite_done(c); + creq = resolve_name_send(resolve_ctx, state, &name, ev); + if (tevent_req_nomem(creq, req)) { + return tevent_req_post(req, ev); + } + creq->async.fn = smb2_connect_resolve_done; + creq->async.private_data = req; + return req; } -/* - continue after a session setup -*/ -static void continue_session(struct composite_context *creq) +static void smb2_connect_socket_done(struct composite_context *creq); + +static void smb2_connect_resolve_done(struct composite_context *creq) { - struct composite_context *c = talloc_get_type(creq->async.private_data, - struct composite_context); - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - struct smb2_request *req; + struct tevent_req *req = + talloc_get_type_abort(creq->async.private_data, + struct tevent_req); + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); + NTSTATUS status; + const char *addr; + const char **ports; + const char *default_ports[] = { "445", NULL }; - c->status = smb2_session_setup_spnego_recv(creq); - if (!composite_is_ok(c)) return; + status = resolve_name_recv(creq, state, &addr); + if (tevent_req_nterror(req, status)) { + return; + } - state->tree = smb2_tree_init(state->session, state, true); - if (composite_nomem(state->tree, c)) return; + if (state->ports == NULL) { + ports = default_ports; + } else { + ports = state->ports; + } - state->tcon.in.reserved = 0; - state->tcon.in.path = talloc_asprintf(state, "\\\\%s\\%s", - state->host, state->share); - if (composite_nomem(state->tcon.in.path, c)) return; - - req = smb2_tree_connect_send(state->tree, &state->tcon); - if (composite_nomem(req, c)) return; + creq = smbcli_sock_connect_send(state, addr, ports, + state->host, state->resolve_ctx, + state->ev, state->socket_options); + if (tevent_req_nomem(creq, req)) { + return; + } + creq->async.fn = smb2_connect_socket_done; + creq->async.private_data = req; +} + +static void smb2_connect_negprot_done(struct smb2_request *smb2req); - req->async.fn = continue_tcon; - req->async.private_data = c; +static void smb2_connect_socket_done(struct composite_context *creq) +{ + struct tevent_req *req = + talloc_get_type_abort(creq->async.private_data, + struct tevent_req); + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); + struct smbcli_socket *sock; + struct smb2_transport *transport; + struct smb2_request *smb2req; + NTSTATUS status; + uint16_t dialects[3] = { + SMB2_DIALECT_REVISION_000, + SMB2_DIALECT_REVISION_202, + SMB2_DIALECT_REVISION_210 + }; + + status = smbcli_sock_connect_recv(creq, state, &sock); + if (tevent_req_nterror(req, status)) { + return; + } + + transport = smb2_transport_init(sock, state, &state->options); + if (tevent_req_nomem(transport, req)) { + return; + } + + ZERO_STRUCT(state->negprot); + state->negprot.in.dialect_count = ARRAY_SIZE(dialects); + switch (transport->options.signing) { + case SMB_SIGNING_OFF: + state->negprot.in.security_mode = 0; + break; + case SMB_SIGNING_SUPPORTED: + case SMB_SIGNING_AUTO: + state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; + break; + case SMB_SIGNING_REQUIRED: + state->negprot.in.security_mode = + SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; + break; + } + state->negprot.in.capabilities = 0; + unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); + state->negprot.in.dialects = dialects; + + smb2req = smb2_negprot_send(transport, &state->negprot); + if (tevent_req_nomem(smb2req, req)) { + return; + } + smb2req->async.fn = smb2_connect_negprot_done; + smb2req->async.private_data = req; } -/* - continue after negprot reply -*/ -static void continue_negprot(struct smb2_request *req) +static void smb2_connect_session_done(struct tevent_req *subreq); + +static void smb2_connect_negprot_done(struct smb2_request *smb2req) { - struct composite_context *c = talloc_get_type(req->async.private_data, - struct composite_context); - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - struct smb2_transport *transport = req->transport; - struct composite_context *creq; + struct tevent_req *req = + talloc_get_type_abort(smb2req->async.private_data, + struct tevent_req); + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); + struct smb2_transport *transport = smb2req->transport; + struct tevent_req *subreq; + NTSTATUS status; - c->status = smb2_negprot_recv(req, c, &state->negprot); - if (!composite_is_ok(c)) return; + status = smb2_negprot_recv(smb2req, state, &state->negprot); + if (tevent_req_nterror(req, status)) { + return; + } transport->negotiate.secblob = state->negprot.out.secblob; talloc_steal(transport, transport->negotiate.secblob.data); @@ -115,7 +218,7 @@ static void continue_negprot(struct smb2_request *req) switch (transport->options.signing) { case SMB_SIGNING_OFF: if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { - composite_error(c, NT_STATUS_ACCESS_DENIED); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return; } transport->signing_required = false; @@ -138,179 +241,158 @@ static void continue_negprot(struct smb2_request *req) if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { transport->signing_required = true; } else { - composite_error(c, NT_STATUS_ACCESS_DENIED); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return; } break; } state->session = smb2_session_init(transport, state->gensec_settings, state, true); - if (composite_nomem(state->session, c)) return; - - creq = smb2_session_setup_spnego_send(state->session, state->credentials); - - composite_continue(c, creq, continue_session, c); -} - -/* - continue after a socket connect completes -*/ -static void continue_socket(struct composite_context *creq) -{ - struct composite_context *c = talloc_get_type(creq->async.private_data, - struct composite_context); - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - struct smbcli_socket *sock; - struct smb2_transport *transport; - struct smb2_request *req; - uint16_t dialects[3] = { - SMB2_DIALECT_REVISION_000, - SMB2_DIALECT_REVISION_202, - SMB2_DIALECT_REVISION_210 - }; - - c->status = smbcli_sock_connect_recv(creq, state, &sock); - if (!composite_is_ok(c)) return; - - transport = smb2_transport_init(sock, state, &state->options); - if (composite_nomem(transport, c)) return; - - ZERO_STRUCT(state->negprot); - state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]); - switch (transport->options.signing) { - case SMB_SIGNING_OFF: - state->negprot.in.security_mode = 0; - break; - case SMB_SIGNING_SUPPORTED: - case SMB_SIGNING_AUTO: - state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; - break; - case SMB_SIGNING_REQUIRED: - state->negprot.in.security_mode = - SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; - break; + if (tevent_req_nomem(state->session, req)) { + return; } - state->negprot.in.capabilities = 0; - unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); - state->negprot.in.dialects = dialects; - req = smb2_negprot_send(transport, &state->negprot); - if (composite_nomem(req, c)) return; - - req->async.fn = continue_negprot; - req->async.private_data = c; + subreq = smb2_session_setup_spnego_send(state, state->ev, + state->session, + state->credentials); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, smb2_connect_session_done, req); } +static void smb2_connect_tcon_done(struct smb2_request *smb2req); -/* - continue after a resolve finishes -*/ -static void continue_resolve(struct composite_context *creq) +static void smb2_connect_session_done(struct tevent_req *subreq) { - struct composite_context *c = talloc_get_type(creq->async.private_data, - struct composite_context); - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - const char *addr; - const char **ports; - const char *default_ports[] = { "445", NULL }; + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); + struct smb2_request *smb2req; + NTSTATUS status; - c->status = resolve_name_recv(creq, state, &addr); - if (!composite_is_ok(c)) return; + status = smb2_session_setup_spnego_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } - if (state->ports == NULL) { - ports = default_ports; - } else { - ports = state->ports; + state->tree = smb2_tree_init(state->session, state, true); + if (tevent_req_nomem(state->tree, req)) { + return; } - creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options); + state->tcon.in.reserved = 0; + state->tcon.in.path = talloc_asprintf(state, "\\\\%s\\%s", + state->host, state->share); + if (tevent_req_nomem(state->tcon.in.path, req)) { + return; + } - composite_continue(c, creq, continue_socket, c); + smb2req = smb2_tree_connect_send(state->tree, &state->tcon); + if (tevent_req_nomem(smb2req, req)) { + return; + } + smb2req->async.fn = smb2_connect_tcon_done; + smb2req->async.private_data = req; } -/* - a composite function that does a full negprot/sesssetup/tcon, returning - a connected smb2_tree - */ -struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx, - const char *host, - const char **ports, - const char *share, - struct resolve_context *resolve_ctx, - struct cli_credentials *credentials, - struct tevent_context *ev, - struct smbcli_options *options, - const char *socket_options, - struct gensec_settings *gensec_settings) +static void smb2_connect_tcon_done(struct smb2_request *smb2req) { - struct composite_context *c; - struct smb2_connect_state *state; - struct nbt_name name; - struct composite_context *creq; - - c = composite_create(mem_ctx, ev); - if (c == NULL) return NULL; - - state = talloc(c, struct smb2_connect_state); - if (composite_nomem(state, c)) return c; - c->private_data = state; + struct tevent_req *req = + talloc_get_type_abort(smb2req->async.private_data, + struct tevent_req); + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); + NTSTATUS status; - state->credentials = credentials; - state->options = *options; - state->host = talloc_strdup(c, host); - if (composite_nomem(state->host, c)) return c; - state->ports = talloc_reference(state, ports); - state->share = talloc_strdup(c, share); - if (composite_nomem(state->share, c)) return c; - state->resolve_ctx = talloc_reference(state, resolve_ctx); - state->socket_options = talloc_reference(state, socket_options); - state->gensec_settings = talloc_reference(state, gensec_settings); + status = smb2_tree_connect_recv(smb2req, &state->tcon); + if (tevent_req_nterror(req, status)) { + return; + } - ZERO_STRUCT(name); - name.name = host; + state->tree->tid = state->tcon.out.tid; - creq = resolve_name_send(resolve_ctx, state, &name, c->event_ctx); - composite_continue(c, creq, continue_resolve, c); - return c; + tevent_req_done(req); } -/* - receive a connect reply -*/ -NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, +NTSTATUS smb2_connect_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, struct smb2_tree **tree) { + struct smb2_connect_state *state = + tevent_req_data(req, + struct smb2_connect_state); NTSTATUS status; - struct smb2_connect_state *state = talloc_get_type(c->private_data, - struct smb2_connect_state); - status = composite_wait(c); - if (NT_STATUS_IS_OK(status)) { - *tree = talloc_steal(mem_ctx, state->tree); + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; } - talloc_free(c); - return status; + + *tree = talloc_move(mem_ctx, &state->tree); + + tevent_req_received(req); + return NT_STATUS_OK; } /* sync version of smb2_connect */ -NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, - const char *host, const char **ports, - const char *share, +NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx, + const char *host, + const char **ports, + const char *share, struct resolve_context *resolve_ctx, struct cli_credentials *credentials, struct smb2_tree **tree, struct tevent_context *ev, struct smbcli_options *options, - const char *socket_options, - struct gensec_settings *gensec_settings) + const char *socket_options, + struct gensec_settings *gensec_settings) { - struct composite_context *c = smb2_connect_send(mem_ctx, host, ports, - share, resolve_ctx, - credentials, ev, options, - socket_options, - gensec_settings); - return smb2_connect_recv(c, mem_ctx, tree); + struct tevent_req *subreq; + NTSTATUS status; + bool ok; + TALLOC_CTX *frame = talloc_stackframe(); + + if (frame == NULL) { + return NT_STATUS_NO_MEMORY; + } + + subreq = smb2_connect_send(frame, + ev, + host, + ports, + share, + resolve_ctx, + credentials, + options, + socket_options, + gensec_settings); + if (subreq == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + ok = tevent_req_poll(subreq, ev); + if (!ok) { + status = map_nt_error_from_unix_common(errno); + TALLOC_FREE(frame); + return status; + } + + status = smb2_connect_recv(subreq, mem_ctx, tree); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + TALLOC_FREE(frame); + return NT_STATUS_OK; } diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 12479623e7..d46cdefc69 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -20,10 +20,11 @@ */ #include "includes.h" +#include <tevent.h> +#include "lib/util/tevent_ntstatus.h" #include "libcli/raw/libcliraw.h" #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" -#include "libcli/composite/composite.h" #include "auth/gensec/gensec.h" #include <unistd.h> @@ -136,56 +137,133 @@ NTSTATUS smb2_session_setup(struct smb2_session *session, return smb2_session_setup_recv(req, mem_ctx, io); } - -struct smb2_session_state { +struct smb2_session_setup_spnego_state { struct smb2_session_setup io; struct smb2_request *req; NTSTATUS gensec_status; }; +static void smb2_session_setup_spnego_handler(struct smb2_request *req); + +/* + a composite function that does a full SPNEGO session setup + */ +struct tevent_req *smb2_session_setup_spnego_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smb2_session *session, + struct cli_credentials *credentials) +{ + struct tevent_req *req; + struct smb2_session_setup_spnego_state *state; + const char *chosen_oid; + struct smb2_request *subreq; + NTSTATUS status; + + req = tevent_req_create(mem_ctx, &state, + struct smb2_session_setup_spnego_state); + if (req == NULL) { + return NULL; + } + + ZERO_STRUCT(state->io); + state->io.in.vc_number = 0; + if (session->transport->signing_required) { + state->io.in.security_mode = + SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; + } + state->io.in.capabilities = 0; + state->io.in.channel = 0; + state->io.in.previous_sessionid = 0; + + status = gensec_set_credentials(session->gensec, credentials); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + status = gensec_set_target_hostname(session->gensec, + session->transport->socket->hostname); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + status = gensec_set_target_service(session->gensec, "cifs"); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + if (session->transport->negotiate.secblob.length > 0) { + chosen_oid = GENSEC_OID_SPNEGO; + } else { + chosen_oid = GENSEC_OID_NTLMSSP; + } + + status = gensec_start_mech_by_oid(session->gensec, chosen_oid); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + status = gensec_update(session->gensec, state, + session->transport->negotiate.secblob, + &state->io.in.secblob); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + state->gensec_status = status; + + subreq = smb2_session_setup_send(session, &state->io); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + subreq->async.fn = smb2_session_setup_spnego_handler; + subreq->async.private_data = req; + + return req; +} + /* handle continuations of the spnego session setup */ -static void session_request_handler(struct smb2_request *req) +static void smb2_session_setup_spnego_handler(struct smb2_request *subreq) { - struct composite_context *c = talloc_get_type(req->async.private_data, - struct composite_context); - struct smb2_session_state *state = talloc_get_type(c->private_data, - struct smb2_session_state); - struct smb2_session *session = req->session; + struct tevent_req *req = + talloc_get_type_abort(subreq->async.private_data, + struct tevent_req); + struct smb2_session_setup_spnego_state *state = + tevent_req_data(req, + struct smb2_session_setup_spnego_state); + struct smb2_session *session = subreq->session; NTSTATUS session_key_err; DATA_BLOB session_key; NTSTATUS peer_status; + NTSTATUS status; - c->status = smb2_session_setup_recv(req, c, &state->io); - peer_status = c->status; - + status = smb2_session_setup_recv(subreq, state, &state->io); + peer_status = status; if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || (NT_STATUS_IS_OK(peer_status) && NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED))) { - c->status = gensec_update(session->gensec, c, - state->io.out.secblob, - &state->io.in.secblob); - state->gensec_status = c->status; - + status = gensec_update(session->gensec, state, + state->io.out.secblob, + &state->io.in.secblob); + state->gensec_status = status; session->uid = state->io.out.uid; } - if (!NT_STATUS_IS_OK(c->status) && - !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - composite_error(c, c->status); + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + tevent_req_nterror(req, status); return; } if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - state->req = smb2_session_setup_send(session, &state->io); - if (state->req == NULL) { - composite_error(c, NT_STATUS_NO_MEMORY); + subreq = smb2_session_setup_send(session, &state->io); + if (tevent_req_nomem(subreq, req)) { return; } - state->req->async.fn = session_request_handler; - state->req->async.private_data = c; + subreq->async.fn = smb2_session_setup_spnego_handler; + subreq->async.private_data = req; return; } @@ -198,84 +276,21 @@ static void session_request_handler(struct smb2_request *req) if (session->session_key.length == 0) { DEBUG(0,("Wrong session key length %u for SMB2 signing\n", (unsigned)session->session_key.length)); - composite_error(c, NT_STATUS_ACCESS_DENIED); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return; } session->signing_active = true; } - composite_done(c); -} - -/* - a composite function that does a full SPNEGO session setup - */ -struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *session, - struct cli_credentials *credentials) -{ - struct composite_context *c; - struct smb2_session_state *state; - const char *chosen_oid; - - c = composite_create(session, session->transport->socket->event.ctx); - if (c == NULL) return NULL; - - state = talloc(c, struct smb2_session_state); - if (composite_nomem(state, c)) return c; - c->private_data = state; - - ZERO_STRUCT(state->io); - state->io.in.vc_number = 0; - if (session->transport->signing_required) { - state->io.in.security_mode = - SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; - } - state->io.in.capabilities = 0; - state->io.in.channel = 0; - state->io.in.previous_sessionid = 0; - - c->status = gensec_set_credentials(session->gensec, credentials); - if (!composite_is_ok(c)) return c; - - c->status = gensec_set_target_hostname(session->gensec, - session->transport->socket->hostname); - if (!composite_is_ok(c)) return c; - - c->status = gensec_set_target_service(session->gensec, "cifs"); - if (!composite_is_ok(c)) return c; - - if (session->transport->negotiate.secblob.length > 0) { - chosen_oid = GENSEC_OID_SPNEGO; - } else { - chosen_oid = GENSEC_OID_NTLMSSP; - } - - c->status = gensec_start_mech_by_oid(session->gensec, chosen_oid); - if (!composite_is_ok(c)) return c; - - c->status = gensec_update(session->gensec, c, - session->transport->negotiate.secblob, - &state->io.in.secblob); - if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - composite_error(c, c->status); - return c; - } - state->gensec_status = c->status; - - state->req = smb2_session_setup_send(session, &state->io); - composite_continue_smb2(c, state->req, session_request_handler, c); - return c; + tevent_req_done(req); } /* receive a composite session setup reply */ -NTSTATUS smb2_session_setup_spnego_recv(struct composite_context *c) +NTSTATUS smb2_session_setup_spnego_recv(struct tevent_req *req) { - NTSTATUS status; - status = composite_wait(c); - talloc_free(c); - return status; + return tevent_req_simple_recv_ntstatus(req); } /* @@ -284,6 +299,37 @@ NTSTATUS smb2_session_setup_spnego_recv(struct composite_context *c) NTSTATUS smb2_session_setup_spnego(struct smb2_session *session, struct cli_credentials *credentials) { - struct composite_context *c = smb2_session_setup_spnego_send(session, credentials); - return smb2_session_setup_spnego_recv(c); + struct tevent_req *subreq; + NTSTATUS status; + bool ok; + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = session->transport->socket->event.ctx; + + if (frame == NULL) { + return NT_STATUS_NO_MEMORY; + } + + subreq = smb2_session_setup_spnego_send(frame, ev, + session, credentials); + if (subreq == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + ok = tevent_req_poll(subreq, ev); + if (!ok) { + status = map_nt_error_from_unix_common(errno); + TALLOC_FREE(frame); + return status; + } + + status = smb2_session_setup_spnego_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + TALLOC_FREE(frame); + return NT_STATUS_OK; } diff --git a/source4/libcli/smb2/wscript_build b/source4/libcli/smb2/wscript_build index c39cf5fd39..5b5ac7d4e6 100644 --- a/source4/libcli/smb2/wscript_build +++ b/source4/libcli/smb2/wscript_build @@ -3,6 +3,7 @@ bld.SAMBA_SUBSYSTEM('LIBCLI_SMB2', source='transport.c request.c negprot.c session.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c', autoproto='smb2_proto.h', - public_deps='LIBCLI_RAW LIBPACKET gensec' + deps='UTIL_TEVENT', + public_deps='LIBCLI_RAW LIBPACKET gensec tevent' ) |