1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-local

This commit is contained in:
Andrew Bartlett 2008-05-21 12:13:45 +10:00
commit 7594f79db6
33 changed files with 3789 additions and 93 deletions

View File

@ -214,15 +214,18 @@ check the space on a device
****************************************************************************/
static int do_dskattr(struct smbclient_context *ctx)
{
int total, bsize, avail;
uint32_t bsize;
uint64_t total, avail;
if (NT_STATUS_IS_ERR(smbcli_dskattr(ctx->cli->tree, &bsize, &total, &avail))) {
d_printf("Error in dskattr: %s\n",smbcli_errstr(ctx->cli->tree));
return 1;
}
d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
total, bsize, avail);
d_printf("\n\t\t%llu blocks of size %u. %llu blocks available\n",
(unsigned long long)total,
(unsigned)bsize,
(unsigned long long)avail);
return 0;
}

View File

@ -204,18 +204,23 @@ int tdb_traverse_read(struct tdb_context *tdb,
{
struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
int ret;
bool in_transaction = (tdb->transaction != NULL);
/* we need to get a read lock on the transaction lock here to
cope with the lock ordering semantics of solaris10 */
if (tdb_transaction_lock(tdb, F_RDLCK)) {
return -1;
if (!in_transaction) {
if (tdb_transaction_lock(tdb, F_RDLCK)) {
return -1;
}
}
tdb->traverse_read++;
ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
tdb->traverse_read--;
tdb_transaction_unlock(tdb);
if (!in_transaction) {
tdb_transaction_unlock(tdb);
}
return ret;
}
@ -232,20 +237,25 @@ int tdb_traverse(struct tdb_context *tdb,
{
struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
int ret;
bool in_transaction = (tdb->transaction != NULL);
if (tdb->read_only || tdb->traverse_read) {
return tdb_traverse_read(tdb, fn, private_data);
}
if (tdb_transaction_lock(tdb, F_WRLCK)) {
return -1;
if (!in_transaction) {
if (tdb_transaction_lock(tdb, F_WRLCK)) {
return -1;
}
}
tdb->traverse_write++;
ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
tdb->traverse_write--;
tdb_transaction_unlock(tdb);
if (!in_transaction) {
tdb_transaction_unlock(tdb);
}
return ret;
}

View File

@ -376,7 +376,7 @@ _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
/**
return (tv1 - tv2) in microseconds
*/
_PUBLIC_ int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2)
_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
{
int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);

View File

@ -127,7 +127,7 @@ _PUBLIC_ NTTIME nttime_from_string(const char *s);
/**
return (tv1 - tv2) in microseconds
*/
_PUBLIC_ int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2);
_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2);
/**
return a zero timeval

View File

@ -650,7 +650,8 @@ NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
/****************************************************************************
Query disk space.
****************************************************************************/
NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *avail)
NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, uint32_t *bsize,
uint64_t *total, uint64_t *avail)
{
union smb_fsinfo fsinfo_parms;
TALLOC_CTX *mem_ctx;
@ -658,12 +659,12 @@ NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *a
mem_ctx = talloc_init("smbcli_dskattr");
fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
fsinfo_parms.dskattr.level = RAW_QFS_SIZE_INFO;
status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
if (NT_STATUS_IS_OK(status)) {
*bsize = fsinfo_parms.dskattr.out.block_size;
*total = fsinfo_parms.dskattr.out.units_total;
*avail = fsinfo_parms.dskattr.out.units_free;
*bsize = fsinfo_parms.size_info.out.bytes_per_sector * fsinfo_parms.size_info.out.sectors_per_unit;
*total = fsinfo_parms.size_info.out.total_alloc_units;
*avail = fsinfo_parms.size_info.out.avail_alloc_units;
}
talloc_free(mem_ctx);

View File

@ -69,6 +69,17 @@ _PUBLIC_ NTSTATUS composite_wait(struct composite_context *c)
return c->status;
}
/*
block until a composite function has completed, then return the status.
Free the composite context before returning
*/
_PUBLIC_ NTSTATUS composite_wait_free(struct composite_context *c)
{
NTSTATUS status = composite_wait(c);
talloc_free(c);
return status;
}
/*
callback from composite_done() and composite_error()
@ -94,6 +105,12 @@ static void composite_trigger(struct event_context *ev, struct timed_event *te,
_PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
{
/* you are allowed to pass NT_STATUS_OK to composite_error(), in which
case it is equivalent to composite_done() */
if (NT_STATUS_IS_OK(status)) {
composite_done(ctx);
return;
}
if (!ctx->used_wait && !ctx->async.fn) {
event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
}
@ -187,7 +204,7 @@ _PUBLIC_ void composite_continue_smb2(struct composite_context *ctx,
{
if (composite_nomem(new_req, ctx)) return;
new_req->async.fn = continuation;
new_req->async.private = private_data;
new_req->async.private_data = private_data;
}
_PUBLIC_ void composite_continue_nbt(struct composite_context *ctx,

View File

@ -101,6 +101,7 @@ bool composite_is_ok(struct composite_context *ctx);
void composite_done(struct composite_context *ctx);
void composite_error(struct composite_context *ctx, NTSTATUS status);
NTSTATUS composite_wait(struct composite_context *c);
NTSTATUS composite_wait_free(struct composite_context *c);
#endif /* __COMPOSITE_H__ */

View File

@ -33,7 +33,8 @@ LIBCLI_SMB_COMPOSITE_OBJ_FILES = $(addprefix $(libclisrcdir)/smb_composite/, \
sesssetup.o \
fetchfile.o \
appendacl.o \
fsinfo.o)
fsinfo.o \
smb2.o)
$(eval $(call proto_header_template,$(libclisrcdir)/smb_composite/proto.h,$(LIBCLI_SMB_COMPOSITE_OBJ_FILES:.o=.c)))

View File

@ -2354,10 +2354,11 @@ union smb_search_first {
#define SMB2_FIND_ID_BOTH_DIRECTORY_INFO 0x25
#define SMB2_FIND_ID_FULL_DIRECTORY_INFO 0x26
/* flags for RAW_FILEINFO_SMB2_ALL_EAS */
/* flags for SMB2 find */
#define SMB2_CONTINUE_FLAG_RESTART 0x01
#define SMB2_CONTINUE_FLAG_SINGLE 0x02
#define SMB2_CONTINUE_FLAG_NEW 0x10
#define SMB2_CONTINUE_FLAG_INDEX 0x04
#define SMB2_CONTINUE_FLAG_REOPEN 0x10
/* SMB2 Find */
struct smb2_find {
@ -2370,7 +2371,7 @@ union smb_search_first {
/* uint16_t buffer_code; 0x21 = 0x20 + 1 */
uint8_t level;
uint8_t continue_flags; /* SMB2_CONTINUE_FLAG_* */
uint32_t unknown; /* perhaps a continue token? */
uint32_t file_index;
/* struct smb2_handle handle; */
/* uint16_t pattern_ofs; */
/* uint16_t pattern_size; */

View File

@ -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)
lock.o notify.o cancel.o keepalive.o break.o util.o)
$(eval $(call proto_header_template,$(libclisrcdir)/smb2/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c)))

View File

@ -44,7 +44,7 @@ struct smb2_connect_state {
*/
static void continue_tcon(struct smb2_request *req)
{
struct composite_context *c = talloc_get_type(req->async.private,
struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_connect_state *state = talloc_get_type(c->private_data,
struct smb2_connect_state);
@ -83,7 +83,7 @@ static void continue_session(struct composite_context *creq)
if (composite_nomem(req, c)) return;
req->async.fn = continue_tcon;
req->async.private = c;
req->async.private_data = c;
}
/*
@ -91,7 +91,7 @@ static void continue_session(struct composite_context *creq)
*/
static void continue_negprot(struct smb2_request *req)
{
struct composite_context *c = talloc_get_type(req->async.private,
struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_connect_state *state = talloc_get_type(c->private_data,
struct smb2_connect_state);
@ -101,6 +101,9 @@ static void continue_negprot(struct smb2_request *req)
c->status = smb2_negprot_recv(req, c, &state->negprot);
if (!composite_is_ok(c)) return;
transport->negotiate.system_time = state->negprot.out.system_time;
transport->negotiate.server_start_time = state->negprot.out.server_start_time;
state->session = smb2_session_init(transport, global_loadparm, state, true);
if (composite_nomem(state->session, c)) return;
@ -142,7 +145,7 @@ static void continue_socket(struct composite_context *creq)
if (composite_nomem(req, c)) return;
req->async.fn = continue_negprot;
req->async.private = c;
req->async.private_data = c;
}

View File

@ -38,7 +38,7 @@ struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io
SCVAL(req->out.body, 0x02, io->in.level);
SCVAL(req->out.body, 0x03, io->in.continue_flags);
SIVAL(req->out.body, 0x04, io->in.unknown);
SIVAL(req->out.body, 0x04, io->in.file_index);
smb2_push_handle(req->out.body+0x08, &io->in.file.handle);
status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern);

View File

@ -43,6 +43,18 @@ void smb2_setup_bufinfo(struct smb2_request *req)
}
}
/* destroy a request structure */
static int smb2_request_destructor(struct smb2_request *req)
{
if (req->transport) {
/* remove it from the list of pending requests (a null op if
its not in the list) */
DLIST_REMOVE(req->transport->pending_recv, req);
}
return 0;
}
/*
initialise a smb2 request
*/
@ -122,6 +134,8 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_
SCVAL(req->out.dynamic, 0, 0);
}
talloc_set_destructor(req, smb2_request_destructor);
return req;
}
@ -154,18 +168,13 @@ NTSTATUS smb2_request_destroy(struct smb2_request *req)
_send() call fails completely */
if (!req) return NT_STATUS_UNSUCCESSFUL;
if (req->transport) {
/* remove it from the list of pending requests (a null op if
its not in the list) */
DLIST_REMOVE(req->transport->pending_recv, req);
}
if (req->state == SMB2_REQUEST_ERROR &&
NT_STATUS_IS_OK(req->status)) {
req->status = NT_STATUS_INTERNAL_ERROR;
status = NT_STATUS_INTERNAL_ERROR;
} else {
status = req->status;
}
status = req->status;
talloc_free(req);
return status;
}

