From 555b45e12c281eb3980d15b12728c59c6b73c302 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 11 Nov 2005 05:53:54 +0000 Subject: r11665: started to put some meat on the structure used for the SMB2 library the call definitions will be in smb2_calls.h, which will play a similar role that smb_interfaces.h plays for the old SMB protocol (This used to be commit 4ef3902a8a99a0b8caa81a07ba07830d7cbbc32c) --- source4/include/structs.h | 1 + source4/libcli/smb2/config.mk | 3 +- source4/libcli/smb2/negprot.c | 53 ++++++++++++++++++------------ source4/libcli/smb2/request.c | 16 --------- source4/libcli/smb2/session.c | 47 +++++++++++++++++++++++++++ source4/libcli/smb2/smb2.h | 8 ++++- source4/libcli/smb2/smb2_calls.h | 63 ++++++++++++++++++++++++++++++++++++ source4/libcli/smb2/transport.c | 2 ++ source4/torture/smb2/connect.c | 70 +++++++++++++++++++++++++++++++++------- 9 files changed, 213 insertions(+), 50 deletions(-) create mode 100644 source4/libcli/smb2/session.c create mode 100644 source4/libcli/smb2/smb2_calls.h diff --git a/source4/include/structs.h b/source4/include/structs.h index 7a31b943fd..b6bc1cc742 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -336,3 +336,4 @@ struct _krb5_krb_auth_data; struct smb2_request; struct smb2_transport; +struct smb2_negprot; diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index 9840876c2f..4879dfb5df 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -2,5 +2,6 @@ OBJ_FILES = \ transport.o \ request.o \ - negprot.o + negprot.o \ + session.o REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBPACKET diff --git a/source4/libcli/smb2/negprot.c b/source4/libcli/smb2/negprot.c index 6b35373807..ffddf8a2f0 100644 --- a/source4/libcli/smb2/negprot.c +++ b/source4/libcli/smb2/negprot.c @@ -23,19 +23,23 @@ #include "includes.h" #include "libcli/raw/libcliraw.h" #include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" /* send a negprot request */ -struct smb2_request *smb2_negprot_send(struct smb2_transport *transport) +struct smb2_request *smb2_negprot_send(struct smb2_transport *transport, + struct smb2_negprot *io) { struct smb2_request *req; + req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26); if (req == NULL) return NULL; - memset(req->out.body, 0, 0x26); - SIVAL(req->out.body, 0, 0x00010024); /* unknown */ + SIVAL(req->out.body, 0x00, io->in.unknown1); + SSVAL(req->out.body, 0x04, io->in.unknown2); + memcpy(req->out.body+0x06, io->in.unknown3, 32); smb2_transport_send(req); @@ -45,29 +49,35 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport) /* recv a negprot reply */ -NTSTATUS smb2_negprot_recv(struct smb2_request *req) +NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, + struct smb2_negprot *io) { - NTTIME t1, t2; - DATA_BLOB secblob; - struct GUID guid; - NTSTATUS status; + uint16_t blobsize; if (!smb2_request_receive(req) || smb2_request_is_error(req)) { return smb2_request_destroy(req); } - t1 = smbcli_pull_nttime(req->in.body, 0x28); - t2 = smbcli_pull_nttime(req->in.body, 0x30); - - secblob = smb2_pull_blob(req, req->in.body+0x40, req->in.body_size - 0x40); - status = smb2_pull_guid(req, req->in.body+0x08, &guid); - NT_STATUS_NOT_OK_RETURN(status); + if (req->in.body_size < 0x40) { + return NT_STATUS_BUFFER_TOO_SMALL; + } - printf("Negprot reply:\n"); - printf("t1 =%s\n", nt_time_string(req, t1)); - printf("t2 =%s\n", nt_time_string(req, t2)); - printf("guid=%s\n", GUID_string(req, &guid)); + io->out.unknown1 = IVAL(req->in.body, 0x00); + io->out.unknown2 = IVAL(req->in.body, 0x04); + memcpy(io->out.sessid, req->in.body + 0x08, 16); + io->out.unknown3 = IVAL(req->in.body, 0x18); + io->out.unknown4 = SVAL(req->in.body, 0x1C); + io->out.unknown5 = IVAL(req->in.body, 0x1E); + io->out.unknown6 = IVAL(req->in.body, 0x22); + io->out.unknown7 = SVAL(req->in.body, 0x26); + io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28); + io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30); + io->out.unknown8 = SVAL(req->in.body, 0x38); + blobsize = SVAL(req->in.body, 0x3A); + io->out.unknown9 = IVAL(req->in.body, 0x3C); + io->out.secblob = smb2_pull_blob(req, req->in.body+0x40, blobsize); + talloc_steal(mem_ctx, io->out.secblob.data); return smb2_request_destroy(req); } @@ -75,8 +85,9 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req) /* sync negprot request */ -NTSTATUS smb2_negprot(struct smb2_transport *transport) +NTSTATUS smb2_negprot(struct smb2_transport *transport, + TALLOC_CTX *mem_ctx, struct smb2_negprot *io) { - struct smb2_request *req = smb2_negprot_send(transport); - return smb2_negprot_recv(req); + struct smb2_request *req = smb2_negprot_send(transport, io); + return smb2_negprot_recv(req, mem_ctx, io); } diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 1b2dc5e64c..e71fc84471 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -25,7 +25,6 @@ #include "libcli/smb2/smb2.h" #include "include/dlinklist.h" #include "lib/events/events.h" -#include "librpc/gen_ndr/ndr_misc.h" /* initialise a smb2 request @@ -154,18 +153,3 @@ DATA_BLOB smb2_pull_blob(struct smb2_request *req, uint8_t *ptr, uint_t size) return data_blob_talloc(req, ptr, size); } -/* - pull a guid from the reply body -*/ -NTSTATUS smb2_pull_guid(struct smb2_request *req, uint8_t *ptr, struct GUID *guid) -{ - NTSTATUS status; - DATA_BLOB blob = smb2_pull_blob(req, ptr, 16); - if (blob.data == NULL) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - status = ndr_pull_struct_blob(&blob, req, guid, - (ndr_pull_flags_fn_t)ndr_pull_GUID); - data_blob_free(&blob); - return status; -} diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c new file mode 100644 index 0000000000..23fed70e17 --- /dev/null +++ b/source4/libcli/smb2/session.c @@ -0,0 +1,47 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client session 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" + +/* + initialise a smb2_session structure + */ +struct smb2_session *smb2_session_init(struct smb2_transport *transport, + TALLOC_CTX *parent_ctx, BOOL primary) +{ + struct smb2_session *session; + + session = talloc_zero(parent_ctx, struct smb2_session); + if (!session) { + return NULL; + } + if (primary) { + session->transport = talloc_steal(session, transport); + } else { + session->transport = talloc_reference(session, transport); + } + + return session; +} + diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 2e01159355..79b983206a 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -29,7 +29,6 @@ struct smb2_options { */ struct smb2_negotiate { DATA_BLOB secblob; - }; /* this is the context for the smb2 transport layer */ @@ -52,6 +51,13 @@ struct smb2_transport { }; +/* + SMB2 session context +*/ +struct smb2_session { + struct smb2_transport *transport; +}; + 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 new file mode 100644 index 0000000000..ef0abc3e45 --- /dev/null +++ b/source4/libcli/smb2/smb2_calls.h @@ -0,0 +1,63 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client calls + + 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. +*/ + + +struct smb2_negprot { + struct { + uint32_t unknown1; /* 0x00010024 */ + uint16_t unknown2; /* 0x00 */ + uint8_t unknown3[32]; /* all zero */ + } in; + struct { + uint32_t unknown1; /* 0x41 */ + uint32_t unknown2; /* 0x06 */ + uint8_t sessid[16]; + uint32_t unknown3; /* 0x0d */ + uint16_t unknown4; /* 0x00 */ + uint32_t unknown5; /* 0x01 */ + uint32_t unknown6; /* 0x01 */ + uint16_t unknown7; /* 0x01 */ + NTTIME current_time; + NTTIME boot_time; + uint16_t unknown8; /* 0x80 */ + /* uint16_t secblob size here */ + uint32_t unknown9; /* 0x204d4c20 */ + DATA_BLOB secblob; + } out; +}; + +struct smb2_session_setup { + struct { + uint32_t unknown1; /* 0x11 */ + uint32_t unknown2; /* 0xF */ + uint32_t unknown3; /* 0x00 */ + uint16_t unknown4; /* 0x50 */ + /* uint16_t secblob size here */ + DATA_BLOB secblob; + } in; + struct { + uint32_t unknown1; /* 0x09 */ + uint16_t unknown2; /* 0x48 */ + /* uint16_t secblob size here */ + DATA_BLOB secblob; + } out; +}; diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index a178b35f93..dd05eed1dd 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -183,6 +183,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) req->in.ptr = req->in.body; req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); + dump_data(0, req->in.body, req->in.body_size); + /* if this request has an async handler then call that to notify that the reply has been received. This might destroy the request so it must happen last */ diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c index 00a9b35c17..7237bb704a 100644 --- a/source4/torture/smb2/connect.c +++ b/source4/torture/smb2/connect.c @@ -23,6 +23,7 @@ #include "includes.h" #include "libcli/raw/libcliraw.h" #include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" #include "librpc/gen_ndr/ndr_security.h" #include "lib/cmdline/popt_common.h" #include "lib/events/events.h" @@ -37,17 +38,16 @@ goto done; \ }} while (0) -/* - basic testing of SMB2 connection calls -*/ -BOOL torture_smb2_connect(void) + +/* + send a negotiate + */ +static struct smb2_transport *torture_smb2_negprot(TALLOC_CTX *mem_ctx, const char *host) { - TALLOC_CTX *mem_ctx = talloc_new(NULL); struct smbcli_socket *socket; struct smb2_transport *transport; - const char *host = lp_parm_string(-1, "torture", "host"); - BOOL ret = True; NTSTATUS status; + struct smb2_negprot io; socket = smbcli_sock_connect_byname(host, 445, mem_ctx, NULL); if (socket == NULL) { @@ -56,19 +56,67 @@ BOOL torture_smb2_connect(void) } transport = smb2_transport_init(socket, mem_ctx); - if (socket == NULL) { + if (transport == NULL) { printf("Failed to setup smb2 transport\n"); return False; } + ZERO_STRUCT(io); + io.in.unknown1 = 0x010024; + /* send a negprot */ - status = smb2_negprot(transport); + status = smb2_negprot(transport, mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { printf("negprot failed - %s\n", nt_errstr(status)); - return False; + return NULL; } + printf("Negprot reply:\n"); + printf("current_time = %s\n", nt_time_string(mem_ctx, io.out.current_time)); + printf("boot_time = %s\n", nt_time_string(mem_ctx, io.out.boot_time)); + + return transport; +} + +#if 0 +/* + send a session setup +*/ +static struct smb2_session *torture_smb2_session(struct smb2_transport *transport, + struct cli_credentials *credentials) +{ + struct smb2_session *session; + NTSTATUS status; + + session = smb2_session_init(transport); + + status = smb2_session_setup(session, credentials) + if (!NT_STATUS_IS_OK(status)) { + printf("session setup failed - %s\n", nt_errstr(status)); + return NULL; + } + + return session; +} +#endif + +/* + basic testing of SMB2 connection calls +*/ +BOOL torture_smb2_connect(void) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct smb2_transport *transport; + struct smb2_session *session; + const char *host = lp_parm_string(-1, "torture", "host"); + struct cli_credentials *credentials = cmdline_credentials; + + transport = torture_smb2_negprot(mem_ctx, host); +#if 0 + session = torture_smb2_session(transport, credentials); +#endif + talloc_free(mem_ctx); - return ret; + return True; } -- cgit