summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-05-05 18:12:07 +0200
committerStefan Metzmacher <metze@samba.org>2011-07-08 01:22:17 +0200
commitab913d17681183d57f21faf7871ba30b5ae41239 (patch)
treeb67721e3e4b1cf8f95807ccf19c1f92846a7f145
parenta0cf7bae60fed5a30a16a99697f74b431456029e (diff)
downloadsamba-ab913d17681183d57f21faf7871ba30b5ae41239.tar.gz
s3:libsmb: add smb2cli_negprot*()
Based on the initial patch from Volker Lendecke <vl@samba.org>. metze
-rw-r--r--source3/Makefile.in1
-rw-r--r--source3/include/client.h11
-rw-r--r--source3/libsmb/smb2cli.h29
-rw-r--r--source3/libsmb/smb2cli_negprot.c163
-rwxr-xr-xsource3/wscript_build1
5 files changed, 205 insertions, 0 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 2b2f9c46247..d7a15686cdf 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -601,6 +601,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/smb_seal.o libsmb/async_smb.o \
libsmb/read_smb.o \
libsmb/smb2cli_base.o \
+ libsmb/smb2cli_negprot.o \
libsmb/cli_np_tstream.o \
libsmb/smbsock_connect.o \
$(LIBSAMBA_OBJ) \
diff --git a/source3/include/client.h b/source3/include/client.h
index e94c63e51f1..86f3d5ec972 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -145,6 +145,17 @@ struct cli_state {
uint32_t pid;
uint32_t tid;
uint64_t uid;
+
+ /* SMB2 negprot */
+ uint16_t security_mode;
+ uint16_t dialect_revision;
+ struct GUID server_guid;
+ uint16_t server_capabilities;
+ uint32_t max_transact_size;
+ uint32_t max_read_size;
+ uint32_t max_write_size;
+ struct timespec system_time;
+ struct timespec server_start_time;
} smb2;
};
diff --git a/source3/libsmb/smb2cli.h b/source3/libsmb/smb2cli.h
new file mode 100644
index 00000000000..f4fd97c8013
--- /dev/null
+++ b/source3/libsmb/smb2cli.h
@@ -0,0 +1,29 @@
+/*
+ Unix SMB/CIFS implementation.
+ smb2 client routines
+ Copyright (C) Volker Lendecke 2011
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SMB2CLI_H__
+#define __SMB2CLI_H__
+
+struct tevent_req *smb2cli_negprot_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli);
+NTSTATUS smb2cli_negprot_recv(struct tevent_req *req);
+NTSTATUS smb2cli_negprot(struct cli_state *cli);
+
+#endif /* __SMB2CLI_H__ */
diff --git a/source3/libsmb/smb2cli_negprot.c b/source3/libsmb/smb2cli_negprot.c
new file mode 100644
index 00000000000..305632283fd
--- /dev/null
+++ b/source3/libsmb/smb2cli_negprot.c
@@ -0,0 +1,163 @@
+/*
+ Unix SMB/CIFS implementation.
+ smb2 lib
+ Copyright (C) Volker Lendecke 2011
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "client.h"
+#include "async_smb.h"
+#include "smb2cli_base.h"
+#include "smb2cli.h"
+#include "libsmb/proto.h"
+#include "librpc/ndr/libndr.h"
+#include "lib/util/tevent_ntstatus.h"
+
+struct smb2cli_negprot_state {
+ struct cli_state *cli;
+ uint8_t fixed[36];
+ uint8_t dyn[4];
+};
+
+static void smb2cli_negprot_done(struct tevent_req *subreq);
+
+struct tevent_req *smb2cli_negprot_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli)
+{
+ struct tevent_req *req, *subreq;
+ struct smb2cli_negprot_state *state;
+ uint8_t *buf;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct smb2cli_negprot_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+
+ buf = state->fixed;
+ SSVAL(buf, 0, 36);
+ SSVAL(buf, 2, 2); /* DialectCount */
+ if (client_is_signing_mandatory(cli)) {
+ SSVAL(buf, 4, SMB2_NEGOTIATE_SIGNING_REQUIRED);
+ } else {
+ SSVAL(buf, 4, SMB2_NEGOTIATE_SIGNING_ENABLED);
+ }
+ SSVAL(buf, 6, 0); /* Reserved */
+ SSVAL(buf, 8, 0); /* Capabilities */
+ memset(buf+12, 0, 16); /* ClientGuid */
+ SBVAL(buf, 28, 0); /* ClientStartTime */
+
+ buf = state->dyn;
+ SSVAL(buf, 0, 0x202); /* SMB2.002 */
+ SSVAL(buf, 2, 0x210); /* SMB2.1 */
+
+ subreq = smb2cli_req_send(state, ev, cli, SMB2_OP_NEGPROT, 0,
+ state->fixed, sizeof(state->fixed),
+ state->dyn, sizeof(state->dyn));
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, smb2cli_negprot_done, req);
+ return req;
+}
+
+static void smb2cli_negprot_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct smb2cli_negprot_state *state =
+ tevent_req_data(req,
+ struct smb2cli_negprot_state);
+ struct cli_state *cli = state->cli;
+ size_t security_offset, security_length;
+ DATA_BLOB blob;
+ NTSTATUS status;
+ struct iovec *iov;
+ uint8_t *body;
+
+ status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 65);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
+ }
+ body = (uint8_t *)iov[1].iov_base;
+
+ cli->smb2.security_mode = SVAL(body, 2);
+ cli->smb2.dialect_revision = SVAL(body, 4);
+
+ blob = data_blob_const(body + 8, 16);
+ GUID_from_data_blob(&blob, &cli->smb2.server_guid);
+
+ cli->smb2.server_capabilities = IVAL(body, 24);
+ cli->smb2.max_transact_size = IVAL(body, 28);
+ cli->smb2.max_read_size = IVAL(body, 32);
+ cli->smb2.max_write_size = IVAL(body, 36);
+ cli->smb2.system_time = interpret_long_date((char *)body + 40);
+ cli->smb2.server_start_time = interpret_long_date((char *)body + 48);
+
+ security_offset = SVAL(body, 56);
+ security_length = SVAL(body, 58);
+
+ if ((security_offset != SMB2_HDR_BODY + iov[1].iov_len) ||
+ (security_length > iov[2].iov_len)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+ cli->secblob = data_blob(iov[1].iov_base, security_length);
+
+ tevent_req_done(req);
+}
+
+NTSTATUS smb2cli_negprot_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS smb2cli_negprot(struct cli_state *cli)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ if (cli_has_async_calls(cli)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = smb2cli_negprot_send(frame, ev, cli);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = smb2cli_negprot_recv(req);
+ fail:
+ TALLOC_FREE(frame);
+ return status;
+}
+
diff --git a/source3/wscript_build b/source3/wscript_build
index 7a277aa2c50..ca5aa411fb5 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -137,6 +137,7 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c
libsmb/clioplock.c libsmb/clirap2.c
libsmb/smb_seal.c libsmb/async_smb.c libsmb/read_smb.c
libsmb/smb2cli_base.c
+ libsmb/smb2cli_negprot.c
libsmb/cli_np_tstream.c
libsmb/reparse_symlink.c
libsmb/clisymlink.c