diff options
Diffstat (limited to 'source4/libcli/smb2')
-rw-r--r-- | source4/libcli/smb2/connect.c | 303 | ||||
-rw-r--r-- | source4/libcli/smb2/wscript_build | 3 |
2 files changed, 198 insertions, 108 deletions
diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 64ed6c3acc..85624019d1 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; @@ -46,19 +49,24 @@ struct smb2_connect_state { /* continue after tcon reply */ -static void continue_tcon(struct smb2_request *req) +static void continue_tcon(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); - - c->status = smb2_tree_connect_recv(req, &state->tcon); - if (!composite_is_ok(c)) return; - + 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; + + status = smb2_tree_connect_recv(smb2req, &state->tcon); + if (tevent_req_nterror(req, status)) { + return; + } + state->tree->tid = state->tcon.out.tid; - composite_done(c); + tevent_req_done(req); } /* @@ -66,44 +74,59 @@ static void continue_tcon(struct smb2_request *req) */ static void continue_session(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); + struct smb2_request *smb2req; + NTSTATUS status; - c->status = smb2_session_setup_spnego_recv(creq); - if (!composite_is_ok(c)) return; + status = smb2_session_setup_spnego_recv(creq); + if (tevent_req_nterror(req, status)) { + return; + } state->tree = smb2_tree_init(state->session, state, true); - if (composite_nomem(state->tree, c)) return; + if (tevent_req_nomem(state->tree, req)) { + return; + } 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; + if (tevent_req_nomem(state->tcon.in.path, req)) { + return; + } - req->async.fn = continue_tcon; - req->async.private_data = c; + smb2req = smb2_tree_connect_send(state->tree, &state->tcon); + if (tevent_req_nomem(smb2req, req)) { + return; + } + smb2req->async.fn = continue_tcon; + smb2req->async.private_data = req; } /* continue after negprot reply */ -static void continue_negprot(struct smb2_request *req) +static void continue_negprot(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 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 composite_context *creq; + 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 +138,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,18 +161,23 @@ 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; + if (tevent_req_nomem(state->session, req)) { + return; + } creq = smb2_session_setup_spnego_send(state->session, state->credentials); - - composite_continue(c, creq, continue_session, c); + if (tevent_req_nomem(creq, req)) { + return; + } + creq->async.fn = continue_session; + creq->async.private_data = req; } /* @@ -157,27 +185,34 @@ static void continue_negprot(struct smb2_request *req) */ 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 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 *req; + struct smb2_request *smb2req; + NTSTATUS status; 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; + status = smbcli_sock_connect_recv(creq, state, &sock); + if (tevent_req_nterror(req, status)) { + return; + } transport = smb2_transport_init(sock, state, &state->options); - if (composite_nomem(transport, c)) return; + if (tevent_req_nomem(transport, req)) { + return; + } ZERO_STRUCT(state->negprot); - state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]); + state->negprot.in.dialect_count = ARRAY_SIZE(dialects); switch (transport->options.signing) { case SMB_SIGNING_OFF: state->negprot.in.security_mode = 0; @@ -195,11 +230,12 @@ static void continue_socket(struct composite_context *creq) 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; + smb2req = smb2_negprot_send(transport, &state->negprot); + if (tevent_req_nomem(smb2req, req)) { + return; + } + smb2req->async.fn = continue_negprot; + smb2req->async.private_data = req; } @@ -208,16 +244,21 @@ static void continue_socket(struct composite_context *creq) */ static void continue_resolve(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 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 = resolve_name_recv(creq, state, &addr); - if (!composite_is_ok(c)) return; + status = resolve_name_recv(creq, state, &addr); + if (tevent_req_nterror(req, status)) { + return; + } if (state->ports == NULL) { ports = default_ports; @@ -225,92 +266,140 @@ static void continue_resolve(struct composite_context *creq) ports = state->ports; } - creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options); - - composite_continue(c, creq, continue_socket, c); + 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 = continue_socket; + creq->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) +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; + struct tevent_req *req; 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; + 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 = 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); + 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; - creq = resolve_name_send(resolve_ctx, state, &name, c->event_ctx); - composite_continue(c, creq, continue_resolve, c); - return 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 = continue_resolve; + creq->async.private_data = req; + return 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(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/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' ) |