From 6615907b94eb2395ddf907e92a543ff0525b9d02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Dec 2005 00:18:29 +0000 Subject: r11980: ronnie worked out that opcode 0xb in SMB2 is in fact ioctl, and that it only appeared to be like a SMBtrans request as it was being called with function 0x11c017 which is "named pipe read write" I wonder if this means we could do DCE/RPC over SMB using ntioctl calls as well? (This used to be commit f2b8857797328be64b0b85e875ae6d108e2aeaaa) --- source4/include/ioctl.h | 3 ++ source4/include/structs.h | 2 +- source4/libcli/smb2/config.mk | 2 +- source4/libcli/smb2/ioctl.c | 111 +++++++++++++++++++++++++++++++++++++++ source4/libcli/smb2/smb2.h | 3 +- source4/libcli/smb2/smb2_calls.h | 8 ++- source4/libcli/smb2/trans.c | 111 --------------------------------------- source4/librpc/rpc/dcerpc_smb2.c | 13 ++--- 8 files changed, 128 insertions(+), 125 deletions(-) create mode 100644 source4/libcli/smb2/ioctl.c delete mode 100644 source4/libcli/smb2/trans.c (limited to 'source4') diff --git a/source4/include/ioctl.h b/source4/include/ioctl.h index 1c08a58d76..cd658c121b 100644 --- a/source4/include/ioctl.h +++ b/source4/include/ioctl.h @@ -28,3 +28,6 @@ #define FSCTL_FILESYSTEM 0x90000 #define FSCTL_SET_SPARSE (FSCTL_FILESYSTEM | (49<<2)) #define FSCTL_REQUEST_BATCH_OPLOCK (FSCTL_FILESYSTEM | (2<<2)) + +#define FSCTL_NAMED_PIPE 0x110000 +#define FSCTL_NAMED_PIPE_READ_WRITE (FSCTL_NAMED_PIPE | 0xc017) diff --git a/source4/include/structs.h b/source4/include/structs.h index f593be6b84..34127c58ca 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -356,6 +356,6 @@ struct smb2_setinfo; struct smb2_read; struct smb2_write; struct smb2_find; -struct smb2_trans; +struct smb2_ioctl; struct smb2_flush; struct smb2_handle; diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index fdb28cfa78..a5b7ce2f38 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -13,7 +13,7 @@ OBJ_FILES = \ read.o \ setinfo.o \ find.o \ - trans.o \ + ioctl.o \ logoff.o \ tdis.o \ flush.o \ diff --git a/source4/libcli/smb2/ioctl.c b/source4/libcli/smb2/ioctl.c new file mode 100644 index 0000000000..26f2bffbc1 --- /dev/null +++ b/source4/libcli/smb2/ioctl.c @@ -0,0 +1,111 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client ioctl call + + Copyright (C) Andrew Tridgell 2005 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" + +/* + send a ioctl request +*/ +struct smb2_request *smb2_ioctl_send(struct smb2_tree *tree, struct smb2_ioctl *io) +{ + NTSTATUS status; + struct smb2_request *req; + + req = smb2_request_init_tree(tree, SMB2_OP_IOCTL, 0x38, + io->in.in.length+io->in.out.length); + if (req == NULL) return NULL; + + SSVAL(req->out.body, 0x02, io->in._pad); + SIVAL(req->out.body, 0x04, io->in.function); + smb2_push_handle(req->out.body+0x08, &io->in.handle); + + status = smb2_push_o32s32_blob(&req->out, 0x18, io->in.out); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + + SIVAL(req->out.body, 0x20, io->in.unknown2); + + status = smb2_push_o32s32_blob(&req->out, 0x24, io->in.in); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + + SIVAL(req->out.body, 0x2C, io->in.max_response_size); + SBVAL(req->out.body, 0x30, io->in.flags); + + smb2_transport_send(req); + + return req; +} + + +/* + recv a ioctl reply +*/ +NTSTATUS smb2_ioctl_recv(struct smb2_request *req, + TALLOC_CTX *mem_ctx, struct smb2_ioctl *io) +{ + NTSTATUS status; + + if (!smb2_request_receive(req) || + smb2_request_is_error(req)) { + return smb2_request_destroy(req); + } + + SMB2_CHECK_PACKET_RECV(req, 0x30, True); + + io->out._pad = SVAL(req->in.body, 0x02); + io->out.function = IVAL(req->in.body, 0x04); + smb2_pull_handle(req->in.body+0x08, &io->out.handle); + + status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x18, &io->out.in); + if (!NT_STATUS_IS_OK(status)) { + smb2_request_destroy(req); + return status; + } + + status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x20, &io->out.out); + if (!NT_STATUS_IS_OK(status)) { + smb2_request_destroy(req); + return status; + } + + io->out.unknown2 = IVAL(req->in.body, 0x28); + io->out.unknown3 = IVAL(req->in.body, 0x2C); + + return smb2_request_destroy(req); +} + +/* + sync ioctl request +*/ +NTSTATUS smb2_ioctl(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, struct smb2_ioctl *io) +{ + struct smb2_request *req = smb2_ioctl_send(tree, io); + return smb2_ioctl_recv(req, mem_ctx, io); +} diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index d12725f70f..ceafacf9d4 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -167,7 +167,8 @@ struct smb2_request { #define SMB2_OP_FLUSH 0x07 #define SMB2_OP_READ 0x08 #define SMB2_OP_WRITE 0x09 -#define SMB2_OP_TRANS 0x0b +#define SMB2_OP_LOCK 0x0a +#define SMB2_OP_IOCTL 0x0b #define SMB2_OP_CANCEL 0x0c #define SMB2_OP_KEEPALIVE 0x0d #define SMB2_OP_FIND 0x0e diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 03f65d947e..08e765ad60 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -316,14 +316,12 @@ struct smb2_find { } out; }; -#define SMB2_TRANS_PIPE_FLAGS 0x0011c017 /* what are these? */ - -struct smb2_trans { +struct smb2_ioctl { struct { /* static body buffer 56 (0x38) bytes */ /* uint16_t buffer_code; 0x39 = 0x38 + 1 */ uint16_t _pad; - uint32_t pipe_flags; + uint32_t function; struct smb2_handle handle; /* uint32_t out_ofs; */ /* uint32_t out_size; */ @@ -342,7 +340,7 @@ struct smb2_trans { /* static body buffer 48 (0x30) bytes */ /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ uint16_t _pad; - uint32_t pipe_flags; + uint32_t function; struct smb2_handle handle; /* uint32_t in_ofs; */ /* uint32_t in_size; */ diff --git a/source4/libcli/smb2/trans.c b/source4/libcli/smb2/trans.c deleted file mode 100644 index de4ff1d827..0000000000 --- a/source4/libcli/smb2/trans.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - SMB2 client trans call - - Copyright (C) Andrew Tridgell 2005 - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "libcli/raw/libcliraw.h" -#include "libcli/smb2/smb2.h" -#include "libcli/smb2/smb2_calls.h" - -/* - send a trans request -*/ -struct smb2_request *smb2_trans_send(struct smb2_tree *tree, struct smb2_trans *io) -{ - NTSTATUS status; - struct smb2_request *req; - - req = smb2_request_init_tree(tree, SMB2_OP_TRANS, 0x38, - io->in.in.length+io->in.out.length); - if (req == NULL) return NULL; - - SSVAL(req->out.body, 0x02, io->in._pad); - SIVAL(req->out.body, 0x04, io->in.pipe_flags); - smb2_push_handle(req->out.body+0x08, &io->in.handle); - - status = smb2_push_o32s32_blob(&req->out, 0x18, io->in.out); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(req); - return NULL; - } - - SIVAL(req->out.body, 0x20, io->in.unknown2); - - status = smb2_push_o32s32_blob(&req->out, 0x24, io->in.in); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(req); - return NULL; - } - - SIVAL(req->out.body, 0x2C, io->in.max_response_size); - SBVAL(req->out.body, 0x30, io->in.flags); - - smb2_transport_send(req); - - return req; -} - - -/* - recv a trans reply -*/ -NTSTATUS smb2_trans_recv(struct smb2_request *req, - TALLOC_CTX *mem_ctx, struct smb2_trans *io) -{ - NTSTATUS status; - - if (!smb2_request_receive(req) || - smb2_request_is_error(req)) { - return smb2_request_destroy(req); - } - - SMB2_CHECK_PACKET_RECV(req, 0x30, True); - - io->out._pad = SVAL(req->in.body, 0x02); - io->out.pipe_flags = IVAL(req->in.body, 0x04); - smb2_pull_handle(req->in.body+0x08, &io->out.handle); - - status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x18, &io->out.in); - if (!NT_STATUS_IS_OK(status)) { - smb2_request_destroy(req); - return status; - } - - status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x20, &io->out.out); - if (!NT_STATUS_IS_OK(status)) { - smb2_request_destroy(req); - return status; - } - - io->out.unknown2 = IVAL(req->in.body, 0x28); - io->out.unknown3 = IVAL(req->in.body, 0x2C); - - return smb2_request_destroy(req); -} - -/* - sync trans request -*/ -NTSTATUS smb2_trans(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, struct smb2_trans *io) -{ - struct smb2_request *req = smb2_trans_send(tree, io); - return smb2_trans_recv(req, mem_ctx, io); -} diff --git a/source4/librpc/rpc/dcerpc_smb2.c b/source4/librpc/rpc/dcerpc_smb2.c index d733ab4713..46e11d4edd 100644 --- a/source4/librpc/rpc/dcerpc_smb2.c +++ b/source4/librpc/rpc/dcerpc_smb2.c @@ -26,6 +26,7 @@ #include "libcli/composite/composite.h" #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" +#include "ioctl.h" /* transport private information used by SMB2 pipe transport */ struct smb2_private { @@ -191,9 +192,9 @@ static void smb2_trans_callback(struct smb2_request *req) struct smb2_trans_state); struct dcerpc_connection *c = state->c; NTSTATUS status; - struct smb2_trans io; + struct smb2_ioctl io; - status = smb2_trans_recv(req, state, &io); + status = smb2_ioctl_recv(req, state, &io); if (NT_STATUS_IS_ERR(status)) { pipe_dead(c, status); return; @@ -213,13 +214,13 @@ static void smb2_trans_callback(struct smb2_request *req) } /* - send a SMBtrans style request + send a SMBtrans style request, using a named pipe read_write fsctl */ static NTSTATUS smb2_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *blob) { struct smb2_private *smb = talloc_get_type(c->transport.private, struct smb2_private); - struct smb2_trans io; + struct smb2_ioctl io; struct smb2_trans_state *state; struct smb2_request *req; @@ -231,13 +232,13 @@ static NTSTATUS smb2_send_trans_request(struct dcerpc_connection *c, DATA_BLOB * state->c = c; ZERO_STRUCT(io); - io.in.pipe_flags = SMB2_TRANS_PIPE_FLAGS; + io.in.function = FSCTL_NAMED_PIPE_READ_WRITE; io.in.handle = smb->handle; io.in.max_response_size = 0x1000; io.in.flags = 1; io.in.out = *blob; - req = smb2_trans_send(smb->tree, &io); + req = smb2_ioctl_send(smb->tree, &io); if (req == NULL) { talloc_free(state); return NT_STATUS_NO_MEMORY; -- cgit