1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

s3:libsmb/cli_np_tstream: add support for SMB2

metze
This commit is contained in:
Stefan Metzmacher 2012-04-25 20:18:22 +02:00
parent b88d649e40
commit b3a3c50eb8

View File

@ -20,6 +20,7 @@
#include "includes.h"
#include "system/network.h"
#include "libsmb/libsmb.h"
#include "libsmb/smb2cli.h"
#include "../lib/util/tevent_ntstatus.h"
#include "../lib/tsocket/tsocket.h"
#include "../lib/tsocket/tsocket_internal.h"
@ -50,7 +51,10 @@ static const struct tstream_context_ops tstream_cli_np_ops;
struct tstream_cli_np {
struct cli_state *cli;
const char *npipe;
bool is_smb1;
uint16_t fnum;
uint64_t fid_persistent;
uint64_t fid_volatile;
unsigned int default_timeout;
struct {
@ -88,7 +92,13 @@ static int tstream_cli_np_destructor(struct tstream_cli_np *cli_nps)
* tstream_disconnect_send()/_recv(), this will
* never be called.
*/
status = cli_close(cli_nps->cli, cli_nps->fnum);
if (cli_nps->is_smb1) {
status = cli_close(cli_nps->cli, cli_nps->fnum);
} else {
status = smb2cli_close(cli_nps->cli, 0,
cli_nps->fid_persistent,
cli_nps->fid_volatile);
}
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("tstream_cli_np_destructor: cli_close "
"failed on pipe %s. Error was %s\n",
@ -102,7 +112,10 @@ static int tstream_cli_np_destructor(struct tstream_cli_np *cli_nps)
struct tstream_cli_np_open_state {
struct cli_state *cli;
bool is_smb1;
uint16_t fnum;
uint64_t fid_persistent;
uint64_t fid_volatile;
const char *npipe;
};
@ -129,15 +142,32 @@ struct tevent_req *tstream_cli_np_open_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
subreq = cli_ntcreate_send(state, ev, cli,
npipe,
0,
DESIRED_ACCESS_PIPE,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
0);
if (cli_state_protocol(cli) < PROTOCOL_SMB2_02) {
state->is_smb1 = true;
}
if (state->is_smb1) {
subreq = cli_ntcreate_send(state, ev, cli,
npipe,
0,
DESIRED_ACCESS_PIPE,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0,
0);
} else {
subreq = smb2cli_create_send(state, ev, cli,
npipe,
SMB2_OPLOCK_LEVEL_NONE,
SMB2_IMPERSONATION_IMPERSONATION,
DESIRED_ACCESS_PIPE,
0, /* file_attributes */
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
0, /* create_options */
NULL); /* blobs */
}
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@ -154,7 +184,13 @@ static void tstream_cli_np_open_done(struct tevent_req *subreq)
tevent_req_data(req, struct tstream_cli_np_open_state);
NTSTATUS status;
status = cli_ntcreate_recv(subreq, &state->fnum);
if (state->is_smb1) {
status = cli_ntcreate_recv(subreq, &state->fnum);
} else {
status = smb2cli_create_recv(subreq,
&state->fid_persistent,
&state->fid_volatile);
}
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
@ -193,7 +229,10 @@ NTSTATUS _tstream_cli_np_open_recv(struct tevent_req *req,
cli_nps->cli = state->cli;
cli_nps->npipe = talloc_move(cli_nps, &state->npipe);
cli_nps->is_smb1 = state->is_smb1;
cli_nps->fnum = state->fnum;
cli_nps->fid_persistent = state->fid_persistent;
cli_nps->fid_volatile = state->fid_volatile;
cli_nps->default_timeout = cli_set_timeout(state->cli, 0);
cli_set_timeout(state->cli, cli_nps->default_timeout);
@ -421,11 +460,23 @@ static void tstream_cli_np_writev_write_next(struct tevent_req *req)
return;
}
subreq = cli_write_andx_send(state, state->ev, cli_nps->cli,
cli_nps->fnum,
8, /* 8 means message mode. */
cli_nps->write.buf, 0,
cli_nps->write.ofs);
if (cli_nps->is_smb1) {
subreq = cli_write_andx_send(state, state->ev, cli_nps->cli,
cli_nps->fnum,
8, /* 8 means message mode. */
cli_nps->write.buf,
0, /* offset */
cli_nps->write.ofs); /* size */
} else {
subreq = smb2cli_write_send(state, state->ev, cli_nps->cli,
cli_nps->write.ofs, /* length */
0, /* offset */
cli_nps->fid_persistent,
cli_nps->fid_volatile,
0, /* remaining_bytes */
0, /* flags */
cli_nps->write.buf);
}
if (tevent_req_nomem(subreq, req)) {
return;
}
@ -450,7 +501,12 @@ static void tstream_cli_np_writev_write_done(struct tevent_req *subreq)
size_t written;
NTSTATUS status;
status = cli_write_andx_recv(subreq, &written);
if (cli_nps->is_smb1) {
status = cli_write_andx_recv(subreq, &written);
} else {
status = smb2cli_write_recv(subreq);
written = cli_nps->write.ofs; // TODO: get the value from the server
}
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
tstream_cli_np_writev_disconnect_now(req, EIO, __location__);
@ -488,7 +544,15 @@ static void tstream_cli_np_writev_disconnect_now(struct tevent_req *req,
return;
}
subreq = cli_close_send(state, state->ev, cli_nps->cli, cli_nps->fnum);
if (cli_nps->is_smb1) {
subreq = cli_close_send(state, state->ev, cli_nps->cli,
cli_nps->fnum);
} else {
subreq = smb2cli_close_send(state, state->ev, cli_nps->cli,
0, /* flags */
cli_nps->fid_persistent,
cli_nps->fid_volatile);
}
if (subreq == NULL) {
/* return the original error */
_tevent_req_error(req, state->error.val, state->error.location);
@ -508,7 +572,11 @@ static void tstream_cli_np_writev_disconnect_done(struct tevent_req *subreq)
struct tstream_cli_np *cli_nps =
tstream_context_data(state->stream, struct tstream_cli_np);
cli_close_recv(subreq);
if (cli_nps->is_smb1) {
cli_close_recv(subreq);
} else {
smb2cli_close_recv(subreq);
}
TALLOC_FREE(subreq);
cli_nps->cli = NULL;
@ -668,8 +736,20 @@ static void tstream_cli_np_readv_read_next(struct tevent_req *req)
return;
}
subreq = cli_read_andx_send(state, state->ev, cli_nps->cli,
cli_nps->fnum, 0, TSTREAM_CLI_NP_MAX_BUF_SIZE);
if (cli_nps->is_smb1) {
subreq = cli_read_andx_send(state, state->ev, cli_nps->cli,
cli_nps->fnum,
0, /* offset */
TSTREAM_CLI_NP_MAX_BUF_SIZE);
} else {
subreq = smb2cli_read_send(state, state->ev, cli_nps->cli,
TSTREAM_CLI_NP_MAX_BUF_SIZE, /* length */
0, /* offset */
cli_nps->fid_persistent,
cli_nps->fid_volatile,
0, /* minimum_count */
0); /* remaining_bytes */
}
if (tevent_req_nomem(subreq, req)) {
return;
}
@ -695,17 +775,37 @@ static void tstream_cli_np_readv_trans_start(struct tevent_req *req)
return;
}
subreq = cli_trans_send(state, state->ev,
cli_nps->cli,
SMBtrans,
"\\PIPE\\",
0, 0, 0,
cli_nps->trans.setup, 2,
0,
NULL, 0, 0,
cli_nps->write.buf,
cli_nps->write.ofs,
TSTREAM_CLI_NP_MAX_BUF_SIZE);
if (cli_nps->is_smb1) {
subreq = cli_trans_send(state, state->ev,
cli_nps->cli,
SMBtrans,
"\\PIPE\\",
0, 0, 0,
cli_nps->trans.setup, 2,
0,
NULL, 0, 0,
cli_nps->write.buf,
cli_nps->write.ofs,
TSTREAM_CLI_NP_MAX_BUF_SIZE);
} else {
DATA_BLOB in_input_buffer = data_blob_null;
DATA_BLOB in_output_buffer = data_blob_null;
in_input_buffer = data_blob_const(cli_nps->write.buf,
cli_nps->write.ofs);
subreq = smb2cli_ioctl_send(state, state->ev,
cli_nps->cli,
cli_nps->fid_persistent,
cli_nps->fid_volatile,
FSCTL_NAMED_PIPE_READ_WRITE,
0, /* in_max_input_length */
&in_input_buffer,
/* in_max_output_length */
TSTREAM_CLI_NP_MAX_BUF_SIZE,
&in_output_buffer,
SMB2_IOCTL_FLAG_IS_FSCTL);
}
if (tevent_req_nomem(subreq, req)) {
return;
}
@ -733,9 +833,22 @@ static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq)
uint32_t received;
NTSTATUS status;
status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
NULL, 0, NULL,
&rcvbuf, 0, &received);
if (cli_nps->is_smb1) {
status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
NULL, 0, NULL,
&rcvbuf, 0, &received);
} else {
DATA_BLOB out_input_buffer = data_blob_null;
DATA_BLOB out_output_buffer = data_blob_null;
status = smb2cli_ioctl_recv(subreq, state,
&out_input_buffer,
&out_output_buffer);
/* Note that rcvbuf is not a talloc pointer here */
rcvbuf = out_output_buffer.data;
received = out_output_buffer.length;
}
TALLOC_FREE(subreq);
if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
status = NT_STATUS_OK;
@ -757,7 +870,13 @@ static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq)
cli_nps->read.ofs = 0;
cli_nps->read.left = received;
cli_nps->read.buf = talloc_move(cli_nps, &rcvbuf);
cli_nps->read.buf = talloc_array(cli_nps, uint8_t, received);
if (cli_nps->read.buf == NULL) {
TALLOC_FREE(subreq);
tevent_req_nomem(cli_nps->read.buf, req);
return;
}
memcpy(cli_nps->read.buf, rcvbuf, received);
if (cli_nps->trans.write_req == NULL) {
tstream_cli_np_readv_read_next(req);
@ -798,7 +917,13 @@ static void tstream_cli_np_readv_read_done(struct tevent_req *subreq)
* a timer event attached to it.
*/
status = cli_read_andx_recv(subreq, &received, &rcvbuf);
if (cli_nps->is_smb1) {
status = cli_read_andx_recv(subreq, &received, &rcvbuf);
} else {
uint32_t data_length = 0;
status = smb2cli_read_recv(subreq, state, &rcvbuf, &data_length);
received = data_length;
}
/*
* We can't TALLOC_FREE(subreq) as usual here, as rcvbuf still is a
* child of that.
@ -870,7 +995,15 @@ static void tstream_cli_np_readv_disconnect_now(struct tevent_req *req,
return;
}
subreq = cli_close_send(state, state->ev, cli_nps->cli, cli_nps->fnum);
if (cli_nps->is_smb1) {
subreq = cli_close_send(state, state->ev, cli_nps->cli,
cli_nps->fnum);
} else {
subreq = smb2cli_close_send(state, state->ev, cli_nps->cli,
0, /* flags */
cli_nps->fid_persistent,
cli_nps->fid_volatile);
}
if (subreq == NULL) {
/* return the original error */
tstream_cli_np_readv_error(req);
@ -890,7 +1023,11 @@ static void tstream_cli_np_readv_disconnect_done(struct tevent_req *subreq)
struct tstream_cli_np *cli_nps =
tstream_context_data(state->stream, struct tstream_cli_np);
cli_close_recv(subreq);
if (cli_nps->is_smb1) {
cli_close_recv(subreq);
} else {
smb2cli_close_recv(subreq);
}
TALLOC_FREE(subreq);
cli_nps->cli = NULL;
@ -991,7 +1128,15 @@ static struct tevent_req *tstream_cli_np_disconnect_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
subreq = cli_close_send(state, ev, cli_nps->cli, cli_nps->fnum);
if (cli_nps->is_smb1) {
subreq = cli_close_send(state, ev, cli_nps->cli,
cli_nps->fnum);
} else {
subreq = smb2cli_close_send(state, ev, cli_nps->cli,
0, /* flags */
cli_nps->fid_persistent,
cli_nps->fid_volatile);
}
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@ -1010,7 +1155,11 @@ static void tstream_cli_np_disconnect_done(struct tevent_req *subreq)
tstream_context_data(state->stream, struct tstream_cli_np);
NTSTATUS status;
status = cli_close_recv(subreq);
if (cli_nps->is_smb1) {
status = cli_close_recv(subreq);
} else {
status = smb2cli_close_recv(subreq);
}
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_error(req, EIO);