View File

@ -145,7 +145,7 @@ struct smb2_session_state {
*/
static void session_request_handler(struct smb2_request *req)
{
struct composite_context *c = talloc_get_type(req->async.private,
struct composite_context *c = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_session_state *state = talloc_get_type(c->private_data,
struct smb2_session_state);
@ -178,7 +178,7 @@ static void session_request_handler(struct smb2_request *req)
}
state->req->async.fn = session_request_handler;
state->req->async.private = c;
state->req->async.private_data = c;
return;
}

View File

@ -19,6 +19,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LIBCLI_SMB2_SMB2_H__
#define __LIBCLI_SMB2_SMB2_H__
#include "libcli/raw/request.h"
struct smb2_handle;
@ -32,6 +35,8 @@ struct smb2_options {
*/
struct smb2_negotiate {
DATA_BLOB secblob;
NTTIME system_time;
NTTIME server_start_time;
};
/* this is the context for the smb2 transport layer */
@ -165,7 +170,7 @@ struct smb2_request {
*/
struct {
void (*fn)(struct smb2_request *);
void *private;
void *private_data;
} async;
};
@ -282,3 +287,5 @@ struct smb2_request {
return NT_STATUS_INVALID_PARAMETER; \
} \
} while (0)
#endif

200
source/libcli/smb2/util.c Normal file
View File

@ -0,0 +1,200 @@
/*
Unix SMB/CIFS implementation.
SMB2 client utility functions
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 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/raw/raw_proto.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
#include "libcli/smb_composite/smb_composite.h"
/*
simple close wrapper with SMB2
*/
NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
{
struct smb2_close c;
ZERO_STRUCT(c);
c.in.file.handle = h;
return smb2_close(tree, &c);
}
/*
unlink a file with SMB2
*/
NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
{
union smb_unlink io;
ZERO_STRUCT(io);
io.unlink.in.pattern = fname;
return smb2_composite_unlink(tree, &io);
}
/*
rmdir with SMB2
*/
NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname)
{
struct smb_rmdir io;
ZERO_STRUCT(io);
io.in.path = dname;
return smb2_composite_rmdir(tree, &io);
}
/*
mkdir with SMB2
*/
NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname)
{
union smb_mkdir io;
ZERO_STRUCT(io);
io.mkdir.level = RAW_MKDIR_MKDIR;
io.mkdir.in.path = dname;
return smb2_composite_mkdir(tree, &io);
}
/*
set file attribute with SMB2
*/
NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib)
{
union smb_setfileinfo io;
ZERO_STRUCT(io);
io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
io.basic_info.in.file.path = name;
io.basic_info.in.attrib = attrib;
return smb2_composite_setpathinfo(tree, &io);
}
/*
recursively descend a tree deleting all files
returns the number of files deleted, or -1 on error
*/
int smb2_deltree(struct smb2_tree *tree, const char *dname)
{
NTSTATUS status;
uint32_t total_deleted = 0;
uint_t count, i;
union smb_search_data *list;
TALLOC_CTX *tmp_ctx = talloc_new(tree);
struct smb2_find f;
struct smb2_create create_parm;
/* it might be a file */
status = smb2_util_unlink(tree, dname);
if (NT_STATUS_IS_OK(status)) {
talloc_free(tmp_ctx);
return 1;
}
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
talloc_free(tmp_ctx);
return 0;
}
ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
create_parm.in.fname = dname;
status = smb2_create(tree, tmp_ctx, &create_parm);
if (NT_STATUS_IS_ERR(status)) {
DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
talloc_free(tmp_ctx);
return -1;
}
ZERO_STRUCT(f);
f.in.file.handle = create_parm.out.file.handle;
f.in.max_response_size = 0x10000;
f.in.level = SMB2_FIND_NAME_INFO;
f.in.pattern = "*";
status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
if (NT_STATUS_IS_ERR(status)) {
DEBUG(2,("Failed to list %s - %s\n",
dname, nt_errstr(status)));
smb2_util_close(tree, create_parm.out.file.handle);
talloc_free(tmp_ctx);
return -1;
}
for (i=0;i<count;i++) {
char *name;
if (strcmp(".", list[i].name_info.name.s) == 0 ||
strcmp("..", list[i].name_info.name.s) == 0) {
continue;
}
name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
status = smb2_util_unlink(tree, name);
if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
/* it could be read-only */
status = smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
status = smb2_util_unlink(tree, name);
}
if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
int ret;
ret = smb2_deltree(tree, name);
if (ret > 0) total_deleted += ret;
}
talloc_free(name);
if (NT_STATUS_IS_OK(status)) {
total_deleted++;
}
}
smb2_util_close(tree, create_parm.out.file.handle);
status = smb2_util_rmdir(tree, dname);
if (NT_STATUS_IS_ERR(status)) {
DEBUG(2,("Failed to delete %s - %s\n",
dname, nt_errstr(status)));
talloc_free(tmp_ctx);
return -1;
}
talloc_free(tmp_ctx);
return total_deleted;
}

