From ab913d17681183d57f21faf7871ba30b5ae41239 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 May 2011 18:12:07 +0200 Subject: s3:libsmb: add smb2cli_negprot*() Based on the initial patch from Volker Lendecke . metze --- source3/Makefile.in | 1 + source3/include/client.h | 11 +++ source3/libsmb/smb2cli.h | 29 +++++++ source3/libsmb/smb2cli_negprot.c | 163 +++++++++++++++++++++++++++++++++++++++ source3/wscript_build | 1 + 5 files changed, 205 insertions(+) create mode 100644 source3/libsmb/smb2cli.h create mode 100644 source3/libsmb/smb2cli_negprot.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 2b2f9c4624..d7a15686cd 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 e94c63e51f..86f3d5ec97 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 0000000000..f4fd97c801 --- /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 . +*/ + +#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 0000000000..305632283f --- /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 . +*/ + +#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 7a277aa2c5..ca5aa411fb 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 -- cgit