summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/structs.h5
-rw-r--r--source4/libcli/smb2/config.mk3
-rw-r--r--source4/libcli/smb2/request.c37
-rw-r--r--source4/libcli/smb2/smb2.h9
-rw-r--r--source4/libcli/smb2/smb2_calls.h14
-rw-r--r--source4/libcli/smb2/tcon.c112
-rw-r--r--source4/torture/smb2/connect.c38
7 files changed, 215 insertions, 3 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h
index eb04436ea3..7c92b66d52 100644
--- a/source4/include/structs.h
+++ b/source4/include/structs.h
@@ -336,5 +336,10 @@ struct _krb5_krb_auth_data;
struct smb2_request;
struct smb2_transport;
+struct smb2_session;
struct smb2_negprot;
struct smb2_session_setup;
+struct smb2_tree;
+struct smb2_tree_connect;
+
+
diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk
index 4879dfb5df..63cb6c6140 100644
--- a/source4/libcli/smb2/config.mk
+++ b/source4/libcli/smb2/config.mk
@@ -3,5 +3,6 @@ OBJ_FILES = \
transport.o \
request.o \
negprot.o \
- session.o
+ session.o \
+ tcon.o
REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBPACKET
diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c
index 28e7018ecc..deadd1794f 100644
--- a/source4/libcli/smb2/request.c
+++ b/source4/libcli/smb2/request.c
@@ -204,3 +204,40 @@ NTSTATUS smb2_push_ofs_blob(struct smb2_request *req, uint8_t *ptr, DATA_BLOB bl
memcpy(ptr+4, blob.data, blob.length);
return NT_STATUS_OK;
}
+
+/*
+ pull a string in a ofs/length/blob format
+*/
+NTSTATUS smb2_pull_ofs_string(struct smb2_request *req, uint8_t *ptr,
+ const char **str)
+{
+ DATA_BLOB blob;
+ NTSTATUS status;
+ ssize_t size;
+ void *vstr;
+ status = smb2_pull_ofs_blob(req, ptr, &blob);
+ NT_STATUS_NOT_OK_RETURN(status);
+ size = convert_string_talloc(req, CH_UTF16, CH_UNIX,
+ blob.data, blob.length, &vstr);
+ data_blob_free(&blob);
+ (*str) = vstr;
+ if (size == -1) {
+ return NT_STATUS_ILLEGAL_CHARACTER;
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ create a UTF16 string in a blob from a char*
+*/
+NTSTATUS smb2_string_blob(TALLOC_CTX *mem_ctx, const char *str, DATA_BLOB *blob)
+{
+ ssize_t size;
+ size = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16,
+ str, strlen(str), (void **)&blob->data);
+ if (size == -1) {
+ return NT_STATUS_ILLEGAL_CHARACTER;
+ }
+ blob->length = size;
+ return NT_STATUS_OK;
+}
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index 8ed51b2351..353f9687d7 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -52,6 +52,14 @@ struct smb2_transport {
/*
+ SMB2 tree context
+*/
+struct smb2_tree {
+ struct smb2_session *session;
+ uint64_t tid;
+};
+
+/*
SMB2 session context
*/
struct smb2_session {
@@ -60,6 +68,7 @@ struct smb2_session {
uint64_t uid;
};
+
struct smb2_request_buffer {
/* the raw SMB2 buffer, including the 4 byte length header */
uint8_t *buffer;
diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h
index 3ee8f90bc9..523f314cbf 100644
--- a/source4/libcli/smb2/smb2_calls.h
+++ b/source4/libcli/smb2/smb2_calls.h
@@ -60,3 +60,17 @@ struct smb2_session_setup {
uint64_t uid; /* returned in header */
} out;
};
+
+struct smb2_tree_connect {
+ struct {
+ uint32_t unknown1; /* 0x09 */
+ const char *path;
+ } in;
+ struct {
+ uint32_t unknown1; /* 0x00020010 */
+ uint32_t unknown2; /* 0x00 */
+ uint32_t unknown3; /* 0x00 */
+ uint32_t unknown4; /* 0x1f01ff */ /* capabilities?? */
+ uint64_t tid;
+ } out;
+};
diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c
new file mode 100644
index 0000000000..7b13750cfe
--- /dev/null
+++ b/source4/libcli/smb2/tcon.c
@@ -0,0 +1,112 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ SMB2 client tree handling
+
+ 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"
+
+/*
+ initialise a smb2_session structure
+ */
+struct smb2_tree *smb2_tree_init(struct smb2_session *session,
+ TALLOC_CTX *parent_ctx, BOOL primary)
+{
+ struct smb2_tree *tree;
+
+ tree = talloc_zero(parent_ctx, struct smb2_tree);
+ if (!session) {
+ return NULL;
+ }
+ if (primary) {
+ tree->session = talloc_steal(tree, session);
+ } else {
+ tree->session = talloc_reference(tree, session);
+ }
+ return tree;
+}
+
+/*
+ send a tree connect
+*/
+struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree,
+ struct smb2_tree_connect *io)
+{
+ struct smb2_request *req;
+ NTSTATUS status;
+ DATA_BLOB path;
+
+ status = smb2_string_blob(tree, io->in.path, &path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ req = smb2_request_init(tree->session->transport, SMB2_OP_TCON,
+ 0x8 + path.length);
+ if (req == NULL) return NULL;
+
+ SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
+ SIVAL(req->out.body, 0x00, io->in.unknown1);
+ status = smb2_push_ofs_blob(req, req->out.body+0x04, path);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(req);
+ return NULL;
+ }
+
+ smb2_transport_send(req);
+
+ return req;
+}
+
+
+/*
+ recv a tree connect reply
+*/
+NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_connect *io)
+{
+ if (!smb2_request_receive(req) ||
+ smb2_request_is_error(req)) {
+ return smb2_request_destroy(req);
+ }
+
+ if (req->in.body_size < 0x10) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ io->out.tid = BVAL(req->in.hdr, SMB2_HDR_TID);
+
+ io->out.unknown1 = IVAL(req->in.body, 0x00);
+ io->out.unknown2 = IVAL(req->in.body, 0x04);
+ io->out.unknown3 = IVAL(req->in.body, 0x08);
+ io->out.unknown4 = IVAL(req->in.body, 0x0C);
+
+ return smb2_request_destroy(req);
+}
+
+/*
+ sync session setup request
+*/
+NTSTATUS smb2_tree_connect(struct smb2_tree *tree, struct smb2_tree_connect *io)
+{
+ struct smb2_request *req = smb2_tree_connect_send(tree, io);
+ return smb2_tree_connect_recv(req, io);
+}
diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c
index 49b9582d4d..8b5a26bce3 100644
--- a/source4/torture/smb2/connect.c
+++ b/source4/torture/smb2/connect.c
@@ -164,6 +164,35 @@ static struct smb2_session *torture_smb2_session(struct smb2_transport *transpor
return session;
}
+
+/*
+ send a tree connect
+*/
+static struct smb2_tree *torture_smb2_tree(struct smb2_session *session,
+ const char *share)
+{
+ struct smb2_tree *tree;
+ struct smb2_tree_connect io;
+ NTSTATUS status;
+
+ tree = smb2_tree_init(session, session, True);
+
+ io.in.unknown1 = 0x09;
+ io.in.path = talloc_asprintf(tree, "\\\\%s\\%s",
+ session->transport->socket->hostname,
+ share);
+
+ status = smb2_tree_connect(tree, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("tcon failed - %s\n", nt_errstr(status));
+ return NULL;
+ }
+
+ printf("Tree connect gave tid = 0x%llx\n", io.out.tid);
+
+ return tree;
+}
+
/*
basic testing of SMB2 connection calls
*/
@@ -171,12 +200,17 @@ BOOL torture_smb2_connect(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct smb2_transport *transport;
- struct smb2_session *session;
+ struct smb2_session *session;
+ struct smb2_tree *tree;
const char *host = lp_parm_string(-1, "torture", "host");
+ const char *share = lp_parm_string(-1, "torture", "share");
struct cli_credentials *credentials = cmdline_credentials;
transport = torture_smb2_negprot(mem_ctx, host);
- session = torture_smb2_session(transport, credentials);
+ session = torture_smb2_session(transport, credentials);
+ session = torture_smb2_session(transport, credentials);
+ tree = torture_smb2_tree(session, share);
+ tree = torture_smb2_tree(session, share);
talloc_free(mem_ctx);