View File

@ -0,0 +1,371 @@
/*
Unix SMB/CIFS implementation.
Copyright (C) Andrew Tridgell 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/>.
*/
/*
a composite API for making SMB-like calls using SMB2. This is useful
as SMB2 often requires more than one requests where a single SMB
request would do. In converting code that uses SMB to use SMB2,
these routines make life a lot easier
*/
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/raw/raw_proto.h"
#include "libcli/composite/composite.h"
#include "libcli/smb_composite/smb_composite.h"
#include "param/param.h"
#include "libcli/smb2/smb2_calls.h"
/*
continue after a SMB2 close
*/
static void continue_close(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
NTSTATUS status;
struct smb2_close close_parm;
status = smb2_close_recv(req, &close_parm);
composite_error(ctx, status);
}
/*
continue after the create in a composite unlink
*/
static void continue_unlink(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_tree *tree = req->tree;
struct smb2_create create_parm;
struct smb2_close close_parm;
NTSTATUS status;
status = smb2_create_recv(req, ctx, &create_parm);
if (!NT_STATUS_IS_OK(status)) {
composite_error(ctx, status);
return;
}
ZERO_STRUCT(close_parm);
close_parm.in.file.handle = create_parm.out.file.handle;
req = smb2_close_send(tree, &close_parm);
composite_continue_smb2(ctx, req, continue_close, ctx);
}
/*
composite SMB2 unlink call
*/
struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
union smb_unlink *io)
{
struct composite_context *ctx;
struct smb2_create create_parm;
struct smb2_request *req;
ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
if (ctx == NULL) return NULL;
/* check for wildcards - we could support these with a
search, but for now they aren't necessary */
if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
composite_error(ctx, NT_STATUS_NOT_SUPPORTED);
return ctx;
}
ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_STD_DELETE;
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE|
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
create_parm.in.create_options =
NTCREATEX_OPTIONS_DELETE_ON_CLOSE |
NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
create_parm.in.fname = io->unlink.in.pattern;
if (create_parm.in.fname[0] == '\\') {
create_parm.in.fname++;
}
req = smb2_create_send(tree, &create_parm);
composite_continue_smb2(ctx, req, continue_unlink, ctx);
return ctx;
}
/*
composite unlink call - sync interface
*/
NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
{
struct composite_context *c = smb2_composite_unlink_send(tree, io);
return composite_wait_free(c);
}
/*
continue after the create in a composite mkdir
*/
static void continue_mkdir(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_tree *tree = req->tree;
struct smb2_create create_parm;
struct smb2_close close_parm;
NTSTATUS status;
status = smb2_create_recv(req, ctx, &create_parm);
if (!NT_STATUS_IS_OK(status)) {
composite_error(ctx, status);
return;
}
ZERO_STRUCT(close_parm);
close_parm.in.file.handle = create_parm.out.file.handle;
req = smb2_close_send(tree, &close_parm);
composite_continue_smb2(ctx, req, continue_close, ctx);
}
/*
composite SMB2 mkdir call
*/
struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree,
union smb_mkdir *io)
{
struct composite_context *ctx;
struct smb2_create create_parm;
struct smb2_request *req;
ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
if (ctx == NULL) return NULL;
ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
create_parm.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
create_parm.in.create_disposition = NTCREATEX_DISP_CREATE;
create_parm.in.fname = io->mkdir.in.path;
if (create_parm.in.fname[0] == '\\') {
create_parm.in.fname++;
}
req = smb2_create_send(tree, &create_parm);
composite_continue_smb2(ctx, req, continue_mkdir, ctx);
return ctx;
}
/*
composite mkdir call - sync interface
*/
NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
{
struct composite_context *c = smb2_composite_mkdir_send(tree, io);
return composite_wait_free(c);
}
/*
continue after the create in a composite rmdir
*/
static void continue_rmdir(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_tree *tree = req->tree;
struct smb2_create create_parm;
struct smb2_close close_parm;
NTSTATUS status;
status = smb2_create_recv(req, ctx, &create_parm);
if (!NT_STATUS_IS_OK(status)) {
composite_error(ctx, status);
return;
}
ZERO_STRUCT(close_parm);
close_parm.in.file.handle = create_parm.out.file.handle;
req = smb2_close_send(tree, &close_parm);
composite_continue_smb2(ctx, req, continue_close, ctx);
}
/*
composite SMB2 rmdir call
*/
struct composite_context *smb2_composite_rmdir_send(struct smb2_tree *tree,
struct smb_rmdir *io)
{
struct composite_context *ctx;
struct smb2_create create_parm;
struct smb2_request *req;
ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
if (ctx == NULL) return NULL;
ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_STD_DELETE;
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE|
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
create_parm.in.create_options =
NTCREATEX_OPTIONS_DIRECTORY |
NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
create_parm.in.fname = io->in.path;
if (create_parm.in.fname[0] == '\\') {
create_parm.in.fname++;
}
req = smb2_create_send(tree, &create_parm);
composite_continue_smb2(ctx, req, continue_rmdir, ctx);
return ctx;
}
/*
composite rmdir call - sync interface
*/
NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io)
{
struct composite_context *c = smb2_composite_rmdir_send(tree, io);
return composite_wait_free(c);
}
/*
continue after the setfileinfo in a composite setpathinfo
*/
static void continue_setpathinfo_close(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_tree *tree = req->tree;
struct smb2_close close_parm;
NTSTATUS status;
union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
union smb_setfileinfo);
status = smb2_setinfo_recv(req);
if (!NT_STATUS_IS_OK(status)) {
composite_error(ctx, status);
return;
}
ZERO_STRUCT(close_parm);
close_parm.in.file.handle = io2->generic.in.file.handle;
req = smb2_close_send(tree, &close_parm);
composite_continue_smb2(ctx, req, continue_close, ctx);
}
/*
continue after the create in a composite setpathinfo
*/
static void continue_setpathinfo(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_tree *tree = req->tree;
struct smb2_create create_parm;
NTSTATUS status;
union smb_setfileinfo *io2 = talloc_get_type(ctx->private_data,
union smb_setfileinfo);
status = smb2_create_recv(req, ctx, &create_parm);
if (!NT_STATUS_IS_OK(status)) {
composite_error(ctx, status);
return;
}
io2->generic.in.file.handle = create_parm.out.file.handle;
req = smb2_setinfo_file_send(tree, io2);
composite_continue_smb2(ctx, req, continue_setpathinfo_close, ctx);
}
/*
composite SMB2 setpathinfo call
*/
struct composite_context *smb2_composite_setpathinfo_send(struct smb2_tree *tree,
union smb_setfileinfo *io)
{
struct composite_context *ctx;
struct smb2_create create_parm;
struct smb2_request *req;
union smb_setfileinfo *io2;
ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
if (ctx == NULL) return NULL;
ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE|
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
create_parm.in.create_options = 0;
create_parm.in.fname = io->generic.in.file.path;
if (create_parm.in.fname[0] == '\\') {
create_parm.in.fname++;
}
req = smb2_create_send(tree, &create_parm);
io2 = talloc(ctx, union smb_setfileinfo);
if (composite_nomem(io2, ctx)) {
return ctx;
}
*io2 = *io;
ctx->private_data = io2;
composite_continue_smb2(ctx, req, continue_setpathinfo, ctx);
return ctx;
}
/*
composite setpathinfo call
*/
NTSTATUS smb2_composite_setpathinfo(struct smb2_tree *tree, union smb_setfileinfo *io)
{
struct composite_context *c = smb2_composite_setpathinfo_send(tree, io);
return composite_wait_free(c);
}

