mirror of
https://github.com/samba-team/samba.git
synced 2025-01-10 01:18:15 +03:00
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-defs
Conflicts:
source/samba4-skip
(This used to be commit 7b0e0eb346
)
This commit is contained in:
commit
5107f093c2
@ -208,9 +208,9 @@ sub Binary($$)
|
||||
$self->_prepare_list($ctx, "LINK_FLAGS");
|
||||
|
||||
if (defined($ctx->{USE_HOSTCC}) && $ctx->{USE_HOSTCC} eq "YES") {
|
||||
$self->output("\$(call host_binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST), \$($ctx->{NAME}_LINK_FLAGS))\n");
|
||||
$self->output("\$(call host_binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_FULL_OBJ_LIST) \$($ctx->{NAME}_DEPEND_LIST), \$($ctx->{NAME}_LINK_FLAGS))\n");
|
||||
} else {
|
||||
$self->output("\$(call binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST), \$($ctx->{NAME}_LINK_FLAGS))\n");
|
||||
$self->output("\$(call binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_FULL_OBJ_LIST) \$($ctx->{NAME}_DEPEND_LIST), \$($ctx->{NAME}_LINK_FLAGS))\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,12 +127,15 @@ static PyObject *py_messaging_send(PyObject *self, PyObject *args, PyObject *kwa
|
||||
NTSTATUS status;
|
||||
struct server_id server;
|
||||
const char *kwnames[] = { "target", "msg_type", "data", NULL };
|
||||
int length;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois#|:send",
|
||||
discard_const_p(char *, kwnames), &target, &msg_type, &data.data, &data.length)) {
|
||||
discard_const_p(char *, kwnames), &target, &msg_type, &data.data, &length)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data.length = length;
|
||||
|
||||
if (!server_id_from_py(target, &server))
|
||||
return NULL;
|
||||
|
||||
@ -159,11 +162,11 @@ static void py_msg_callback_wrapper(struct messaging_context *msg, void *private
|
||||
static PyObject *py_messaging_register(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
messaging_Object *iface = (messaging_Object *)self;
|
||||
uint32_t msg_type = -1;
|
||||
int msg_type = -1;
|
||||
PyObject *callback;
|
||||
NTSTATUS status;
|
||||
const char *kwnames[] = { "callback", "msg_type", NULL };
|
||||
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:send",
|
||||
discard_const_p(char *, kwnames), &callback, &msg_type)) {
|
||||
return NULL;
|
||||
@ -172,8 +175,10 @@ static PyObject *py_messaging_register(PyObject *self, PyObject *args, PyObject
|
||||
Py_INCREF(callback);
|
||||
|
||||
if (msg_type == -1) {
|
||||
uint32_t msg_type32 = msg_type;
|
||||
status = messaging_register_tmp(iface->msg_ctx, callback,
|
||||
py_msg_callback_wrapper, &msg_type);
|
||||
py_msg_callback_wrapper, &msg_type32);
|
||||
msg_type = msg_type32;
|
||||
} else {
|
||||
status = messaging_register(iface->msg_ctx, callback,
|
||||
msg_type, py_msg_callback_wrapper);
|
||||
@ -189,7 +194,7 @@ static PyObject *py_messaging_register(PyObject *self, PyObject *args, PyObject
|
||||
static PyObject *py_messaging_deregister(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
messaging_Object *iface = (messaging_Object *)self;
|
||||
uint32_t msg_type = -1;
|
||||
int msg_type = -1;
|
||||
PyObject *callback;
|
||||
const char *kwnames[] = { "callback", "msg_type", NULL };
|
||||
|
||||
|
@ -1354,7 +1354,7 @@ union smb_open {
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
/* SMBNTCreateX interface */
|
||||
/* SMBNTCreateX, nttrans and generic interface */
|
||||
struct {
|
||||
enum smb_open_level level;
|
||||
struct {
|
||||
@ -1377,6 +1377,9 @@ union smb_open {
|
||||
NTTRANS varient of the call */
|
||||
struct security_descriptor *sec_desc;
|
||||
struct smb_ea_list *ea_list;
|
||||
|
||||
/* some optional parameters from the SMB2 varient */
|
||||
bool query_maximal_access;
|
||||
} in;
|
||||
struct {
|
||||
union smb_handle file;
|
||||
@ -1392,6 +1395,10 @@ union smb_open {
|
||||
uint16_t file_type;
|
||||
uint16_t ipc_state;
|
||||
uint8_t is_directory;
|
||||
|
||||
/* optional return values matching SMB2 tagged
|
||||
values in the call */
|
||||
uint32_t maximal_access;
|
||||
} out;
|
||||
} ntcreatex, nttrans, generic;
|
||||
|
||||
|
@ -61,10 +61,10 @@ NTSTATUS smb2_cancel(struct smb2_request *r)
|
||||
|
||||
SSVAL(c->out.body, 0x02, 0);
|
||||
|
||||
old_timeout = c->transport->options.timeout;
|
||||
c->transport->options.timeout = 0;
|
||||
old_timeout = c->transport->options.request_timeout;
|
||||
c->transport->options.request_timeout = 0;
|
||||
smb2_transport_send(c);
|
||||
c->transport->options.timeout = old_timeout;
|
||||
c->transport->options.request_timeout = old_timeout;
|
||||
|
||||
if (c->state == SMB2_REQUEST_ERROR) {
|
||||
status = c->status;
|
||||
|
@ -5,6 +5,6 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \
|
||||
transport.o request.o negprot.o session.o tcon.o \
|
||||
create.o close.o connect.o getinfo.o write.o read.o \
|
||||
setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \
|
||||
lock.o notify.o cancel.o keepalive.o break.o util.o)
|
||||
lock.o notify.o cancel.o keepalive.o break.o util.o signing.o)
|
||||
|
||||
$(eval $(call proto_header_template,$(libclisrcdir)/smb2/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c)))
|
||||
|
@ -33,6 +33,7 @@ struct smb2_connect_state {
|
||||
struct resolve_context *resolve_ctx;
|
||||
const char *host;
|
||||
const char *share;
|
||||
struct smbcli_options options;
|
||||
struct smb2_negprot negprot;
|
||||
struct smb2_tree_connect tcon;
|
||||
struct smb2_session *session;
|
||||
@ -103,6 +104,34 @@ static void continue_negprot(struct smb2_request *req)
|
||||
|
||||
transport->negotiate.system_time = state->negprot.out.system_time;
|
||||
transport->negotiate.server_start_time = state->negprot.out.server_start_time;
|
||||
transport->negotiate.security_mode = state->negprot.out.security_mode;
|
||||
|
||||
switch (transport->options.signing) {
|
||||
case SMB_SIGNING_OFF:
|
||||
if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
|
||||
composite_error(c, NT_STATUS_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
transport->signing.doing_signing = false;
|
||||
break;
|
||||
case SMB_SIGNING_SUPPORTED:
|
||||
case SMB_SIGNING_AUTO:
|
||||
if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
|
||||
transport->signing.doing_signing = true;
|
||||
} else {
|
||||
transport->signing.doing_signing = false;
|
||||
}
|
||||
break;
|
||||
case SMB_SIGNING_REQUIRED:
|
||||
if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
|
||||
transport->signing.doing_signing = true;
|
||||
} else {
|
||||
composite_error(c, NT_STATUS_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
state->session = smb2_session_init(transport, global_loadparm, state, true);
|
||||
if (composite_nomem(state->session, c)) return;
|
||||
@ -129,12 +158,24 @@ static void continue_socket(struct composite_context *creq)
|
||||
c->status = smbcli_sock_connect_recv(creq, state, &sock);
|
||||
if (!composite_is_ok(c)) return;
|
||||
|
||||
transport = smb2_transport_init(sock, state);
|
||||
transport = smb2_transport_init(sock, state, &state->options);
|
||||
if (composite_nomem(transport, c)) return;
|
||||
|
||||
ZERO_STRUCT(state->negprot);
|
||||
state->negprot.in.dialect_count = 2;
|
||||
state->negprot.in.security_mode = 0;
|
||||
switch (transport->options.signing) {
|
||||
case SMB_SIGNING_OFF:
|
||||
state->negprot.in.security_mode = 0;
|
||||
break;
|
||||
case SMB_SIGNING_SUPPORTED:
|
||||
case SMB_SIGNING_AUTO:
|
||||
state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
|
||||
break;
|
||||
case SMB_SIGNING_REQUIRED:
|
||||
state->negprot.in.security_mode =
|
||||
SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
|
||||
break;
|
||||
}
|
||||
state->negprot.in.capabilities = 0;
|
||||
unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
|
||||
dialects[0] = 0;
|
||||
@ -178,7 +219,8 @@ struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
|
||||
const char *share,
|
||||
struct resolve_context *resolve_ctx,
|
||||
struct cli_credentials *credentials,
|
||||
struct event_context *ev)
|
||||
struct event_context *ev,
|
||||
struct smbcli_options *options)
|
||||
{
|
||||
struct composite_context *c;
|
||||
struct smb2_connect_state *state;
|
||||
@ -193,6 +235,7 @@ struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
|
||||
c->private_data = state;
|
||||
|
||||
state->credentials = credentials;
|
||||
state->options = *options;
|
||||
state->host = talloc_strdup(c, host);
|
||||
if (composite_nomem(state->host, c)) return c;
|
||||
state->share = talloc_strdup(c, share);
|
||||
@ -232,10 +275,11 @@ NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx,
|
||||
struct resolve_context *resolve_ctx,
|
||||
struct cli_credentials *credentials,
|
||||
struct smb2_tree **tree,
|
||||
struct event_context *ev)
|
||||
struct event_context *ev,
|
||||
struct smbcli_options *options)
|
||||
{
|
||||
struct composite_context *c = smb2_connect_send(mem_ctx, host, share,
|
||||
resolve_ctx,
|
||||
credentials, ev);
|
||||
credentials, ev, options);
|
||||
return smb2_connect_recv(c, mem_ctx, tree);
|
||||
}
|
||||
|
@ -387,12 +387,13 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct
|
||||
/* pull out the parsed blobs */
|
||||
for (i=0;i<io->out.blobs.num_blobs;i++) {
|
||||
if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
|
||||
/* why 8 bytes not 4?? */
|
||||
/* TODO: this also contains a status field in
|
||||
first 4 bytes */
|
||||
if (io->out.blobs.blobs[i].data.length != 8) {
|
||||
smb2_request_destroy(req);
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 0);
|
||||
io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 4);
|
||||
}
|
||||
if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
|
||||
if (io->out.blobs.blobs[i].data.length != 32) {
|
||||
|
@ -44,10 +44,10 @@ struct smb2_request *smb2_notify_send(struct smb2_tree *tree, struct smb2_notify
|
||||
SIVAL(req->out.body, 0x18, io->in.completion_filter);
|
||||
SIVAL(req->out.body, 0x1C, io->in.unknown);
|
||||
|
||||
old_timeout = req->transport->options.timeout;
|
||||
req->transport->options.timeout = 0;
|
||||
old_timeout = req->transport->options.request_timeout;
|
||||
req->transport->options.request_timeout = 0;
|
||||
smb2_transport_send(req);
|
||||
req->transport->options.timeout = old_timeout;
|
||||
req->transport->options.request_timeout = old_timeout;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
@ -164,8 +164,8 @@ static void session_request_handler(struct smb2_request *req)
|
||||
|
||||
session_key_err = gensec_session_key(session->gensec, &session_key);
|
||||
if (NT_STATUS_IS_OK(session_key_err)) {
|
||||
session->session_key = session_key;
|
||||
}
|
||||
session->transport->signing.session_key = session_key;
|
||||
}
|
||||
}
|
||||
|
||||
session->uid = state->io.out.uid;
|
||||
@ -187,6 +187,14 @@ static void session_request_handler(struct smb2_request *req)
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->transport->signing.doing_signing) {
|
||||
c->status = smb2_start_signing(session->transport);
|
||||
if (!NT_STATUS_IS_OK(c->status)) {
|
||||
composite_error(c, c->status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
composite_done(c);
|
||||
}
|
||||
|
||||
@ -208,7 +216,10 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se
|
||||
|
||||
ZERO_STRUCT(state->io);
|
||||
state->io.in.vc_number = 0;
|
||||
state->io.in.security_mode = 0;
|
||||
if (session->transport->signing.doing_signing) {
|
||||
state->io.in.security_mode =
|
||||
SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
|
||||
}
|
||||
state->io.in.capabilities = 0;
|
||||
state->io.in.channel = 0;
|
||||
state->io.in.previous_sessionid = 0;
|
||||
|
165
source4/libcli/smb2/signing.c
Normal file
165
source4/libcli/smb2/signing.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
SMB2 Signing Code
|
||||
|
||||
Copyright (C) Andrew Tridgell <tridge@samba.org> 2008
|
||||
|
||||
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 "libcli/raw/libcliraw.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/smb2/smb2_calls.h"
|
||||
#include "heimdal/lib/hcrypto/sha.h"
|
||||
|
||||
/*
|
||||
NOTE: this code does not yet interoperate with the windows SMB2
|
||||
implementation. We are waiting on feedback on the docs to find out
|
||||
why
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
setup signing on a transport
|
||||
*/
|
||||
NTSTATUS smb2_start_signing(struct smb2_transport *transport)
|
||||
{
|
||||
if (transport->signing.session_key.length != 16) {
|
||||
DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
|
||||
(unsigned)transport->signing.session_key.length));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
transport->signing.signing_started = true;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
sign an outgoing message
|
||||
*/
|
||||
NTSTATUS smb2_sign_message(struct smb2_request *req)
|
||||
{
|
||||
struct smb2_request_buffer *buf = &req->out;
|
||||
uint64_t session_id;
|
||||
SHA256_CTX m;
|
||||
uint8_t res[32];
|
||||
|
||||
if (!req->transport->signing.doing_signing ||
|
||||
!req->transport->signing.signing_started) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
|
||||
/* can't sign non-SMB2 messages */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
|
||||
if (session_id == 0) {
|
||||
/* we don't sign messages with a zero session_id. See
|
||||
MS-SMB2 3.2.4.1.1 */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (req->transport->signing.session_key.length != 16) {
|
||||
DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
|
||||
(unsigned)req->transport->signing.session_key.length));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
|
||||
|
||||
SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
|
||||
|
||||
ZERO_STRUCT(m);
|
||||
SHA256_Init(&m);
|
||||
SHA256_Update(&m, req->transport->signing.session_key.data,
|
||||
req->transport->signing.session_key.length);
|
||||
SHA256_Update(&m, buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE);
|
||||
SHA256_Final(res, &m);
|
||||
|
||||
DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
|
||||
|
||||
memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16);
|
||||
|
||||
if (DEBUGLVL(5)) {
|
||||
/* check our own signature */
|
||||
smb2_check_signature(req->transport, buf->buffer, buf->size);
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
check an incoming signature
|
||||
*/
|
||||
NTSTATUS smb2_check_signature(struct smb2_transport *transport,
|
||||
uint8_t *buffer, uint_t length)
|
||||
{
|
||||
uint64_t session_id;
|
||||
SHA256_CTX m;
|
||||
uint8_t res[SHA256_DIGEST_LENGTH];
|
||||
uint8_t sig[16];
|
||||
|
||||
if (!transport->signing.signing_started ||
|
||||
!transport->signing.doing_signing) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (length < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
|
||||
/* can't check non-SMB2 messages */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
session_id = BVAL(buffer+NBT_HDR_SIZE, SMB2_HDR_SESSION_ID);
|
||||
if (session_id == 0) {
|
||||
/* don't sign messages with a zero session_id. See
|
||||
MS-SMB2 3.2.4.1.1 */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (transport->signing.session_key.length == 0) {
|
||||
/* we don't have the session key yet */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (transport->signing.session_key.length != 16) {
|
||||
DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
|
||||
(unsigned)transport->signing.session_key.length));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
memcpy(sig, buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, 16);
|
||||
|
||||
memset(buffer + NBT_HDR_SIZE + SMB2_HDR_SIGNATURE, 0, 16);
|
||||
|
||||
ZERO_STRUCT(m);
|
||||
SHA256_Init(&m);
|
||||
SHA256_Update(&m, transport->signing.session_key.data, 16);
|
||||
SHA256_Update(&m, buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE);
|
||||
SHA256_Final(res, &m);
|
||||
|
||||
memcpy(buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, sig, 16);
|
||||
|
||||
if (memcmp(res, sig, 16) != 0) {
|
||||
DEBUG(0,("Bad SMB2 signature for message of size %u\n", length));
|
||||
dump_data(0, sig, 16);
|
||||
dump_data(0, res, 16);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -23,20 +23,24 @@
|
||||
#define __LIBCLI_SMB2_SMB2_H__
|
||||
|
||||
#include "libcli/raw/request.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
|
||||
struct smb2_handle;
|
||||
|
||||
struct smb2_options {
|
||||
uint32_t timeout;
|
||||
struct smb2_signing_context {
|
||||
bool doing_signing;
|
||||
bool signing_started;
|
||||
DATA_BLOB session_key;
|
||||
};
|
||||
|
||||
/*
|
||||
information returned from the negotiate response
|
||||
information returned from the negotiate process
|
||||
*/
|
||||
struct smb2_negotiate {
|
||||
DATA_BLOB secblob;
|
||||
NTTIME system_time;
|
||||
NTTIME server_start_time;
|
||||
uint16_t security_mode;
|
||||
};
|
||||
|
||||
/* this is the context for the smb2 transport layer */
|
||||
@ -44,7 +48,6 @@ struct smb2_transport {
|
||||
/* socket level info */
|
||||
struct smbcli_socket *socket;
|
||||
|
||||
struct smb2_options options;
|
||||
struct smb2_negotiate negotiate;
|
||||
|
||||
/* next seqnum to allocate */
|
||||
@ -74,6 +77,9 @@ struct smb2_transport {
|
||||
/* private data passed to the oplock handler */
|
||||
void *private_data;
|
||||
} oplock;
|
||||
|
||||
struct smbcli_options options;
|
||||
struct smb2_signing_context signing;
|
||||
};
|
||||
|
||||
|
||||
@ -92,7 +98,6 @@ struct smb2_session {
|
||||
struct smb2_transport *transport;
|
||||
struct gensec_security *gensec;
|
||||
uint64_t uid;
|
||||
DATA_BLOB session_key;
|
||||
};
|
||||
|
||||
|
||||
@ -193,6 +198,13 @@ struct smb2_request {
|
||||
#define SMB2_HDR_SIGNATURE 0x30 /* 16 bytes */
|
||||
#define SMB2_HDR_BODY 0x40
|
||||
|
||||
/* header flags */
|
||||
#define SMB2_HDR_FLAG_REDIRECT 0x01
|
||||
#define SMB2_HDR_FLAG_ASYNC 0x02
|
||||
#define SMB2_HDR_FLAG_CHAINED 0x04
|
||||
#define SMB2_HDR_FLAG_SIGNED 0x08
|
||||
#define SMB2_HDR_FLAG_DFS 0x10000000
|
||||
|
||||
/* SMB2 opcodes */
|
||||
#define SMB2_OP_NEGPROT 0x00
|
||||
#define SMB2_OP_SESSSETUP 0x01
|
||||
|
@ -74,7 +74,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob);
|
||||
create a transport structure based on an established socket
|
||||
*/
|
||||
struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
|
||||
TALLOC_CTX *parent_ctx)
|
||||
TALLOC_CTX *parent_ctx,
|
||||
struct smbcli_options *options)
|
||||
{
|
||||
struct smb2_transport *transport;
|
||||
|
||||
@ -82,6 +83,7 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
|
||||
if (!transport) return NULL;
|
||||
|
||||
transport->socket = talloc_steal(transport, sock);
|
||||
transport->options = *options;
|
||||
|
||||
/* setup the stream -> packet parser */
|
||||
transport->packet = packet_init(transport);
|
||||
@ -112,8 +114,6 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock,
|
||||
|
||||
talloc_set_destructor(transport, transport_destructor);
|
||||
|
||||
transport->options.timeout = 30;
|
||||
|
||||
return transport;
|
||||
}
|
||||
|
||||
@ -140,27 +140,24 @@ void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status)
|
||||
}
|
||||
}
|
||||
|
||||
static bool smb2_handle_oplock_break(struct smb2_transport *transport,
|
||||
const DATA_BLOB *blob)
|
||||
static NTSTATUS smb2_handle_oplock_break(struct smb2_transport *transport,
|
||||
const DATA_BLOB *blob)
|
||||
{
|
||||
uint8_t *hdr;
|
||||
uint16_t opcode;
|
||||
uint64_t seqnum;
|
||||
|
||||
hdr = blob->data+NBT_HDR_SIZE;
|
||||
|
||||
if (blob->length < (SMB2_MIN_SIZE+0x18)) {
|
||||
DEBUG(1,("Discarding smb2 oplock reply of size %u\n",
|
||||
blob->length));
|
||||
return false;
|
||||
(unsigned)blob->length));
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
|
||||
opcode = SVAL(hdr, SMB2_HDR_OPCODE);
|
||||
seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
|
||||
|
||||
if ((opcode != SMB2_OP_BREAK) ||
|
||||
(seqnum != UINT64_MAX)) {
|
||||
return false;
|
||||
if (opcode != SMB2_OP_BREAK) {
|
||||
return NT_STATUS_INVALID_NETWORK_RESPONSE;
|
||||
}
|
||||
|
||||
if (transport->oplock.handler) {
|
||||
@ -173,9 +170,11 @@ static bool smb2_handle_oplock_break(struct smb2_transport *transport,
|
||||
|
||||
transport->oplock.handler(transport, &h, level,
|
||||
transport->oplock.private_data);
|
||||
} else {
|
||||
DEBUG(5,("Got SMB2 oplock break with no handler\n"));
|
||||
}
|
||||
|
||||
return true;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -194,6 +193,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
|
||||
uint16_t buffer_code;
|
||||
uint32_t dynamic_size;
|
||||
uint32_t i;
|
||||
NTSTATUS status;
|
||||
|
||||
buffer = blob.data;
|
||||
len = blob.length;
|
||||
@ -205,14 +205,20 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (smb2_handle_oplock_break(transport, &blob)) {
|
||||
status = smb2_check_signature(transport, buffer, len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(buffer);
|
||||
return NT_STATUS_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
flags = IVAL(hdr, SMB2_HDR_FLAGS);
|
||||
seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
|
||||
|
||||
/* see MS-SMB2 3.2.5.19 */
|
||||
if (seqnum == UINT64_MAX) {
|
||||
return smb2_handle_oplock_break(transport, &blob);
|
||||
}
|
||||
|
||||
/* match the incoming request against the list of pending requests */
|
||||
for (req=transport->pending_recv; req; req=req->next) {
|
||||
if (req->seqnum == seqnum) break;
|
||||
@ -340,6 +346,13 @@ void smb2_transport_send(struct smb2_request *req)
|
||||
return;
|
||||
}
|
||||
|
||||
status = smb2_sign_message(req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
req->state = SMB2_REQUEST_ERROR;
|
||||
req->status = status;
|
||||
return;
|
||||
}
|
||||
|
||||
blob = data_blob_const(req->out.buffer, req->out.size);
|
||||
status = packet_send(req->transport->packet, blob);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -352,9 +365,9 @@ void smb2_transport_send(struct smb2_request *req)
|
||||
DLIST_ADD(req->transport->pending_recv, req);
|
||||
|
||||
/* add a timeout */
|
||||
if (req->transport->options.timeout) {
|
||||
if (req->transport->options.request_timeout) {
|
||||
event_add_timed(req->transport->socket->event.ctx, req,
|
||||
timeval_current_ofs(req->transport->options.timeout, 0),
|
||||
timeval_current_ofs(req->transport->options.request_timeout, 0),
|
||||
smb2_timeout_handler, req);
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,7 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
|
||||
struct composite_context *c;
|
||||
struct pipe_np_smb2_state *s;
|
||||
struct composite_context *conn_req;
|
||||
struct smbcli_options options;
|
||||
|
||||
/* composite context allocation and setup */
|
||||
c = composite_create(mem_ctx, io->pipe->conn->event_ctx);
|
||||
@ -240,11 +241,14 @@ static struct composite_context *dcerpc_pipe_connect_ncacn_np_smb2_send(
|
||||
cli_credentials_guess(s->io.creds, lp_ctx);
|
||||
}
|
||||
|
||||
lp_smbcli_options(lp_ctx, &options);
|
||||
|
||||
/* send smb2 connect request */
|
||||
conn_req = smb2_connect_send(mem_ctx, s->io.binding->host, "IPC$",
|
||||
s->io.resolve_ctx,
|
||||
s->io.creds,
|
||||
c->event_ctx);
|
||||
c->event_ctx,
|
||||
&options);
|
||||
composite_continue(c, conn_req, continue_smb2_connect, c);
|
||||
return c;
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ static NTSTATUS smb2_session_key(struct dcerpc_connection *c, DATA_BLOB *session
|
||||
{
|
||||
struct smb2_private *smb = talloc_get_type(c->transport.private_data,
|
||||
struct smb2_private);
|
||||
*session_key = smb->tree->session->session_key;
|
||||
*session_key = smb->tree->session->transport->signing.session_key;
|
||||
if (session_key->data == NULL) {
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
|
@ -233,6 +233,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
|
||||
io->smb2.out.size = io2->generic.out.size;
|
||||
io->smb2.out.file_attr = io2->generic.out.attrib;
|
||||
io->smb2.out.reserved2 = 0;
|
||||
io->smb2.out.maximal_access = io2->generic.out.maximal_access;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -522,6 +523,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
|
||||
io2->generic.in.fname = io->smb2.in.fname;
|
||||
io2->generic.in.sec_desc = io->smb2.in.sec_desc;
|
||||
io2->generic.in.ea_list = &io->smb2.in.eas;
|
||||
io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access;
|
||||
|
||||
/* we don't support timewarp yet */
|
||||
if (io->smb2.in.timewarp != 0) {
|
||||
|
@ -464,7 +464,11 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
/* on SMB, this bit is always granted, even if not
|
||||
asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -496,7 +500,9 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
|
||||
|
||||
/* expand the generic access bits to file specific bits */
|
||||
*access_mask = pvfs_translate_mask(*access_mask);
|
||||
*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
*access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
status = pvfs_acl_load(pvfs, name, -1, acl);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
||||
@ -518,8 +524,11 @@ NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
|
||||
/* check the acl against the required access mask */
|
||||
status = sec_access_check(sd, token, *access_mask, access_mask);
|
||||
|
||||
/* this bit is always granted, even if not asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
|
||||
/* on SMB, this bit is always granted, even if not
|
||||
asked for */
|
||||
*access_mask |= SEC_FILE_READ_ATTRIBUTE;
|
||||
}
|
||||
|
||||
talloc_free(acl);
|
||||
|
||||
@ -800,3 +809,15 @@ NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
return the maximum allowed access mask
|
||||
*/
|
||||
NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
|
||||
struct ntvfs_request *req,
|
||||
struct pvfs_filename *name,
|
||||
uint32_t *maximal_access)
|
||||
{
|
||||
*maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
return pvfs_access_check(pvfs, req, name, maximal_access);
|
||||
}
|
||||
|
@ -73,7 +73,8 @@ NTSTATUS pvfs_ioctl(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
case RAW_IOCTL_SMB2:
|
||||
case RAW_IOCTL_SMB2_NO_HANDLE:
|
||||
return NT_STATUS_FS_DRIVER_REQUIRED;
|
||||
/* see WSPP SMB2 test 46 */
|
||||
return NT_STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
|
@ -68,13 +68,8 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs,
|
||||
int i,
|
||||
NTSTATUS status)
|
||||
{
|
||||
/* in SMB2 mode we also try to unlock failing lock */
|
||||
if (req->ctx->protocol != PROTOCOL_SMB2) {
|
||||
i--;
|
||||
}
|
||||
|
||||
/* undo the locks we just did */
|
||||
for (;i>=0;i--) {
|
||||
for (i--;i>=0;i--) {
|
||||
brl_unlock(pvfs->brl_context,
|
||||
f->brl_handle,
|
||||
locks[i].pid,
|
||||
@ -390,12 +385,9 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
|
||||
DLIST_ADD(f->pending_list, pending);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
/* in SMB2 mode we also try to unlock failing lock */
|
||||
if (req->ctx->protocol != PROTOCOL_SMB2) {
|
||||
i--;
|
||||
}
|
||||
|
||||
/* undo the locks we just did */
|
||||
for (;i>=0;i--) {
|
||||
for (i--;i>=0;i--) {
|
||||
brl_unlock(pvfs->brl_context,
|
||||
f->brl_handle,
|
||||
locks[i].pid,
|
||||
|
@ -252,8 +252,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
|
||||
} else {
|
||||
status = pvfs_access_check_create(pvfs, req, name, &access_mask);
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
f->ntvfs = h;
|
||||
@ -578,6 +582,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
|
||||
status = pvfs_access_check_create(pvfs, req, name, &access_mask);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
/* check that the parent isn't opened with delete on close set */
|
||||
status = pvfs_resolve_parent(pvfs, req, name, &parent);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
@ -1122,6 +1132,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
uint32_t create_options;
|
||||
uint32_t share_access;
|
||||
uint32_t access_mask;
|
||||
uint32_t create_action = NTCREATEX_ACTION_EXISTED;
|
||||
bool del_on_close;
|
||||
bool stream_existed, stream_truncate=false;
|
||||
uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
|
||||
@ -1134,6 +1145,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
return ntvfs_map_open(ntvfs, req, io);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(io->generic.out);
|
||||
|
||||
create_options = io->generic.in.create_options;
|
||||
share_access = io->generic.in.share_access;
|
||||
access_mask = io->generic.in.access_mask;
|
||||
@ -1169,6 +1182,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* we ignore some file_attr bits */
|
||||
io->ntcreatex.in.file_attr &= ~(FILE_ATTRIBUTE_NONINDEXED |
|
||||
FILE_ATTRIBUTE_COMPRESSED |
|
||||
FILE_ATTRIBUTE_REPARSE_POINT |
|
||||
FILE_ATTRIBUTE_SPARSE |
|
||||
FILE_ATTRIBUTE_NORMAL);
|
||||
|
||||
/* resolve the cifs name to a posix name */
|
||||
status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname,
|
||||
PVFS_RESOLVE_STREAMS, &name);
|
||||
@ -1210,6 +1230,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
} else {
|
||||
stream_truncate = true;
|
||||
}
|
||||
create_action = NTCREATEX_ACTION_TRUNCATED;
|
||||
break;
|
||||
|
||||
case NTCREATEX_DISP_OPEN:
|
||||
@ -1228,6 +1249,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
} else {
|
||||
stream_truncate = true;
|
||||
}
|
||||
create_action = NTCREATEX_ACTION_TRUNCATED;
|
||||
break;
|
||||
|
||||
case NTCREATEX_DISP_CREATE:
|
||||
@ -1272,8 +1294,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
/* check the security descriptor */
|
||||
status = pvfs_access_check(pvfs, req, name, &access_mask);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
if (io->generic.in.query_maximal_access) {
|
||||
status = pvfs_access_maximal_allowed(pvfs, req, name,
|
||||
&io->generic.out.maximal_access);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
}
|
||||
|
||||
status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
|
||||
@ -1487,7 +1513,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
|
||||
io->generic.out.oplock_level = oplock_granted;
|
||||
io->generic.out.file.ntvfs = h;
|
||||
io->generic.out.create_action = stream_existed?
|
||||
NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
|
||||
create_action:NTCREATEX_ACTION_CREATED;
|
||||
|
||||
io->generic.out.create_time = name->dos.create_time;
|
||||
io->generic.out.access_time = name->dos.access_time;
|
||||
io->generic.out.write_time = name->dos.write_time;
|
||||
|
@ -41,6 +41,10 @@ static uint32_t pvfs_fileinfo_access(union smb_fileinfo *info)
|
||||
needed = 0;
|
||||
break;
|
||||
|
||||
case RAW_FILEINFO_ACCESS_INFORMATION:
|
||||
needed = 0;
|
||||
break;
|
||||
|
||||
case RAW_FILEINFO_SEC_DESC:
|
||||
needed = 0;
|
||||
if (info->query_secdesc.in.secinfo_flags & (SECINFO_OWNER|SECINFO_GROUP)) {
|
||||
@ -216,6 +220,10 @@ static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs,
|
||||
|
||||
case RAW_FILEINFO_NAME_INFO:
|
||||
case RAW_FILEINFO_NAME_INFORMATION:
|
||||
if (req->ctx->protocol == PROTOCOL_SMB2) {
|
||||
/* strange that SMB2 doesn't have this */
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
info->name_info.out.fname.s = name->original_name;
|
||||
return NT_STATUS_OK;
|
||||
|
||||
|
@ -457,7 +457,12 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
|
||||
|
||||
/* possibly change the attribute */
|
||||
if (newstats.dos.attrib != h->name->dos.attrib) {
|
||||
mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
|
||||
mode_t mode;
|
||||
if ((newstats.dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
|
||||
if (!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (fchmod(h->fd, mode) == -1) {
|
||||
return pvfs_map_errno(pvfs, errno);
|
||||
|
@ -162,9 +162,9 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
|
||||
struct composite_context *creq;
|
||||
struct share_config *scfg = ntvfs->ctx->config;
|
||||
struct smb2_tree *tree;
|
||||
|
||||
struct cli_credentials *credentials;
|
||||
bool machine_account;
|
||||
struct smbcli_options options;
|
||||
|
||||
/* Here we need to determine which server to connect to.
|
||||
* For now we use parametric options, type cifs.
|
||||
@ -224,10 +224,12 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
lp_smbcli_options(ntvfs->ctx->lp_ctx, &options);
|
||||
|
||||
creq = smb2_connect_send(private, host, remote_share,
|
||||
lp_resolve_context(ntvfs->ctx->lp_ctx),
|
||||
credentials,
|
||||
ntvfs->ctx->event_ctx);
|
||||
ntvfs->ctx->event_ctx, &options);
|
||||
|
||||
status = smb2_connect_recv(creq, private, &tree);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
@ -61,3 +61,4 @@ nss.test # Fails
|
||||
samba4.samba3sam.python # Conversion from EJS not yet finished
|
||||
raw.offline # Samba 4 doesn't have much offline support yet
|
||||
winreg* #Does not authenticate against the target server
|
||||
^samba4.samdb.python #Not working yet
|
||||
|
@ -930,8 +930,9 @@ def provision(setup_dir, message, session_info,
|
||||
if aci is None:
|
||||
aci = "# no aci for local ldb"
|
||||
|
||||
if smbconf is None:
|
||||
os.makedirs(os.path.join(targetdir, "etc"))
|
||||
if targetdir is not None:
|
||||
if (not os.path.exists(os.path.join(targetdir, "etc"))):
|
||||
os.makedirs(os.path.join(targetdir, "etc"))
|
||||
smbconf = os.path.join(targetdir, "etc", "smb.conf")
|
||||
|
||||
# only install a new smb.conf if there isn't one there already
|
||||
|
@ -20,27 +20,28 @@
|
||||
|
||||
from samba.dcerpc import ClientConnection
|
||||
from unittest import TestCase
|
||||
from samba.tests import cmdline_loadparm
|
||||
|
||||
class BareTestCase(TestCase):
|
||||
def test_bare(self):
|
||||
# Connect to the echo pipe
|
||||
x = ClientConnection("ncalrpc:localhost[DEFAULT]",
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1))
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=cmdline_loadparm)
|
||||
self.assertEquals("\x01\x00\x00\x00", x.request(0, chr(0) * 4))
|
||||
|
||||
def test_alter_context(self):
|
||||
x = ClientConnection("ncalrpc:localhost[DEFAULT]",
|
||||
("12345778-1234-abcd-ef00-0123456789ac", 1))
|
||||
("12345778-1234-abcd-ef00-0123456789ac", 1), lp_ctx=cmdline_loadparm)
|
||||
y = ClientConnection("ncalrpc:localhost",
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1),
|
||||
basis_connection=x)
|
||||
basis_connection=x, lp_ctx=cmdline_loadparm)
|
||||
x.alter_context(("60a15ec5-4de8-11d7-a637-005056a20182", 1))
|
||||
# FIXME: self.assertEquals("\x01\x00\x00\x00", x.request(0, chr(0) * 4))
|
||||
|
||||
def test_two_connections(self):
|
||||
x = ClientConnection("ncalrpc:localhost[DEFAULT]",
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1))
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1), lp_ctx=cmdline_loadparm)
|
||||
y = ClientConnection("ncalrpc:localhost",
|
||||
("60a15ec5-4de8-11d7-a637-005056a20182", 1),
|
||||
basis_connection=x)
|
||||
basis_connection=x, lp_ctx=cmdline_loadparm)
|
||||
self.assertEquals("\x01\x00\x00\x00", y.request(0, chr(0) * 4))
|
||||
|
@ -27,7 +27,7 @@ class RpcEchoTests(RpcInterfaceTestCase):
|
||||
self.conn = echo.rpcecho("ncalrpc:", self.get_loadparm())
|
||||
|
||||
def test_two_contexts(self):
|
||||
self.conn2 = echo.rpcecho("ncalrpc:", basis_connection=self.conn)
|
||||
self.conn2 = echo.rpcecho("ncalrpc:", self.get_loadparm(), basis_connection=self.conn)
|
||||
self.assertEquals(3, self.conn2.AddOne(2))
|
||||
|
||||
def test_abstract_syntax(self):
|
||||
|
@ -19,12 +19,13 @@
|
||||
from samba.auth import system_session
|
||||
from samba.credentials import Credentials
|
||||
import os
|
||||
from samba.provision import setup_samdb, guess_names, setup_templatesdb
|
||||
from samba.provision import setup_samdb, guess_names, setup_templatesdb, make_smbconf
|
||||
from samba.samdb import SamDB
|
||||
from samba.tests import cmdline_loadparm, TestCaseInTempDir
|
||||
from samba import security
|
||||
from unittest import TestCase
|
||||
import uuid
|
||||
import param
|
||||
|
||||
class SamDBTestCase(TestCaseInTempDir):
|
||||
def setUp(self):
|
||||
@ -43,9 +44,22 @@ class SamDBTestCase(TestCaseInTempDir):
|
||||
hostguid = str(uuid.uuid4())
|
||||
path = os.path.join(self.tempdir, "samdb.ldb")
|
||||
session_info = system_session()
|
||||
names = guess_names(lp=cmdline_loadparm, hostname="foo",
|
||||
domain="EXAMPLE.COM", dnsdomain="example.com",
|
||||
serverrole="domain controller",
|
||||
|
||||
hostname="foo"
|
||||
domain="EXAMPLE"
|
||||
dnsdomain="example.com"
|
||||
serverrole="domain controller"
|
||||
|
||||
smbconf = os.path.join(self.tempdir, "smb.conf")
|
||||
make_smbconf(smbconf, setup_path, hostname, domain, dnsdomain, serverrole,
|
||||
self.tempdir)
|
||||
|
||||
lp = param.LoadParm()
|
||||
lp.load(smbconf)
|
||||
|
||||
names = guess_names(lp=lp, hostname=hostname,
|
||||
domain=domain, dnsdomain=dnsdomain,
|
||||
serverrole=severrole,
|
||||
domaindn=self.domaindn, configdn=configdn,
|
||||
schemadn=schemadn)
|
||||
setup_templatesdb(os.path.join(self.tempdir, "templates.ldb"),
|
||||
@ -58,9 +72,10 @@ class SamDBTestCase(TestCaseInTempDir):
|
||||
policyguid, False, "secret",
|
||||
"secret", "secret", invocationid,
|
||||
"secret", "domain controller")
|
||||
|
||||
def tearDown(self):
|
||||
for f in ['templates.ldb', 'schema.ldb', 'configuration.ldb',
|
||||
'users.ldb', 'samdb.ldb']:
|
||||
'users.ldb', 'samdb.ldb', 'smb.conf']:
|
||||
os.remove(os.path.join(self.tempdir, f))
|
||||
super(SamDBTestCase, self).tearDown()
|
||||
|
||||
|
@ -352,6 +352,6 @@ rm -rf $PREFIX/upgrade
|
||||
plantest "blackbox.upgrade" none $PYTHON setup/upgrade $CONFIGURATION --targetdir=$PREFIX/upgrade ../testdata/samba3 ../testdata/samba3/smb.conf
|
||||
rm -rf $PREFIX/provision
|
||||
mkdir $PREFIX/provision
|
||||
plantest "blackbox.provision.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_provision.sh "$PREFIX/provision" "$CONFIGURATION"
|
||||
plantest "blackbox.setpassword.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_setpassword.sh "$PREFIX/provision" "$CONFIGURATION"
|
||||
plantest "blackbox.newuser.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_newuser.sh "$PREFIX/provision" "$CONFIGURATION"
|
||||
plantest "blackbox.provision.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_provision.sh "$PREFIX/provision"
|
||||
plantest "blackbox.setpassword.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_setpassword.sh "$PREFIX/provision"
|
||||
plantest "blackbox.newuser.py" none PYTHON="$PYTHON" $samba4srcdir/setup/tests/blackbox_newuser.sh "$PREFIX/provision"
|
||||
|
@ -521,6 +521,7 @@ sub provision($$$$$$)
|
||||
my $ncalrpcdir = "$prefix_abs/ncalrpc";
|
||||
my $lockdir = "$prefix_abs/lockdir";
|
||||
my $winbindd_socket_dir = "$prefix_abs/winbind_socket";
|
||||
my $ntp_signd_socket_dir = "$prefix_abs/ntp_signd_socket";
|
||||
my $winbindd_priv_pipe_dir = "$privatedir/smbd.tmp/winbind_pipe";
|
||||
my $nsswrap_passwd = "$etcdir/passwd";
|
||||
my $nsswrap_group = "$etcdir/group";
|
||||
@ -556,6 +557,7 @@ sub provision($$$$$$)
|
||||
modules dir = $self->{bindir}/modules
|
||||
js include = $srcdir/scripting/libjs
|
||||
winbindd socket directory = $winbindd_socket_dir
|
||||
ntp signd socket directory = $ntp_signd_socket_dir
|
||||
winbind separator = /
|
||||
name resolve order = bcast
|
||||
interfaces = $interfaces
|
||||
|
@ -1,20 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
if [ $# -lt 1 ]; then
|
||||
cat <<EOF
|
||||
Usage: blackbox_newuser.sh PREFIX CONFIGURATION
|
||||
Usage: blackbox_newuser.sh PREFIX
|
||||
EOF
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
PREFIX="$1"
|
||||
CONFIGURATION="$2"
|
||||
shift 2
|
||||
shift 1
|
||||
|
||||
. `dirname $0`/../../../testprogs/blackbox/subunit.sh
|
||||
|
||||
|
||||
testit "simple-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
testit "simple-dc" $PYTHON ./setup/provision --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
|
||||
testit "newuser" $PYTHON ./setup/newuser --configfile=$PREFIX/simple-dc/etc/smb.conf testuser testpass
|
||||
|
||||
|
@ -1,28 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
if [ $# -lt 1 ]; then
|
||||
cat <<EOF
|
||||
Usage: blackbox_provision.sh PREFIX CONFIGURATION
|
||||
Usage: blackbox_provision.sh PREFIX
|
||||
EOF
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
PREFIX="$1"
|
||||
CONFIGURATION="$2"
|
||||
shift 2
|
||||
shift 1
|
||||
|
||||
. `dirname $0`/../../../testprogs/blackbox/subunit.sh
|
||||
|
||||
testit "simple-default" $PYTHON ./setup/provision $CONFIGURATION --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-default
|
||||
testit "simple-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
testit "simple-member" $PYTHON ./setup/provision $CONFIGURATION --server-role="member" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-member
|
||||
testit "simple-standalone" $PYTHON ./setup/provision $CONFIGURATION --server-role="standalone" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-standalone
|
||||
testit "blank-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/blank-dc --blank
|
||||
testit "partitions-only-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/partitions-only-dc --partitions-only
|
||||
testit "simple-default" $PYTHON ./setup/provision --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-default
|
||||
testit "simple-dc" $PYTHON ./setup/provision --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
testit "simple-member" $PYTHON ./setup/provision --server-role="member" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-member
|
||||
testit "simple-standalone" $PYTHON ./setup/provision --server-role="standalone" --domain=FOO --realm=foo.example.com --targetdir=$PREFIX/simple-standalone
|
||||
testit "blank-dc" $PYTHON ./setup/provision --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/blank-dc --blank
|
||||
testit "partitions-only-dc" $PYTHON ./setup/provision --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/partitions-only-dc --partitions-only
|
||||
|
||||
reprovision() {
|
||||
$PYTHON ./setup/provision $CONFIGURATION --domain=FOO --realm=foo.example.com --targetdir="$PREFIX/reprovision"
|
||||
$PYTHON ./setup/provision $CONFIGURATION --domain=FOO --realm=foo.example.com --targetdir="$PREFIX/reprovision"
|
||||
$PYTHON ./setup/provision --domain=FOO --realm=foo.example.com --targetdir="$PREFIX/reprovision"
|
||||
$PYTHON ./setup/provision --domain=FOO --realm=foo.example.com --targetdir="$PREFIX/reprovision"
|
||||
}
|
||||
|
||||
testit "reprovision" reprovision
|
||||
|
@ -1,19 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
if [ $# -lt 1 ]; then
|
||||
cat <<EOF
|
||||
Usage: blackbox_setpassword.sh PREFIX CONFIGURATION
|
||||
Usage: blackbox_setpassword.sh PREFIX
|
||||
EOF
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
PREFIX="$1"
|
||||
CONFIGURATION="$2"
|
||||
shift 2
|
||||
shift 1
|
||||
|
||||
. `dirname $0`/../../../testprogs/blackbox/subunit.sh
|
||||
|
||||
testit "simple-dc" $PYTHON ./setup/provision $CONFIGURATION --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
testit "simple-dc" $PYTHON ./setup/provision --server-role="dc" --domain=FOO --realm=foo.example.com --domain-sid=S-1-5-21-4177067393-1453636373-93818738 --targetdir=$PREFIX/simple-dc
|
||||
|
||||
testit "newuser" $PYTHON ./setup/newuser --configfile=$PREFIX/simple-dc/etc/smb.conf testuser testpass
|
||||
|
||||
|
@ -55,8 +55,7 @@ static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
|
||||
|
||||
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, op->info->out.blob.length));
|
||||
|
||||
/* TODO: this is maybe a o16s32_blob */
|
||||
SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x02, op->info->out.blob));
|
||||
SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob));
|
||||
SSVAL(req->out.body, 0x06, 0);
|
||||
|
||||
smb2srv_send_reply(req);
|
||||
|
@ -36,6 +36,18 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
|
||||
DATA_BLOB blob;
|
||||
|
||||
SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
|
||||
|
||||
/* setup the blobs we should give in the reply */
|
||||
if (io->smb2.out.maximal_access != 0) {
|
||||
uint32_t data[2];
|
||||
SIVAL(data, 0, 0);
|
||||
SIVAL(data, 4, io->smb2.out.maximal_access);
|
||||
SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs,
|
||||
SMB2_CREATE_TAG_MXAC,
|
||||
data_blob_const(data, 8)));
|
||||
}
|
||||
|
||||
|
||||
SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs));
|
||||
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length));
|
||||
|
||||
|
@ -158,7 +158,8 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
|
||||
}
|
||||
|
||||
if (!smb_sess) {
|
||||
status = NT_STATUS_USER_SESSION_DELETED;
|
||||
/* see WSPP test suite - test 11 */
|
||||
status = NT_STATUS_REQUEST_NOT_ACCEPTED;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
@ -264,23 +264,6 @@ gentest_OBJ_FILES = $(torturesrcdir)/gentest.o
|
||||
|
||||
MANPAGES += $(torturesrcdir)/man/gentest.1
|
||||
|
||||
#################################
|
||||
# Start BINARY gentest_smb2
|
||||
[BINARY::gentest_smb2]
|
||||
INSTALLDIR = BINDIR
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
LIBSAMBA-HOSTCONFIG \
|
||||
LIBSAMBA-UTIL \
|
||||
LIBPOPT \
|
||||
POPT_SAMBA \
|
||||
POPT_CREDENTIALS \
|
||||
LIBCLI_SMB \
|
||||
LIBCLI_RAW
|
||||
# End BINARY gentest_smb2
|
||||
#################################
|
||||
|
||||
gentest_smb2_OBJ_FILES = $(torturesrcdir)/gentest_smb2.o
|
||||
|
||||
#################################
|
||||
# Start BINARY masktest
|
||||
[BINARY::masktest]
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,7 @@
|
||||
if (v != correct) { \
|
||||
printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
|
||||
__location__, #v, (unsigned long long)v, (unsigned long long)correct); \
|
||||
return false; \
|
||||
return false; \
|
||||
}} while (0)
|
||||
|
||||
/*
|
||||
@ -52,7 +52,8 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
struct smb2_create io;
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||
uint32_t access_mask, file_attributes, denied_mask;
|
||||
uint32_t access_mask, file_attributes, file_attributes_set, denied_mask;
|
||||
union smb_fileinfo q;
|
||||
|
||||
ZERO_STRUCT(io);
|
||||
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
@ -115,7 +116,8 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
for (i=0;i<32;i++) {
|
||||
io.in.desired_access = 1<<i;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
|
||||
NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
|
||||
access_mask |= io.in.desired_access;
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
@ -131,6 +133,7 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.in.file_attributes = 0;
|
||||
file_attributes = 0;
|
||||
file_attributes_set = 0;
|
||||
denied_mask = 0;
|
||||
{
|
||||
int i;
|
||||
@ -146,12 +149,14 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
status = smb2_util_close(tree, io.out.file.handle);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
file_attributes_set |= io.out.file_attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EQUAL(file_attributes, 0xffff8048);
|
||||
CHECK_EQUAL(denied_mask, 0x4000);
|
||||
CHECK_EQUAL(file_attributes_set, 0x00001127);
|
||||
|
||||
smb2_deltree(tree, FNAME);
|
||||
|
||||
@ -177,6 +182,20 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
|
||||
|
||||
io.in.fname = FNAME;
|
||||
io.in.file_attributes = 0;
|
||||
io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
|
||||
io.in.query_maximal_access = true;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
|
||||
|
||||
q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
|
||||
q.access_information.in.file.handle = io.out.file.handle;
|
||||
status = smb2_getinfo_file(tree, tmp_ctx, &q);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
smb2_deltree(tree, FNAME);
|
||||
@ -237,6 +256,7 @@ static bool test_create_blob(struct torture_context *torture, struct smb2_tree *
|
||||
io.in.query_maximal_access = true;
|
||||
status = smb2_create(tree, tmp_ctx, &io);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
|
||||
|
||||
status = smb2_util_close(tree, io.out.file.handle);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
@ -106,7 +106,11 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
lck.in.reserved = 0x123ab3;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
lck.in.reserved = 0x123ab4;
|
||||
@ -115,7 +119,11 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
lck.in.reserved = 0x123ab5;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
lck.in.lock_count = 0x0001;
|
||||
@ -133,14 +141,22 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
CHECK_VALUE(lck.out.reserved, 0);
|
||||
|
||||
el[0].flags = 0x00000000;
|
||||
@ -473,6 +489,51 @@ static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_t
|
||||
return test_lock_read_write(torture, tree, &s);
|
||||
}
|
||||
|
||||
|
||||
static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
NTSTATUS status;
|
||||
struct smb2_handle h;
|
||||
uint8_t buf[200];
|
||||
struct smb2_lock lck;
|
||||
struct smb2_lock_element el[2];
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "autounlock.txt", &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
ZERO_STRUCT(lck);
|
||||
lck.in.locks = el;
|
||||
lck.in.lock_count = 0x0001;
|
||||
lck.in.file.handle = h;
|
||||
el[0].offset = 0;
|
||||
el[0].length = 1;
|
||||
el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
|
||||
status = smb2_lock(tree, &lck);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* basic testing of SMB2 locking
|
||||
*/
|
||||
struct torture_suite *torture_smb2_lock_init(void)
|
||||
@ -483,6 +544,7 @@ struct torture_suite *torture_smb2_lock_init(void)
|
||||
torture_suite_add_1smb2_test(suite, "RW-NONE", test_lock_rw_none);
|
||||
torture_suite_add_1smb2_test(suite, "RW-SHARED", test_lock_rw_shared);
|
||||
torture_suite_add_1smb2_test(suite, "RW-EXCLUSIV", test_lock_rw_exclusiv);
|
||||
torture_suite_add_1smb2_test(suite, "AUTO-UNLOCK", test_lock_auto_unlock);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
|
||||
|
||||
|
@ -44,6 +44,9 @@
|
||||
goto done; \
|
||||
}} while (0)
|
||||
|
||||
#define FNAME "smb2_readtest.dat"
|
||||
#define DNAME "smb2_readtest.dir"
|
||||
|
||||
static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
@ -55,7 +58,7 @@ static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tre
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "lock1.txt", &h);
|
||||
status = torture_smb2_testfile(tree, FNAME, &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
@ -139,7 +142,7 @@ static bool test_read_position(struct torture_context *torture, struct smb2_tree
|
||||
|
||||
ZERO_STRUCT(buf);
|
||||
|
||||
status = torture_smb2_testfile(tree, "lock1.txt", &h);
|
||||
status = torture_smb2_testfile(tree, FNAME, &h);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
|
||||
@ -172,6 +175,58 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_read_dir(struct torture_context *torture, struct smb2_tree *tree)
|
||||
{
|
||||
bool ret = true;
|
||||
NTSTATUS status;
|
||||
struct smb2_handle h;
|
||||
struct smb2_read rd;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(tree);
|
||||
|
||||
status = torture_smb2_testdir(tree, DNAME, &h);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf(__location__ " Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(rd);
|
||||
rd.in.file.handle = h;
|
||||
rd.in.length = 10;
|
||||
rd.in.offset = 0;
|
||||
rd.in.min_count = 1;
|
||||
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
rd.in.min_count = 11;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
|
||||
rd.in.length = 0;
|
||||
rd.in.min_count = 2592;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
|
||||
rd.in.length = 0;
|
||||
rd.in.min_count = 0;
|
||||
rd.in.channel = 0;
|
||||
status = smb2_read(tree, tmp_ctx, &rd);
|
||||
if (torture_setting_bool(torture, "windows", false)) {
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
} else {
|
||||
CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
basic testing of SMB2 read
|
||||
*/
|
||||
@ -181,6 +236,7 @@ struct torture_suite *torture_smb2_read_init(void)
|
||||
|
||||
torture_suite_add_1smb2_test(suite, "EOF", test_read_eof);
|
||||
torture_suite_add_1smb2_test(suite, "POSITION", test_read_position);
|
||||
torture_suite_add_1smb2_test(suite, "DIR", test_read_dir);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2-READ tests");
|
||||
|
||||
|
@ -203,17 +203,20 @@ bool torture_smb2_scan(struct torture_context *torture)
|
||||
NTSTATUS status;
|
||||
int opcode;
|
||||
struct smb2_request *req;
|
||||
struct smbcli_options options;
|
||||
|
||||
lp_smbcli_options(torture->lp_ctx, &options);
|
||||
|
||||
status = smb2_connect(mem_ctx, host, share,
|
||||
lp_resolve_context(torture->lp_ctx),
|
||||
credentials, &tree,
|
||||
torture->ev);
|
||||
torture->ev, &options);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Connection failed - %s\n", nt_errstr(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
tree->session->transport->options.timeout = 3;
|
||||
tree->session->transport->options.request_timeout = 3;
|
||||
|
||||
for (opcode=0;opcode<1000;opcode++) {
|
||||
req = smb2_request_init_tree(tree, opcode, 2, false, 0);
|
||||
@ -224,12 +227,12 @@ bool torture_smb2_scan(struct torture_context *torture)
|
||||
status = smb2_connect(mem_ctx, host, share,
|
||||
lp_resolve_context(torture->lp_ctx),
|
||||
credentials, &tree,
|
||||
torture->ev);
|
||||
torture->ev, &options);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Connection failed - %s\n", nt_errstr(status));
|
||||
return false;
|
||||
}
|
||||
tree->session->transport->options.timeout = 3;
|
||||
tree->session->transport->options.request_timeout = 3;
|
||||
} else {
|
||||
status = smb2_request_destroy(req);
|
||||
printf("active opcode %4d gave status %s\n", opcode, nt_errstr(status));
|
||||
|
@ -175,6 +175,10 @@ bool torture_smb2_setinfo(struct torture_context *torture)
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
|
||||
|
||||
printf("can't change a file to a directory\n");
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER);
|
||||
|
||||
printf("restore attribute\n");
|
||||
sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
|
||||
CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
|
||||
|
@ -270,11 +270,14 @@ bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tr
|
||||
const char *host = torture_setting_string(tctx, "host", NULL);
|
||||
const char *share = torture_setting_string(tctx, "share", NULL);
|
||||
struct cli_credentials *credentials = cmdline_credentials;
|
||||
struct smbcli_options options;
|
||||
|
||||
lp_smbcli_options(tctx->lp_ctx, &options);
|
||||
|
||||
status = smb2_connect(tctx, host, share,
|
||||
lp_resolve_context(tctx->lp_ctx),
|
||||
credentials, tree,
|
||||
tctx->ev);
|
||||
tctx->ev, &options);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
|
||||
host, share, nt_errstr(status));
|
||||
|
Loading…
Reference in New Issue
Block a user