From b186fdd185d2d5c7d9abd7f652aed58fec6de2ff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 28 Sep 2012 19:53:16 +0200 Subject: libcli/smb: add smb1cli_echo* metze --- libcli/smb/smb1cli_echo.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++ libcli/smb/smbXcli_base.h | 10 +++ libcli/smb/wscript | 1 + 3 files changed, 181 insertions(+) create mode 100644 libcli/smb/smb1cli_echo.c (limited to 'libcli') diff --git a/libcli/smb/smb1cli_echo.c b/libcli/smb/smb1cli_echo.c new file mode 100644 index 0000000000..cab8ae628c --- /dev/null +++ b/libcli/smb/smb1cli_echo.c @@ -0,0 +1,170 @@ +/* + Unix SMB/CIFS implementation. + smb2 lib + Copyright (C) Stefan Metzmacher 2012 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/network.h" +#include "lib/util/tevent_ntstatus.h" +#include "smb_common.h" +#include "smbXcli_base.h" + +struct smb1cli_echo_state { + uint16_t vwv[1]; + DATA_BLOB data; + uint16_t num_echos; +}; + +static void smb1cli_echo_done(struct tevent_req *subreq); + +struct tevent_req *smb1cli_echo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbXcli_conn *conn, + uint32_t timeout_msec, + uint16_t num_echos, + DATA_BLOB data) +{ + struct tevent_req *req, *subreq; + struct smb1cli_echo_state *state; + + req = tevent_req_create(mem_ctx, &state, struct smb1cli_echo_state); + if (req == NULL) { + return NULL; + } + SSVAL(state->vwv, 0, num_echos); + state->data = data; + state->num_echos = num_echos; + + subreq = smb1cli_req_send(state, ev, conn, SMBecho, + 0, 0, /* *_flags */ + 0, 0, /* *_flags2 */ + timeout_msec, + 0, /* pid */ + NULL, /* tcon */ + NULL, /* session */ + ARRAY_SIZE(state->vwv), state->vwv, + data.length, data.data); + if (subreq == NULL) { + goto fail; + } + tevent_req_set_callback(subreq, smb1cli_echo_done, req); + return req; + fail: + TALLOC_FREE(req); + return NULL; +} + +static void smb1cli_echo_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct smb1cli_echo_state *state = tevent_req_data( + req, struct smb1cli_echo_state); + NTSTATUS status; + uint32_t num_bytes; + uint8_t *bytes; + struct iovec *recv_iov; + struct smb1cli_req_expected_response expected[] = { + { + .status = NT_STATUS_OK, + .wct = 1, + }, + }; + + status = smb1cli_req_recv(subreq, state, + &recv_iov, + NULL, /* phdr */ + NULL, /* pwct */ + NULL, /* pvwv */ + NULL, /* pvwv_offset */ + &num_bytes, + &bytes, + NULL, /* pbytes_offset */ + NULL, /* pinbuf */ + expected, ARRAY_SIZE(expected)); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + + if (num_bytes != state->data.length) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + if (memcmp(bytes, state->data.data, num_bytes) != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } + + /* TODO: do we want to verify the sequence number? */ + + state->num_echos -=1; + if (state->num_echos == 0) { + tevent_req_done(req); + return; + } + + if (!smbXcli_req_set_pending(subreq)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } +} + +/** + * Get the result out from an echo request + * @param[in] req The async_req from smb1cli_echo_send + * @retval Did the server reply correctly? + */ + +NTSTATUS smb1cli_echo_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS smb1cli_echo(struct smbXcli_conn *conn, uint32_t timeout_msec, + uint16_t num_echos, DATA_BLOB data) +{ + 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(conn)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + ev = tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = smb1cli_echo_send(frame, ev, conn, timeout_msec, num_echos, data); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = smb1cli_echo_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h index 954ff45ad9..03cb2809e7 100644 --- a/libcli/smb/smbXcli_base.h +++ b/libcli/smb/smbXcli_base.h @@ -187,6 +187,16 @@ NTSTATUS smb1cli_trans(TALLOC_CTX *mem_ctx, struct smbXcli_conn *conn, uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam, uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata); +struct tevent_req *smb1cli_echo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbXcli_conn *conn, + uint32_t timeout_msec, + uint16_t num_echos, + DATA_BLOB data); +NTSTATUS smb1cli_echo_recv(struct tevent_req *req); +NTSTATUS smb1cli_echo(struct smbXcli_conn *conn, uint32_t timeout_msec, + uint16_t num_echos, DATA_BLOB data); + uint32_t smb2cli_conn_server_capabilities(struct smbXcli_conn *conn); uint16_t smb2cli_conn_server_security_mode(struct smbXcli_conn *conn); uint32_t smb2cli_conn_max_trans_size(struct smbXcli_conn *conn); diff --git a/libcli/smb/wscript b/libcli/smb/wscript index 0a498d8551..3616ad140f 100755 --- a/libcli/smb/wscript +++ b/libcli/smb/wscript @@ -21,6 +21,7 @@ def build(bld): util.c smbXcli_base.c smb1cli_trans.c + smb1cli_echo.c smb2cli_session.c smb2cli_create.c smb2cli_close.c -- cgit