View File

@ -29,6 +29,7 @@
#include "libcli/raw/signing.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/smb2/smb2.h"
/*

View File

@ -83,7 +83,7 @@ static void smb2_read_callback(struct smb2_request *req)
uint16_t frag_length;
NTSTATUS status;
state = talloc_get_type(req->async.private, struct smb2_read_state);
state = talloc_get_type(req->async.private_data, struct smb2_read_state);
smb = talloc_get_type(state->c->transport.private_data, struct smb2_private);
status = smb2_read_recv(req, state, &io);
@ -136,7 +136,7 @@ static void smb2_read_callback(struct smb2_request *req)
}
req->async.fn = smb2_read_callback;
req->async.private = state;
req->async.private_data = state;
}
@ -180,7 +180,7 @@ static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLO
}
req->async.fn = smb2_read_callback;
req->async.private = state;
req->async.private_data = state;
return NT_STATUS_OK;
}
@ -212,7 +212,7 @@ struct smb2_trans_state {
*/
static void smb2_trans_callback(struct smb2_request *req)
{
struct smb2_trans_state *state = talloc_get_type(req->async.private,
struct smb2_trans_state *state = talloc_get_type(req->async.private_data,
struct smb2_trans_state);
struct dcerpc_connection *c = state->c;
NTSTATUS status;
@ -269,7 +269,7 @@ static NTSTATUS smb2_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *
}
req->async.fn = smb2_trans_callback;
req->async.private = state;
req->async.private_data = state;
talloc_steal(state, req);
@ -281,7 +281,7 @@ static NTSTATUS smb2_send_trans_request(struct dcerpc_connection *c, DATA_BLOB *
*/
static void smb2_write_callback(struct smb2_request *req)
{
struct dcerpc_connection *c = (struct dcerpc_connection *)req->async.private;
struct dcerpc_connection *c = (struct dcerpc_connection *)req->async.private_data;
if (!NT_STATUS_IS_OK(req->status)) {
DEBUG(0,("dcerpc_smb2: write callback error\n"));
@ -319,7 +319,7 @@ static NTSTATUS smb2_send_request(struct dcerpc_connection *c, DATA_BLOB *blob,
}
req->async.fn = smb2_write_callback;
req->async.private = c;
req->async.private_data = c;
return NT_STATUS_OK;
}
@ -444,7 +444,7 @@ struct composite_context *dcerpc_pipe_open_smb2_send(struct dcerpc_pipe *p,
static void pipe_open_recv(struct smb2_request *req)
{
struct pipe_open_smb2_state *state =
talloc_get_type(req->async.private,
talloc_get_type(req->async.private_data,
struct pipe_open_smb2_state);
struct composite_context *ctx = state->ctx;
struct dcerpc_connection *c = state->c;

View File

@ -84,8 +84,6 @@ static void getdc_recv_netlogon_reply(struct dgram_mailslot_handler *dgmslot,
goto done;
}
status = NT_STATUS_NO_LOGON_SERVERS;
p = netlogon.samlogon.nt4.server;
DEBUG(10, ("NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, "
@ -102,6 +100,8 @@ static void getdc_recv_netlogon_reply(struct dgram_mailslot_handler *dgmslot,
goto done;
}
status = NT_STATUS_OK;
done:
irpc_send_reply(s->msg, status);
}

View File

@ -16,6 +16,20 @@ PRIVATE_DEPENDENCIES = \
ntvfs_cifs_OBJ_FILES = $(ntvfssrcdir)/cifs/vfs_cifs.o
################################################
# Start MODULE ntvfs_smb2
[MODULE::ntvfs_smb2]
INIT_FUNCTION = ntvfs_smb2_init
SUBSYSTEM = ntvfs
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB LIBCLI_RAW
# End MODULE ntvfs_smb2
################################################
ntvfs_smb2_OBJ_FILES = ntvfs/smb2/vfs_smb2.o
################################################
# Start MODULE ntvfs_simple
[MODULE::ntvfs_simple]

View File

@ -205,6 +205,7 @@ NTSTATUS ntvfs_init(struct loadparm_context *lp_ctx)
static bool initialized = false;
extern NTSTATUS ntvfs_posix_init(void);
extern NTSTATUS ntvfs_cifs_init(void);
extern NTSTATUS ntvfs_smb2_init(void);
extern NTSTATUS ntvfs_nbench_init(void);
extern NTSTATUS ntvfs_unixuid_init(void);
extern NTSTATUS ntvfs_ipc_init(void);

View File

@ -1117,6 +1117,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
return status;
}
/* if the client specified that it must not be a directory then
check that it isn't */
if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
(io->generic.in.create_options & NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
/* if the client specified that it must be a directory then
check that it is */
if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
(io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
return NT_STATUS_NOT_A_DIRECTORY;
}
/* directory opens are handled separately */
if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) ||
(io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {

View File

@ -0,0 +1,844 @@
/*
Unix SMB/CIFS implementation.
CIFS-to-SMB2 NTVFS filesystem backend
Copyright (C) Andrew Tridgell 2008
largely based on vfs_cifs.c which was
Copyright (C) Andrew Tridgell 2003
Copyright (C) James J Myers 2003 <myersjj@samba.org>
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/>.
*/
/*
this implements a CIFS->CIFS NTVFS filesystem backend.
*/
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/raw/raw_proto.h"
#include "libcli/composite/composite.h"
#include "libcli/smb_composite/smb_composite.h"
#include "auth/auth.h"
#include "auth/credentials/credentials.h"
#include "ntvfs/ntvfs.h"
#include "lib/util/dlinklist.h"
#include "param/param.h"
#include "libcli/resolve/resolve.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
struct cvfs_file {
struct cvfs_file *prev, *next;
uint16_t fnum;
struct ntvfs_handle *h;
};
/* this is stored in ntvfs_private */
struct cvfs_private {
struct smb2_tree *tree;
struct smb2_transport *transport;
struct ntvfs_module_context *ntvfs;
struct async_info *pending;
struct cvfs_file *files;
/* a handle on the root of the share */
/* TODO: leaving this handle open could prevent other users
from opening the share with exclusive access. We probably
need to open it on demand */
struct smb2_handle roothandle;
};
/* a structure used to pass information to an async handler */
struct async_info {
struct async_info *next, *prev;
struct cvfs_private *cvfs;
struct ntvfs_request *req;
void *c_req;
struct composite_context *c_comp;
struct cvfs_file *f;
void *parms;
};
#define SETUP_FILE_HERE(f) do { \
f = ntvfs_handle_get_backend_data(io->generic.in.file.ntvfs, ntvfs); \
if (!f) return NT_STATUS_INVALID_HANDLE; \
io->generic.in.file.fnum = f->fnum; \
} while (0)
#define SETUP_FILE do { \
struct cvfs_file *f; \
SETUP_FILE_HERE(f); \
} while (0)
#define SMB2_SERVER "smb2:server"
#define SMB2_USER "smb2:user"
#define SMB2_PASSWORD "smb2:password"
#define SMB2_DOMAIN "smb2:domain"
#define SMB2_SHARE "smb2:share"
#define SMB2_USE_MACHINE_ACCT "smb2:use-machine-account"
#define SMB2_USE_MACHINE_ACCT_DEFAULT false
/*
a handler for oplock break events from the server - these need to be passed
along to the client
*/
static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *p_private)
{
struct cvfs_private *private = p_private;
NTSTATUS status;
struct ntvfs_handle *h = NULL;
struct cvfs_file *f;
for (f=private->files; f; f=f->next) {
if (f->fnum != fnum) continue;
h = f->h;
break;
}
if (!h) {
DEBUG(5,("vfs_smb2: ignoring oplock break level %d for fnum %d\n", level, fnum));
return true;
}
DEBUG(5,("vfs_smb2: sending oplock break level %d for fnum %d\n", level, fnum));
status = ntvfs_send_oplock_break(private->ntvfs, h, level);
if (!NT_STATUS_IS_OK(status)) return false;
return true;
}
/*
return a handle to the root of the share
*/
static NTSTATUS smb2_get_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
{
struct smb2_create io;
NTSTATUS status;
ZERO_STRUCT(io);
io.in.oplock_level = 0;
io.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
io.in.file_attributes = 0;
io.in.create_disposition = NTCREATEX_DISP_OPEN;
io.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE|
NTCREATEX_SHARE_ACCESS_DELETE;
io.in.create_options = 0;
io.in.fname = NULL;
status = smb2_create(tree, tree, &io);
NT_STATUS_NOT_OK_RETURN(status);
*handle = io.out.file.handle;
return NT_STATUS_OK;
}
/*
connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, const char *sharename)
{
NTSTATUS status;
struct cvfs_private *private;
const char *host, *user, *pass, *domain, *remote_share;
struct composite_context *creq;
struct share_config *scfg = ntvfs->ctx->config;
struct smb2_tree *tree;
struct cli_credentials *credentials;
bool machine_account;
/* Here we need to determine which server to connect to.
* For now we use parametric options, type cifs.
* Later we will use security=server and auth_server.c.
*/
host = share_string_option(scfg, SMB2_SERVER, NULL);
user = share_string_option(scfg, SMB2_USER, NULL);
pass = share_string_option(scfg, SMB2_PASSWORD, NULL);
domain = share_string_option(scfg, SMB2_DOMAIN, NULL);
remote_share = share_string_option(scfg, SMB2_SHARE, NULL);
if (!remote_share) {
remote_share = sharename;
}
machine_account = share_bool_option(scfg, SMB2_USE_MACHINE_ACCT, SMB2_USE_MACHINE_ACCT_DEFAULT);
private = talloc_zero(ntvfs, struct cvfs_private);
if (!private) {
return NT_STATUS_NO_MEMORY;
}
ntvfs->private_data = private;
if (!host) {
DEBUG(1,("CIFS backend: You must supply server\n"));
return NT_STATUS_INVALID_PARAMETER;
}
if (user && pass) {
DEBUG(5, ("CIFS backend: Using specified password\n"));
credentials = cli_credentials_init(private);
if (!credentials) {
return NT_STATUS_NO_MEMORY;
}
cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
if (domain) {
cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
}
cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
} else if (machine_account) {
DEBUG(5, ("CIFS backend: Using machine account\n"));
credentials = cli_credentials_init(private);
cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
if (domain) {
cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
}
status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
} else if (req->session_info->credentials) {
DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
credentials = req->session_info->credentials;
} else {
DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
return NT_STATUS_INVALID_PARAMETER;
}
creq = smb2_connect_send(private, host, remote_share,
lp_resolve_context(ntvfs->ctx->lp_ctx),
credentials,
ntvfs->ctx->event_ctx);
status = smb2_connect_recv(creq, private, &tree);
NT_STATUS_NOT_OK_RETURN(status);
status = smb2_get_roothandle(tree, &private->roothandle);
NT_STATUS_NOT_OK_RETURN(status);
private->tree = tree;
private->transport = private->tree->session->transport;
private->ntvfs = ntvfs;
ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
/* we need to receive oplock break requests from the server */
/* TODO: enable oplocks
smbcli_oplock_handler(private->transport, oplock_handler, private);
*/
return NT_STATUS_OK;
}
/*
disconnect from a share
*/
static NTSTATUS cvfs_disconnect(struct ntvfs_module_context *ntvfs)
{
struct cvfs_private *private = ntvfs->private_data;
struct async_info *a, *an;
/* first cleanup pending requests */
for (a=private->pending; a; a = an) {
an = a->next;
talloc_free(a->c_req);
talloc_free(a);
}
talloc_free(private);
ntvfs->private_data = NULL;
return NT_STATUS_OK;
}
/*
destroy an async info structure
*/
static int async_info_destructor(struct async_info *async)
{
DLIST_REMOVE(async->cvfs->pending, async);
return 0;
}
/*
a handler for simple async SMB2 replies
this handler can only be used for functions that don't return any
parameters (those that just return a status code)
*/
static void async_simple_smb2(struct smb2_request *c_req)
{
struct async_info *async = c_req->async.private_data;
struct ntvfs_request *req = async->req;
smb2_request_receive(c_req);
req->async_states->status = smb2_request_destroy(c_req);
talloc_free(async);
req->async_states->send_fn(req);
}
/*
a handler for simple async composite replies
this handler can only be used for functions that don't return any
parameters (those that just return a status code)
*/
static void async_simple_composite(struct composite_context *c_req)
{
struct async_info *async = c_req->async.private_data;
struct ntvfs_request *req = async->req;
req->async_states->status = composite_wait_free(c_req);
talloc_free(async);
req->async_states->send_fn(req);
}
/* save some typing for the simple functions */
#define ASYNC_RECV_TAIL_F(io, async_fn, file) do { \
if (!c_req) return NT_STATUS_UNSUCCESSFUL; \
{ \
struct async_info *async; \
async = talloc(req, struct async_info); \
if (!async) return NT_STATUS_NO_MEMORY; \
async->parms = io; \
async->req = req; \
async->f = file; \
async->cvfs = private; \
async->c_req = c_req; \
DLIST_ADD(private->pending, async); \
c_req->async.private_data = async; \
talloc_set_destructor(async, async_info_destructor); \
} \
c_req->async.fn = async_fn; \
req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; \
return NT_STATUS_OK; \
} while (0)
#define ASYNC_RECV_TAIL(io, async_fn) ASYNC_RECV_TAIL_F(io, async_fn, NULL)
#define SIMPLE_ASYNC_TAIL ASYNC_RECV_TAIL(NULL, async_simple_smb2)
#define SIMPLE_COMPOSITE_TAIL ASYNC_RECV_TAIL(NULL, async_simple_composite)
#define CHECK_ASYNC(req) do { \
if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { \
DEBUG(0,("SMB2 proxy backend does not support sync operation at %s\n", \
__location__)); \
return NT_STATUS_NOT_IMPLEMENTED; \
}} while (0)
/*
delete a file - the dirtype specifies the file types to include in the search.
The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
BUGS:
- doesn't handle wildcards
- doesn't obey attrib restrictions
*/
static NTSTATUS cvfs_unlink(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_unlink *unl)
{
struct cvfs_private *private = ntvfs->private_data;
struct composite_context *c_req;
CHECK_ASYNC(req);
c_req = smb2_composite_unlink_send(private->tree, unl);
SIMPLE_COMPOSITE_TAIL;
}
/*
ioctl interface
*/
static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_ioctl *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
check if a directory exists
*/
static NTSTATUS cvfs_chkpath(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_chkpath *cp)
{
struct cvfs_private *private = ntvfs->private_data;
struct smb2_request *c_req;
struct smb2_find f;
CHECK_ASYNC(req);
/* SMB2 doesn't have a chkpath operation, and also doesn't
have a query path info call, so the best seems to be to do a
find call, using the roothandle we established at connect
time */
ZERO_STRUCT(f);
f.in.file.handle = private->roothandle;
f.in.level = SMB2_FIND_DIRECTORY_INFO;
f.in.pattern = cp->chkpath.in.path;
/* SMB2 find doesn't accept \ or the empty string - this is the best
approximation */
if (strcmp(f.in.pattern, "\\") == 0 ||
strcmp(f.in.pattern, "") == 0) {
f.in.pattern = "?";
}
f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE | SMB2_CONTINUE_FLAG_RESTART;
f.in.max_response_size = 0x1000;
c_req = smb2_find_send(private->tree, &f);
SIMPLE_ASYNC_TAIL;
}
/*
return info on a pathname
*/
static NTSTATUS cvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_fileinfo *info)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
query info on a open file
*/
static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_fileinfo *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
set info on a pathname
*/
static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_setfileinfo *st)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
open a file
*/
static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_open *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
create a directory
*/
static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_mkdir *md)
{
struct cvfs_private *private = ntvfs->private_data;
struct composite_context *c_req;
CHECK_ASYNC(req);
c_req = smb2_composite_mkdir_send(private->tree, md);
SIMPLE_COMPOSITE_TAIL;
}
/*
remove a directory
*/
static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, struct smb_rmdir *rd)
{
struct cvfs_private *private = ntvfs->private_data;
struct composite_context *c_req;
CHECK_ASYNC(req);
c_req = smb2_composite_rmdir_send(private->tree, rd);
SIMPLE_COMPOSITE_TAIL;
}
/*
rename a set of files
*/
static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_rename *ren)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
copy a set of files
*/
static NTSTATUS cvfs_copy(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, struct smb_copy *cp)
{
return NT_STATUS_NOT_SUPPORTED;
}
/*
read from a file
*/
static NTSTATUS cvfs_read(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_read *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
write to a file
*/
static NTSTATUS cvfs_write(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_write *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
seek in a file
*/
static NTSTATUS cvfs_seek(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_seek *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
flush a file
*/
static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_flush *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
close a file
*/
static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_close *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
exit - closing files open by the pid
*/
static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
logoff - closing files open by the user
*/
static NTSTATUS cvfs_logoff(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req)
{
/* we can't do this right in the cifs backend .... */
return NT_STATUS_OK;
}
/*
setup for an async call - nothing to do yet
*/
static NTSTATUS cvfs_async_setup(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
void *private)
{
return NT_STATUS_OK;
}
/*
cancel an async call
*/
static NTSTATUS cvfs_cancel(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
lock a byte range
*/
static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_lock *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
set info on a open file
*/
static NTSTATUS cvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_setfileinfo *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
a handler for async fsinfo replies
*/
static void async_fsinfo(struct smb2_request *c_req)
{
struct async_info *async = c_req->async.private_data;
struct ntvfs_request *req = async->req;
req->async_states->status = smb2_getinfo_fs_recv(c_req, req, async->parms);
talloc_free(async);
req->async_states->send_fn(req);
}
/*
return filesystem space info
*/
static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_fsinfo *fs)
{
struct cvfs_private *private = ntvfs->private_data;
struct smb2_request *c_req;
enum smb_fsinfo_level level = fs->generic.level;
CHECK_ASYNC(req);
switch (level) {
/* some levels go straight through */
case RAW_QFS_VOLUME_INFORMATION:
case RAW_QFS_SIZE_INFORMATION:
case RAW_QFS_DEVICE_INFORMATION:
case RAW_QFS_ATTRIBUTE_INFORMATION:
case RAW_QFS_QUOTA_INFORMATION:
case RAW_QFS_FULL_SIZE_INFORMATION:
case RAW_QFS_OBJECTID_INFORMATION:
break;
/* some get mapped */
case RAW_QFS_VOLUME_INFO:
level = RAW_QFS_VOLUME_INFORMATION;
break;
case RAW_QFS_SIZE_INFO:
level = RAW_QFS_SIZE_INFORMATION;
break;
case RAW_QFS_DEVICE_INFO:
level = RAW_QFS_DEVICE_INFORMATION;
break;
case RAW_QFS_ATTRIBUTE_INFO:
level = RAW_QFS_ATTRIBUTE_INFO;
break;
default:
/* the rest get refused for now */
DEBUG(0,("fsinfo level %u not possible on SMB2\n",
(unsigned)fs->generic.level));
break;
}
fs->generic.level = level;
fs->generic.handle = private->roothandle;
c_req = smb2_getinfo_fs_send(private->tree, fs);
ASYNC_RECV_TAIL(fs, async_fsinfo);
}
/*
return print queue info
*/
static NTSTATUS cvfs_lpq(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_lpq *lpq)
{
return NT_STATUS_NOT_SUPPORTED;
}
/*
list files in a directory matching a wildcard pattern
*/
static NTSTATUS cvfs_search_first(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_search_first *io,
void *search_private,
bool (*callback)(void *, const union smb_search_data *))
{
struct cvfs_private *private = ntvfs->private_data;
struct smb2_find f;
enum smb_search_data_level smb2_level;
uint_t count, i;
union smb_search_data *data;
NTSTATUS status;
if (io->generic.level != RAW_SEARCH_TRANS2) {
DEBUG(0,("We only support trans2 search in smb2 backend\n"));
return NT_STATUS_NOT_SUPPORTED;
}
switch (io->generic.data_level) {
case RAW_SEARCH_DATA_DIRECTORY_INFO:
smb2_level = SMB2_FIND_DIRECTORY_INFO;
break;
case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
smb2_level = SMB2_FIND_FULL_DIRECTORY_INFO;
break;
case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
smb2_level = SMB2_FIND_BOTH_DIRECTORY_INFO;
break;
case RAW_SEARCH_DATA_NAME_INFO:
smb2_level = SMB2_FIND_NAME_INFO;
break;
case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
smb2_level = SMB2_FIND_ID_FULL_DIRECTORY_INFO;
break;
case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
smb2_level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
break;
default:
DEBUG(0,("Unsupported search level %u for smb2 backend\n",
(unsigned)io->generic.data_level));
return NT_STATUS_INVALID_INFO_CLASS;
}
/* we do the search on the roothandle. This only works because
search is synchronous, otherwise we'd have no way to
distinguish multiple searches happening at once
*/
ZERO_STRUCT(f);
f.in.file.handle = private->roothandle;
f.in.level = smb2_level;
f.in.pattern = io->t2ffirst.in.pattern;
while (f.in.pattern[0] == '\\') {
f.in.pattern++;
}
f.in.continue_flags = 0;
f.in.max_response_size = 0x10000;
status = smb2_find_level(private->tree, req, &f, &count, &data);
NT_STATUS_NOT_OK_RETURN(status);
for (i=0;i<count;i++) {
if (!callback(search_private, &data[i])) break;
}
io->t2ffirst.out.handle = 0;
io->t2ffirst.out.count = i;
/* TODO: fix end_of_file */
io->t2ffirst.out.end_of_search = 1;
talloc_free(data);
return NT_STATUS_OK;
}
/* continue a search */
static NTSTATUS cvfs_search_next(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_search_next *io,
void *search_private,
bool (*callback)(void *, const union smb_search_data *))
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/* close a search */
static NTSTATUS cvfs_search_close(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req, union smb_search_close *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/* SMBtrans - not used on file shares */
static NTSTATUS cvfs_trans(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
struct smb_trans2 *trans2)
{
return NT_STATUS_ACCESS_DENIED;
}
/* change notify request - always async */
static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs,
struct ntvfs_request *req,
union smb_notify *io)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
initialise the CIFS->CIFS backend, registering ourselves with the ntvfs subsystem
*/
NTSTATUS ntvfs_smb2_init(void)
{
NTSTATUS ret;
struct ntvfs_ops ops;
NTVFS_CURRENT_CRITICAL_SIZES(vers);
ZERO_STRUCT(ops);
/* fill in the name and type */
ops.name = "smb2";
ops.type = NTVFS_DISK;
/* fill in all the operations */
ops.connect = cvfs_connect;
ops.disconnect = cvfs_disconnect;
ops.unlink = cvfs_unlink;
ops.chkpath = cvfs_chkpath;
ops.qpathinfo = cvfs_qpathinfo;
ops.setpathinfo = cvfs_setpathinfo;
ops.open = cvfs_open;
ops.mkdir = cvfs_mkdir;
ops.rmdir = cvfs_rmdir;
ops.rename = cvfs_rename;
ops.copy = cvfs_copy;
ops.ioctl = cvfs_ioctl;
ops.read = cvfs_read;
ops.write = cvfs_write;
ops.seek = cvfs_seek;
ops.flush = cvfs_flush;
ops.close = cvfs_close;
ops.exit = cvfs_exit;
ops.lock = cvfs_lock;
ops.setfileinfo = cvfs_setfileinfo;
ops.qfileinfo = cvfs_qfileinfo;
ops.fsinfo = cvfs_fsinfo;
ops.lpq = cvfs_lpq;
ops.search_first = cvfs_search_first;
ops.search_next = cvfs_search_next;
ops.search_close = cvfs_search_close;
ops.trans = cvfs_trans;
ops.logoff = cvfs_logoff;
ops.async_setup = cvfs_async_setup;
ops.cancel = cvfs_cancel;
ops.notify = cvfs_notify;
/* register ourselves with the NTVFS subsystem. We register
under the name 'smb2'. */
ret = ntvfs_register(&ops, &vers);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(0,("Failed to register SMB2 backend\n"));
}
return ret;
}

View File

@ -508,7 +508,8 @@ static void switch_message(int type, struct smbsrv_request *req)
}
}
DEBUG(5,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->server_id.id));
DEBUG(5,("switch message %s (task_id %u)\n",
smb_fn_name(type), (unsigned)req->smb_conn->connection->server_id.id));
/* this must be called before we do any reply */
if (flags & SIGNING_NO_REPLY) {

View File

@ -112,7 +112,7 @@ static NTSTATUS smb2srv_find_backend(struct smb2srv_find_state *state)
return NT_STATUS_FOOBAR;
}
if (info->in.continue_flags & SMB2_CONTINUE_FLAG_NEW) {
if (info->in.continue_flags & SMB2_CONTINUE_FLAG_REOPEN) {
state->ff = talloc(state, union smb_search_first);
NT_STATUS_HAVE_NO_MEMORY(state->ff);
@ -156,7 +156,7 @@ void smb2srv_find_recv(struct smb2srv_request *req)
info->data_level = RAW_SEARCH_DATA_GENERIC;/* will be overwritten later */
info->in.level = CVAL(req->in.body, 0x02);
info->in.continue_flags = CVAL(req->in.body, 0x03);
info->in.unknown = IVAL(req->in.body, 0x04);
info->in.file_index = IVAL(req->in.body, 0x04);
info->in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08);
SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, info, req->in.body+0x18, &info->in.pattern));
info->in.max_response_size = IVAL(req->in.body, 0x1C);

View File

@ -70,6 +70,7 @@ TORTURE_RAW_OBJ_FILES = $(addprefix $(torturesrcdir)/raw/, \
pingpong.o \
lockbench.o \
lookuprate.o \
tconrate.o \
openbench.o \
rename.o \
eas.o \
@ -261,6 +262,23 @@ 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

View File

@ -35,6 +35,8 @@ NTSTATUS torture_raw_init(void)
torture_suite_add_simple_test(suite, "BENCH-OPEN", torture_bench_open);
torture_suite_add_simple_test(suite, "BENCH-LOOKUP",
torture_bench_lookup);
torture_suite_add_simple_test(suite, "BENCH-TCON",
torture_bench_treeconnect);
torture_suite_add_simple_test(suite, "OFFLINE", torture_test_offline);
torture_suite_add_1smb_test(suite, "QFSINFO", torture_raw_qfsinfo);
torture_suite_add_1smb_test(suite, "QFILEINFO", torture_raw_qfileinfo);

View File

@ -0,0 +1,201 @@
/*
SMB tree connection rate test
Copyright (C) 2006-2007 James Peach
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/libcli.h"
#include "libcli/resolve/resolve.h"
#include "torture/smbtorture.h"
#include "lib/cmdline/popt_common.h"
#include "param/param.h"
#include "system/filesys.h"
#include "system/shmem.h"
#define TIME_LIMIT_SECS 30
#define usec_to_sec(s) ((s) / 1000000)
#define sec_to_usec(s) ((s) * 1000000)
/* Map a shared memory buffer of at least nelem counters. */
static void * map_count_buffer(unsigned nelem, size_t elemsz)
{
void * buf;
size_t bufsz;
size_t pagesz = getpagesize();
bufsz = nelem * elemsz;
bufsz = (bufsz + pagesz) % pagesz; /* round up to pagesz */
#ifdef MAP_ANON
/* BSD */
buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
-1 /* fd */, 0 /* offset */);
#else
buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
open("/dev/zero", O_RDWR), 0 /* offset */);
#endif
if (buf == MAP_FAILED) {
printf("failed to map count buffer: %s\n",
strerror(errno));
return NULL;
}
return buf;
}
static int fork_tcon_client(struct torture_context *tctx,
int *tcon_count, unsigned tcon_timelimit,
const char *host, const char *share)
{
pid_t child;
struct smbcli_state *cli;
struct timeval end;
struct timeval now;
struct smbcli_options options;
lp_smbcli_options(tctx->lp_ctx, &options);
child = fork();
if (child == -1) {
printf("failed to fork child: %s\n,", strerror(errno));
return -1;
} else if (child != 0) {
/* Parent, just return. */
return 0;
}
/* Child. Just make as many connections as possible within the
* time limit. Don't bother synchronising the child start times
* because it's probably not work the effort, and a bit of startup
* jitter is probably a more realistic test.
*/
end = timeval_current();
now = timeval_current();
end.tv_sec += tcon_timelimit;
*tcon_count = 0;
while (timeval_compare(&now, &end) == -1) {
NTSTATUS status;
status = smbcli_full_connection(NULL, &cli,
host, lp_smb_ports(tctx->lp_ctx), share,
NULL, cmdline_credentials,
lp_resolve_context(tctx->lp_ctx),
tctx->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
printf("failed to connect to //%s/%s: %s\n",
host, share, nt_errstr(status));
goto done;
}
smbcli_tdis(cli);
*tcon_count = *tcon_count + 1;
now = timeval_current();
}
done:
exit(0);
}
static bool children_remain(void)
{
/* Reap as many children as possible. */
for (;;) {
pid_t ret = waitpid(-1, NULL, WNOHANG);
if (ret == 0) {
/* no children ready */
return true;
}
if (ret == -1) {
/* no children left. maybe */
return errno == ECHILD ? false : true;
}
}
/* notreached */
return false;
}
static double rate_convert_secs(unsigned count,
const struct timeval *start, const struct timeval *end)
{
return (double)count /
usec_to_sec((double)usec_time_diff(end, start));
}
/* Test the rate at which the server will accept connections. */
bool torture_bench_treeconnect(struct torture_context *tctx)
{
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = torture_setting_string(tctx, "share", NULL);
int timelimit = torture_setting_int(tctx, "timelimit",
TIME_LIMIT_SECS);
int nprocs = torture_setting_int(tctx, "nprocs", 4);
int *curr_counts = map_count_buffer(nprocs, sizeof(int));
int *last_counts = talloc_array(NULL, int, nprocs);
struct timeval now, last, start;
int i, delta;
torture_assert(tctx, nprocs > 0, "bad proc count");
torture_assert(tctx, timelimit > 0, "bad timelimit");
torture_assert(tctx, curr_counts, "allocation failure");
torture_assert(tctx, last_counts, "allocation failure");
start = last = timeval_current();
for (i = 0; i < nprocs; ++i) {
fork_tcon_client(tctx, &curr_counts[i], timelimit, host, share);
}
while (children_remain()) {
sleep(1);
now = timeval_current();
for (i = 0, delta = 0; i < nprocs; ++i) {
delta += curr_counts[i] - last_counts[i];
}
printf("%u connections/sec\n",
(unsigned)rate_convert_secs(delta, &last, &now));
memcpy(last_counts, curr_counts, nprocs * sizeof(int));
last = timeval_current();
}
now = timeval_current();
for (i = 0, delta = 0; i < nprocs; ++i) {
delta += curr_counts[i];
}
printf("TOTAL: %u connections/sec over %u secs\n",
(unsigned)rate_convert_secs(delta, &start, &now),
timelimit);
return true;
}
/* vim: set sts=8 sw=8 : */

View File

@ -738,6 +738,70 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture)
}
torture_assert_ntstatus_ok(torture, s->error, "Failed establish a connect");
/*
* Change the workstation password after establishing the netlogon
* schannel connections to prove that existing connections are not
* affected by a wks pwchange.
*/
{
struct netr_ServerPasswordSet pwset;
char *password = generate_random_str(s->join_ctx1, 8);
struct creds_CredentialState *creds_state;
struct dcerpc_pipe *net_pipe;
status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
&ndr_table_netlogon,
s->wks_creds1,
torture->ev, torture->lp_ctx);
torture_assert_ntstatus_ok(torture, status,
"dcerpc_pipe_connect_b failed");
pwset.in.server_name = talloc_asprintf(
net_pipe, "\\\\%s", dcerpc_server_name(net_pipe));
pwset.in.computer_name =
cli_credentials_get_workstation(s->wks_creds1);
pwset.in.account_name = talloc_asprintf(
net_pipe, "%s$", pwset.in.computer_name);
pwset.in.secure_channel_type = SEC_CHAN_WKSTA;
E_md4hash(password, pwset.in.new_password.hash);
creds_state = cli_credentials_get_netlogon_creds(
s->wks_creds1);
creds_des_encrypt(creds_state, &pwset.in.new_password);
creds_client_authenticator(creds_state, &pwset.in.credential);
status = dcerpc_netr_ServerPasswordSet(net_pipe, torture, &pwset);
torture_assert_ntstatus_ok(torture, status,
"ServerPasswordSet failed");
if (!creds_client_check(creds_state,
&pwset.out.return_authenticator.cred)) {
printf("Credential chaining failed\n");
}
cli_credentials_set_password(s->wks_creds1, password,
CRED_SPECIFIED);
talloc_free(net_pipe);
/* Just as a test, connect with the new creds */
talloc_free(s->wks_creds1->netlogon_creds);
s->wks_creds1->netlogon_creds = NULL;
status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
&ndr_table_netlogon,
s->wks_creds1,
torture->ev, torture->lp_ctx);
torture_assert_ntstatus_ok(torture, status,
"dcerpc_pipe_connect_b failed");
talloc_free(net_pipe);
}
torture_comment(torture, "Start looping LogonSamLogonEx on %d connections for %d secs\n",
s->nprocs, s->timelimit);
for (i=0; i < s->nprocs; i++) {

View File

@ -99,7 +99,7 @@ static bool torture_oplock_handler(struct smb2_transport *transport,
req = smb2_break_send(tree, &break_info.br);
req->async.fn = torture_oplock_break_callback;
req->async.private = NULL;
req->async.private_data = NULL;
return true;
}

View File

@ -22,6 +22,7 @@
#include "includes.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
#include "libcli/smb_composite/smb_composite.h"
#include "lib/cmdline/popt_common.h"
#include "lib/events/events.h"
#include "system/time.h"
@ -33,47 +34,6 @@
#include "torture/smb2/proto.h"
/*
close a handle with SMB2
*/
NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
{
struct smb2_close c;
ZERO_STRUCT(c);
c.in.file.handle = h;
return smb2_close(tree, &c);
}
/*
unlink a file with SMB2
*/
NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
{
struct smb2_create io;
NTSTATUS status;
ZERO_STRUCT(io);
io.in.desired_access = SEC_RIGHTS_FILE_ALL;
io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
io.in.create_disposition = NTCREATEX_DISP_OPEN;
io.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE|
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE;
io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
io.in.fname = fname;
status = smb2_create(tree, tree, &io);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
return NT_STATUS_OK;
}
NT_STATUS_NOT_OK_RETURN(status);
return smb2_util_close(tree, io.out.file.handle);
}
/*
write to a file on SMB2
*/