mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r15018: Merge Volker's ipc/trans2/nttrans changes over
into 3.0. Also merge the new POSIX lock code - this is not enabled unless -DDEVELOPER is defined. This doesn't yet map onto underlying system POSIX locks. Updates vfs to allow lock queries. Jeremy.
This commit is contained in:
parent
b1bbe56831
commit
08e52ead03
@ -7,7 +7,7 @@ INSTALLCMD = @INSTALL@
|
||||
SAMBA_SOURCE = @SAMBA_SOURCE@
|
||||
SHLIBEXT = @SHLIBEXT@
|
||||
OBJEXT = @OBJEXT@
|
||||
FLAGS = $(CFLAGS) -Iinclude -I$(SAMBA_SOURCE)/include -I$(SAMBA_SOURCE)/popt -I$(SAMBA_SOURCE)/ubiqx -I$(SAMBA_SOURCE)/smbwrapper -I. $(CPPFLAGS) -I$(SAMBA_SOURCE) -fPIC
|
||||
FLAGS = $(CFLAGS) -Iinclude -I$(SAMBA_SOURCE)/include -I$(SAMBA_SOURCE)/popt -I$(SAMBA_SOURCE)/smbwrapper -I. $(CPPFLAGS) -I$(SAMBA_SOURCE) -fPIC
|
||||
|
||||
|
||||
prefix = @prefix@
|
||||
|
@ -226,6 +226,11 @@ static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int
|
||||
return vfswrap_lock(NULL, fsp, fd, op, offset, count, type);
|
||||
}
|
||||
|
||||
static BOOL skel_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
return vfswrap_getlock(NULL, fsp, fd, poffset, pcount, ptype, ppid);
|
||||
}
|
||||
|
||||
static int skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
|
||||
{
|
||||
return vfswrap_symlink(NULL, conn, oldpath, newpath);
|
||||
@ -576,6 +581,7 @@ static vfs_op_tuple skel_op_tuples[] = {
|
||||
{SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_OPAQUE},
|
||||
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_OPAQUE},
|
||||
|
@ -225,6 +225,11 @@ static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int
|
||||
return SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type);
|
||||
}
|
||||
|
||||
static BOOL skel_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
return SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid);
|
||||
}
|
||||
|
||||
static int skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
|
||||
{
|
||||
return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
|
||||
@ -543,6 +548,7 @@ static vfs_op_tuple skel_op_tuples[] = {
|
||||
{SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
|
||||
|
@ -486,6 +486,36 @@ typedef struct {
|
||||
BOOL is_wild;
|
||||
} name_compare_entry;
|
||||
|
||||
struct trans_state {
|
||||
struct trans_state *next, *prev;
|
||||
uint16 vuid;
|
||||
uint16 mid;
|
||||
|
||||
uint32 max_param_return;
|
||||
uint32 max_data_return;
|
||||
uint32 max_setup_return;
|
||||
|
||||
uint8 cmd; /* SMBtrans or SMBtrans2 */
|
||||
|
||||
fstring name; /* for trans requests */
|
||||
uint16 call; /* for trans2 and nttrans requests */
|
||||
|
||||
BOOL close_on_completion;
|
||||
BOOL one_way;
|
||||
|
||||
unsigned int setup_count;
|
||||
uint16 *setup;
|
||||
|
||||
size_t received_data;
|
||||
size_t received_param;
|
||||
|
||||
size_t total_param;
|
||||
char *param;
|
||||
|
||||
size_t total_data;
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* Include VFS stuff */
|
||||
|
||||
#include "smb_acls.h"
|
||||
@ -550,6 +580,7 @@ typedef struct connection_struct {
|
||||
name_compare_entry *veto_oplock_list; /* Per-share list of files to refuse oplocks on. */
|
||||
name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */
|
||||
struct dfree_cached_info *dfree_info;
|
||||
struct trans_state *pending_trans;
|
||||
} connection_struct;
|
||||
|
||||
struct current_user {
|
||||
@ -799,17 +830,29 @@ struct parm_struct {
|
||||
#define FLAG_HIDE 0x2000 /* options that should be hidden in SWAT */
|
||||
#define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
|
||||
|
||||
/* passed to br lock code */
|
||||
enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK};
|
||||
/* passed to br lock code - the UNLOCK_LOCK should never be stored into the tdb
|
||||
and is used in calculating POSIX unlock ranges only. */
|
||||
|
||||
enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK, UNLOCK_LOCK};
|
||||
enum brl_flavour {WINDOWS_LOCK = 0, POSIX_LOCK = 1};
|
||||
|
||||
struct byte_range_lock {
|
||||
files_struct *fsp;
|
||||
unsigned int num_locks;
|
||||
BOOL modified;
|
||||
void *lock_data;
|
||||
};
|
||||
|
||||
#define BRLOCK_FN_CAST() \
|
||||
void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
|
||||
enum brl_type lock_type, \
|
||||
enum brl_flavour lock_flav, \
|
||||
br_off start, br_off size)
|
||||
|
||||
#define BRLOCK_FN(fn) \
|
||||
void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
|
||||
enum brl_type lock_type, \
|
||||
enum brl_flavour lock_flav, \
|
||||
br_off start, br_off size)
|
||||
|
||||
struct bitmap {
|
||||
|
@ -110,6 +110,8 @@ struct profile_stats {
|
||||
unsigned syscall_ftruncate_time;
|
||||
unsigned syscall_fcntl_lock_count;
|
||||
unsigned syscall_fcntl_lock_time;
|
||||
unsigned syscall_fcntl_getlock_count;
|
||||
unsigned syscall_fcntl_getlock_time;
|
||||
unsigned syscall_readlink_count;
|
||||
unsigned syscall_readlink_time;
|
||||
unsigned syscall_symlink_count;
|
||||
|
@ -441,7 +441,9 @@ Offset Size Name
|
||||
#define SMB_QUERY_ATTR_FLAGS 0x206 /* chflags, chattr */
|
||||
#define SMB_SET_ATTR_FLAGS 0x206
|
||||
#define SMB_QUERY_POSIX_PERMISSION 0x207
|
||||
/* Only valid for qfileinfo */
|
||||
#define SMB_QUERY_POSIX_LOCK 0x208
|
||||
/* Only valid for setfileinfo */
|
||||
#define SMB_SET_POSIX_LOCK 0x208
|
||||
|
||||
/* Transact 2 Find First levels */
|
||||
@ -576,4 +578,28 @@ number of entries sent will be zero.
|
||||
#define SMB_POSIX_ACL_ENTRY_SIZE 10
|
||||
|
||||
#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF
|
||||
|
||||
/* Definition of SMB_SET_POSIX_LOCK */
|
||||
/*
|
||||
[2 bytes] lock_type - 0 = Read, 1 = Write, 2 = Unlock
|
||||
[2 bytes] lock_flags - 1 = Wait (only valid for setlock)
|
||||
[4 bytes] pid = locking context.
|
||||
[8 bytes] start = unsigned 64 bits.
|
||||
[8 bytes] length = unsigned 64 bits.
|
||||
*/
|
||||
|
||||
#define POSIX_LOCK_TYPE_OFFSET 0
|
||||
#define POSIX_LOCK_FLAGS_OFFSET 2
|
||||
#define POSIX_LOCK_PID_OFFSET 4
|
||||
#define POSIX_LOCK_START_OFFSET 8
|
||||
#define POSIX_LOCK_LEN_OFFSET 16
|
||||
#define POSIX_LOCK_DATA_SIZE 24
|
||||
|
||||
#define POSIX_LOCK_FLAG_NOWAIT 0
|
||||
#define POSIX_LOCK_FLAG_WAIT 1
|
||||
|
||||
#define POSIX_LOCK_TYPE_READ 0
|
||||
#define POSIX_LOCK_TYPE_WRITE 1
|
||||
#define POSIX_LOCK_TYPE_UNLOCK 2
|
||||
|
||||
#endif
|
||||
|
@ -59,9 +59,10 @@
|
||||
/* Changed to version 12 to add mask and attributes to opendir(). JRA
|
||||
Also include aio calls. JRA. */
|
||||
/* Changed to version 13 as the internal structure of files_struct has changed. JRA */
|
||||
/* Changed to version 14 as the we had to change DIR to SMB_STRUCT_DIR. JRA */
|
||||
/* Changed to version 15 as the we added the statvfs call. JRA */
|
||||
#define SMB_VFS_INTERFACE_VERSION 15
|
||||
/* Changed to version 14 as we had to change DIR to SMB_STRUCT_DIR. JRA */
|
||||
/* Changed to version 15 as we added the statvfs call. JRA */
|
||||
/* Changed to version 16 as we added the getlock call. JRA */
|
||||
#define SMB_VFS_INTERFACE_VERSION 16
|
||||
|
||||
|
||||
/* to bug old modules which are trying to compile with the old functions */
|
||||
@ -141,6 +142,7 @@ typedef enum _vfs_op_type {
|
||||
SMB_VFS_OP_UTIME,
|
||||
SMB_VFS_OP_FTRUNCATE,
|
||||
SMB_VFS_OP_LOCK,
|
||||
SMB_VFS_OP_GETLOCK,
|
||||
SMB_VFS_OP_SYMLINK,
|
||||
SMB_VFS_OP_READLINK,
|
||||
SMB_VFS_OP_LINK,
|
||||
@ -262,6 +264,7 @@ struct vfs_ops {
|
||||
int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times);
|
||||
int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
|
||||
BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
|
||||
BOOL (*getlock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
|
||||
int (*symlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
|
||||
int (*readlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *buf, size_t bufsiz);
|
||||
int (*link)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath);
|
||||
@ -375,6 +378,7 @@ struct vfs_ops {
|
||||
struct vfs_handle_struct *utime;
|
||||
struct vfs_handle_struct *ftruncate;
|
||||
struct vfs_handle_struct *lock;
|
||||
struct vfs_handle_struct *getlock;
|
||||
struct vfs_handle_struct *symlink;
|
||||
struct vfs_handle_struct *readlink;
|
||||
struct vfs_handle_struct *link;
|
||||
|
@ -70,6 +70,7 @@
|
||||
#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times)))
|
||||
#define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
|
||||
#define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
|
||||
#define SMB_VFS_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs.ops.getlock((fsp)->conn->vfs.handles.getlock, (fsp), (fd) ,(poffset), (pcount), (ptype), (ppid)))
|
||||
#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (conn), (oldpath), (newpath)))
|
||||
#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (conn), (path), (buf), (bufsiz)))
|
||||
#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (conn), (oldpath), (newpath)))
|
||||
@ -181,6 +182,7 @@
|
||||
#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times)))
|
||||
#define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
|
||||
#define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
|
||||
#define SMB_VFS_OPAQUE_GETLOCK(fsp, fd, poffset, pcount, ptype, ppid) ((fsp)->conn->vfs_opaque.ops.getlock((fsp)->conn->vfs_opaque.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
|
||||
#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (conn), (oldpath), (newpath)))
|
||||
#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (conn), (path), (buf), (bufsiz)))
|
||||
#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (conn), (oldpath), (newpath)))
|
||||
@ -293,6 +295,7 @@
|
||||
#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times)))
|
||||
#define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
|
||||
#define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
|
||||
#define SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid) ((handle)->vfs_next.ops.getlock((handle)->vfs_next.handles.getlock, (fsp), (fd), (poffset), (pcount), (ptype), (ppid)))
|
||||
#define SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (conn), (oldpath), (newpath)))
|
||||
#define SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (conn), (path), (buf), (bufsiz)))
|
||||
#define SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (conn), (oldpath), (newpath)))
|
||||
|
@ -1876,6 +1876,7 @@ void free_namearray(name_compare_entry *name_array)
|
||||
/****************************************************************************
|
||||
Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
|
||||
is dealt with in posix.c
|
||||
Returns True if the lock was granted, False otherwise.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
|
||||
@ -1893,34 +1894,54 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
|
||||
|
||||
ret = sys_fcntl_ptr(fd,op,&lock);
|
||||
|
||||
if (ret == -1 && errno != 0)
|
||||
DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
|
||||
|
||||
/* a lock query - return True if this region is locked, False if not locked. */
|
||||
if (op == SMB_F_GETLK) {
|
||||
if ((ret != -1) &&
|
||||
(lock.l_type != F_UNLCK) &&
|
||||
(lock.l_pid != 0) &&
|
||||
(lock.l_pid != sys_getpid())) {
|
||||
DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
|
||||
return(True);
|
||||
}
|
||||
|
||||
/* it must be not locked or locked by me */
|
||||
return(False);
|
||||
}
|
||||
|
||||
/* a lock set or unset */
|
||||
if (ret == -1) {
|
||||
DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
|
||||
(double)offset,(double)count,op,type,strerror(errno)));
|
||||
return(False);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* everything went OK */
|
||||
DEBUG(8,("fcntl_lock: Lock call successful\n"));
|
||||
|
||||
return(True);
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
|
||||
is dealt with in posix.c
|
||||
Returns True if we have information regarding this lock region (and returns
|
||||
F_UNLCK in *ptype if the region is unlocked). False if the call failed.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
SMB_STRUCT_FLOCK lock;
|
||||
int ret;
|
||||
|
||||
DEBUG(8,("fcntl_getlock %d %.0f %.0f %d\n",fd,(double)*poffset,(double)*pcount,*ptype));
|
||||
|
||||
lock.l_type = *ptype;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = *poffset;
|
||||
lock.l_len = *pcount;
|
||||
lock.l_pid = 0;
|
||||
|
||||
ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
|
||||
|
||||
if (ret == -1) {
|
||||
DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
|
||||
(double)*poffset,(double)*pcount,*ptype,strerror(errno)));
|
||||
return False;
|
||||
}
|
||||
|
||||
*ptype = lock.l_type;
|
||||
*poffset = lock.l_start;
|
||||
*pcount = lock.l_len;
|
||||
*ppid = lock.l_pid;
|
||||
|
||||
DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
|
||||
fd, (int)lock.l_type, (unsigned int)lock.l_pid));
|
||||
return True;
|
||||
}
|
||||
|
||||
#undef DBGC_CLASS
|
||||
|
@ -816,6 +816,7 @@ BOOL cli_close(struct cli_state *cli, int fnum)
|
||||
send a lock with a specified locktype
|
||||
this is used for testing LOCKING_ANDX_CANCEL_LOCK
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
|
||||
uint32 offset, uint32 len, int timeout, unsigned char locktype)
|
||||
{
|
||||
@ -863,11 +864,11 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
|
||||
return cli_nt_error(cli);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Lock a file.
|
||||
note that timeout is in units of 2 milliseconds
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_lock(struct cli_state *cli, int fnum,
|
||||
uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
|
||||
{
|
||||
@ -1068,6 +1069,108 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Get/unlock a POSIX lock on a file - internal function.
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL cli_posix_lock_internal(struct cli_state *cli, int fnum,
|
||||
SMB_BIG_UINT offset, SMB_BIG_UINT len, BOOL wait_lock, enum brl_type lock_type)
|
||||
{
|
||||
unsigned int param_len = 4;
|
||||
unsigned int data_len = POSIX_LOCK_DATA_SIZE;
|
||||
uint16 setup = TRANSACT2_SETFILEINFO;
|
||||
char param[4];
|
||||
unsigned char data[POSIX_LOCK_DATA_SIZE];
|
||||
char *rparam=NULL, *rdata=NULL;
|
||||
int saved_timeout = cli->timeout;
|
||||
|
||||
SSVAL(param,0,fnum);
|
||||
SSVAL(param,2,SMB_SET_POSIX_LOCK);
|
||||
|
||||
switch (lock_type) {
|
||||
case READ_LOCK:
|
||||
SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
|
||||
break;
|
||||
case WRITE_LOCK:
|
||||
SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
|
||||
break;
|
||||
case UNLOCK_LOCK:
|
||||
SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
|
||||
break;
|
||||
default:
|
||||
return False;
|
||||
}
|
||||
|
||||
if (wait_lock) {
|
||||
SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
|
||||
cli->timeout = 0x7FFFFFFF;
|
||||
} else {
|
||||
SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
|
||||
}
|
||||
|
||||
SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
|
||||
SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
|
||||
SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
|
||||
|
||||
if (!cli_send_trans(cli, SMBtrans2,
|
||||
NULL, /* name */
|
||||
-1, 0, /* fid, flags */
|
||||
&setup, 1, 0, /* setup, length, max */
|
||||
param, param_len, 2, /* param, length, max */
|
||||
(char *)&data, data_len, cli->max_xmit /* data, length, max */
|
||||
)) {
|
||||
cli->timeout = saved_timeout;
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!cli_receive_trans(cli, SMBtrans2,
|
||||
&rparam, ¶m_len,
|
||||
&rdata, &data_len)) {
|
||||
cli->timeout = saved_timeout;
|
||||
SAFE_FREE(rdata);
|
||||
SAFE_FREE(rparam);
|
||||
return False;
|
||||
}
|
||||
|
||||
cli->timeout = saved_timeout;
|
||||
|
||||
SAFE_FREE(rdata);
|
||||
SAFE_FREE(rparam);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
POSIX Lock a file.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_posix_lock(struct cli_state *cli, int fnum,
|
||||
SMB_BIG_UINT offset, SMB_BIG_UINT len,
|
||||
BOOL wait_lock, enum brl_type lock_type)
|
||||
{
|
||||
if (lock_type != READ_LOCK || lock_type != WRITE_LOCK) {
|
||||
return False;
|
||||
}
|
||||
return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
POSIX Unlock a file.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
|
||||
{
|
||||
return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
POSIX Get any lock covering a file.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Do a SMBgetattrE call.
|
||||
|
@ -153,7 +153,6 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
|
||||
/* Note we're in a trans state. Save the sequence
|
||||
* numbers for replies. */
|
||||
|
||||
cli_signing_trans_start(cli, mid);
|
||||
return(True);
|
||||
}
|
||||
|
||||
@ -173,7 +172,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
*data_len = *param_len = 0;
|
||||
|
||||
if (!cli_receive_smb(cli)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -184,7 +182,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
DEBUG(0,("Expected %s response, got command 0x%02x\n",
|
||||
trans==SMBtrans?"SMBtrans":"SMBtrans2",
|
||||
CVAL(cli->inbuf,smb_com)));
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
|
||||
@ -197,7 +194,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
status = cli_nt_error(cli);
|
||||
|
||||
if (NT_STATUS_IS_ERR(status) || NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -210,7 +206,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
*data = SMB_REALLOC(*data,total_data);
|
||||
if (!(*data)) {
|
||||
DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -219,7 +214,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
*param = SMB_REALLOC(*param,total_param);
|
||||
if (!(*param)) {
|
||||
DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -231,7 +225,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
if (this_data + *data_len > total_data ||
|
||||
this_param + *param_len > total_param) {
|
||||
DEBUG(1,("Data overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -240,7 +233,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
this_param + *param_len < this_param ||
|
||||
this_param + *param_len < *param_len) {
|
||||
DEBUG(1,("Data overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -253,7 +245,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
data_offset_out + this_data < data_offset_out ||
|
||||
data_offset_out + this_data < this_data) {
|
||||
DEBUG(1,("Data overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
if (data_offset_in > cli->bufsize ||
|
||||
@ -261,7 +252,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
data_offset_in + this_data < data_offset_in ||
|
||||
data_offset_in + this_data < this_data) {
|
||||
DEBUG(1,("Data overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -276,7 +266,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
param_offset_out + this_param < param_offset_out ||
|
||||
param_offset_out + this_param < this_param) {
|
||||
DEBUG(1,("Param overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
if (param_offset_in > cli->bufsize ||
|
||||
@ -284,7 +273,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
param_offset_in + this_param < param_offset_in ||
|
||||
param_offset_in + this_param < this_param) {
|
||||
DEBUG(1,("Param overflow in cli_receive_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -297,7 +285,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
break;
|
||||
|
||||
if (!cli_receive_smb(cli)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -308,11 +295,9 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
DEBUG(0,("Expected %s response, got command 0x%02x\n",
|
||||
trans==SMBtrans?"SMBtrans":"SMBtrans2",
|
||||
CVAL(cli->inbuf,smb_com)));
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
|
||||
@ -326,8 +311,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
cli_signing_trans_stop(cli);
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
@ -453,7 +437,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
|
||||
/* Note we're in a trans state. Save the sequence
|
||||
* numbers for replies. */
|
||||
|
||||
cli_signing_trans_start(cli, mid);
|
||||
return(True);
|
||||
}
|
||||
|
||||
@ -474,7 +457,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
*data_len = *param_len = 0;
|
||||
|
||||
if (!cli_receive_smb(cli)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -484,7 +466,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
|
||||
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
|
||||
CVAL(cli->inbuf,smb_com)));
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
|
||||
@ -496,7 +477,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (cli_is_dos_error(cli)) {
|
||||
cli_dos_error(cli, &eclass, &ecode);
|
||||
if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
@ -507,7 +487,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (cli_is_nt_error(cli)) {
|
||||
if (!NT_STATUS_EQUAL(cli_nt_error(cli),
|
||||
NT_STATUS_BUFFER_TOO_SMALL)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
@ -521,7 +500,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
*data = SMB_REALLOC(*data,total_data);
|
||||
if (!(*data)) {
|
||||
DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -530,7 +508,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
*param = SMB_REALLOC(*param,total_param);
|
||||
if (!(*param)) {
|
||||
DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
@ -542,7 +519,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (this_data + *data_len > total_data ||
|
||||
this_param + *param_len > total_param) {
|
||||
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -551,7 +527,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
this_param + *param_len < this_param ||
|
||||
this_param + *param_len < *param_len) {
|
||||
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -564,7 +539,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
data_offset_out + this_data < data_offset_out ||
|
||||
data_offset_out + this_data < this_data) {
|
||||
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
if (data_offset_in > cli->bufsize ||
|
||||
@ -572,7 +546,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
data_offset_in + this_data < data_offset_in ||
|
||||
data_offset_in + this_data < this_data) {
|
||||
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -588,7 +561,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
param_offset_out + this_param < param_offset_out ||
|
||||
param_offset_out + this_param < this_param) {
|
||||
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
if (param_offset_in > cli->bufsize ||
|
||||
@ -596,7 +568,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
param_offset_in + this_param < param_offset_in ||
|
||||
param_offset_in + this_param < this_param) {
|
||||
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -610,7 +581,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
break;
|
||||
|
||||
if (!cli_receive_smb(cli)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -620,13 +590,11 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
|
||||
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
|
||||
CVAL(cli->inbuf,smb_com)));
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
if (cli_is_dos_error(cli)) {
|
||||
cli_dos_error(cli, &eclass, &ecode);
|
||||
if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
@ -636,7 +604,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (cli_is_nt_error(cli)) {
|
||||
if (!NT_STATUS_EQUAL(cli_nt_error(cli),
|
||||
NT_STATUS_BUFFER_TOO_SMALL)) {
|
||||
cli_signing_trans_stop(cli);
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
@ -650,7 +617,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
||||
if (total_data <= *data_len && total_param <= *param_len)
|
||||
break;
|
||||
}
|
||||
|
||||
cli_signing_trans_stop(cli);
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ static const struct {
|
||||
{ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE},
|
||||
{ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED},
|
||||
{ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE},
|
||||
{ERRDOS, 124, NT_STATUS_INVALID_LEVEL},
|
||||
{ERRDOS, ERRunknownlevel, NT_STATUS_INVALID_LEVEL},
|
||||
{ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE},
|
||||
{ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
|
||||
{ERRDOS, 109, NT_STATUS_PIPE_BROKEN},
|
||||
@ -680,7 +680,7 @@ static const struct {
|
||||
{ERRDOS, 121, NT_STATUS_IO_TIMEOUT},
|
||||
{ERRDOS, 122, NT_STATUS_BUFFER_TOO_SMALL},
|
||||
{ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID},
|
||||
{ERRDOS, 124, NT_STATUS_INVALID_LEVEL},
|
||||
{ERRDOS, ERRunknownlevel, NT_STATUS_INVALID_LEVEL},
|
||||
{ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND},
|
||||
{ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND},
|
||||
{ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY},
|
||||
|
@ -28,17 +28,9 @@ struct outstanding_packet_lookup {
|
||||
struct outstanding_packet_lookup *prev, *next;
|
||||
};
|
||||
|
||||
/* Store the data for an ongoing trans/trans2/nttrans operation. */
|
||||
struct trans_info_context {
|
||||
uint16 mid;
|
||||
uint32 send_seq_num;
|
||||
uint32 reply_seq_num;
|
||||
};
|
||||
|
||||
struct smb_basic_signing_context {
|
||||
DATA_BLOB mac_key;
|
||||
uint32 send_seq_num;
|
||||
struct trans_info_context *trans_info;
|
||||
struct outstanding_packet_lookup *outstanding_packet_list;
|
||||
};
|
||||
|
||||
@ -315,7 +307,6 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
{
|
||||
unsigned char calc_md5_mac[16];
|
||||
struct smb_basic_signing_context *data = si->signing_context;
|
||||
uint32 send_seq_num;
|
||||
|
||||
if (!si->doing_signing)
|
||||
return;
|
||||
@ -330,12 +321,8 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
/* mark the packet as signed - BEFORE we sign it...*/
|
||||
mark_packet_signed(outbuf);
|
||||
|
||||
if (data->trans_info)
|
||||
send_seq_num = data->trans_info->send_seq_num;
|
||||
else
|
||||
send_seq_num = data->send_seq_num;
|
||||
|
||||
simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
|
||||
simple_packet_signature(data, (const unsigned char *)outbuf,
|
||||
data->send_seq_num, calc_md5_mac);
|
||||
|
||||
DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
|
||||
dump_data(10, (const char *)calc_md5_mac, 8);
|
||||
@ -345,13 +332,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
/* cli->outbuf[smb_ss_field+2]=0;
|
||||
Uncomment this to test if the remote server actually verifies signatures...*/
|
||||
|
||||
if (data->trans_info)
|
||||
return;
|
||||
|
||||
data->send_seq_num++;
|
||||
store_sequence_for_reply(&data->outstanding_packet_list,
|
||||
SVAL(outbuf,smb_mid), data->send_seq_num);
|
||||
data->send_seq_num++;
|
||||
data->send_seq_num += 2;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
@ -362,7 +343,6 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
|
||||
{
|
||||
BOOL good;
|
||||
uint32 reply_seq_number;
|
||||
uint32 saved_seq;
|
||||
unsigned char calc_md5_mac[16];
|
||||
unsigned char *server_sent_mac;
|
||||
|
||||
@ -376,17 +356,9 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
|
||||
return False;
|
||||
}
|
||||
|
||||
if (data->trans_info) {
|
||||
reply_seq_number = data->trans_info->reply_seq_num;
|
||||
} else if (!get_sequence_for_reply(&data->outstanding_packet_list,
|
||||
SVAL(inbuf, smb_mid), &reply_seq_number)) {
|
||||
DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
|
||||
(unsigned int) SVAL(inbuf, smb_mid) ));
|
||||
return False;
|
||||
}
|
||||
|
||||
saved_seq = reply_seq_number;
|
||||
simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
|
||||
reply_seq_number = data->send_seq_num - 1;
|
||||
simple_packet_signature(data, (const unsigned char *)inbuf,
|
||||
reply_seq_number, calc_md5_mac);
|
||||
|
||||
server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
|
||||
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
|
||||
@ -400,12 +372,11 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
|
||||
#if 1 /* JRATEST */
|
||||
{
|
||||
int i;
|
||||
reply_seq_number -= 5;
|
||||
for (i = 0; i < 10; i++, reply_seq_number++) {
|
||||
simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
|
||||
for (i = -5; i < 5; i++) {
|
||||
simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number+i, calc_md5_mac);
|
||||
if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
|
||||
DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
|
||||
We were expecting seq %u\n", reply_seq_number, saved_seq ));
|
||||
We were expecting seq %u\n", reply_seq_number+i, reply_seq_number ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -416,7 +387,7 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
|
||||
DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
|
||||
dump_data(10, (const char *)server_sent_mac, 8);
|
||||
}
|
||||
return signing_good(inbuf, si, good, saved_seq, must_be_ok);
|
||||
return signing_good(inbuf, si, good, reply_seq_number, must_be_ok);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
@ -437,10 +408,6 @@ static void simple_free_signing_context(struct smb_sign_info *si)
|
||||
|
||||
data_blob_free(&data->mac_key);
|
||||
|
||||
if (data->trans_info) {
|
||||
SAFE_FREE(data->trans_info);
|
||||
}
|
||||
|
||||
SAFE_FREE(si->signing_context);
|
||||
|
||||
return;
|
||||
@ -502,65 +469,6 @@ BOOL cli_simple_set_signing(struct cli_state *cli,
|
||||
return True;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Tell client code we are in a multiple trans reply state.
|
||||
We call this after the last outgoing trans2 packet (which
|
||||
has incremented the sequence numbers), so we must save the
|
||||
current mid and sequence number -2.
|
||||
************************************************************/
|
||||
|
||||
void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
|
||||
{
|
||||
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
|
||||
uint32 reply_seq_num;
|
||||
|
||||
if (!cli->sign_info.doing_signing || !data)
|
||||
return;
|
||||
|
||||
data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
|
||||
ZERO_STRUCTP(data->trans_info);
|
||||
|
||||
/* This ensures the sequence is pulled off the outstanding packet list */
|
||||
if (!get_sequence_for_reply(&data->outstanding_packet_list,
|
||||
mid, &reply_seq_num)) {
|
||||
DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
data->trans_info->send_seq_num = reply_seq_num - 1;
|
||||
data->trans_info->mid = mid;
|
||||
data->trans_info->reply_seq_num = reply_seq_num;
|
||||
|
||||
DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
|
||||
data->send_seq_num = %u\n",
|
||||
(unsigned int)data->trans_info->mid,
|
||||
(unsigned int)data->trans_info->reply_seq_num,
|
||||
(unsigned int)data->trans_info->send_seq_num,
|
||||
(unsigned int)data->send_seq_num ));
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Tell client code we are out of a multiple trans reply state.
|
||||
************************************************************/
|
||||
|
||||
void cli_signing_trans_stop(struct cli_state *cli)
|
||||
{
|
||||
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
|
||||
|
||||
if (!cli->sign_info.doing_signing || !data)
|
||||
return;
|
||||
|
||||
DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
|
||||
data->send_seq_num = %u\n",
|
||||
(unsigned int)data->trans_info->mid,
|
||||
(unsigned int)data->trans_info->reply_seq_num,
|
||||
(unsigned int)data->trans_info->send_seq_num,
|
||||
(unsigned int)data->send_seq_num ));
|
||||
|
||||
SAFE_FREE(data->trans_info);
|
||||
data->trans_info = NULL;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
SMB signing - TEMP implementation - calculate a MAC to send.
|
||||
************************************************************/
|
||||
@ -659,8 +567,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
{
|
||||
unsigned char calc_md5_mac[16];
|
||||
struct smb_basic_signing_context *data = si->signing_context;
|
||||
uint32 send_seq_number = data->send_seq_num;
|
||||
BOOL was_deferred_packet = False;
|
||||
uint32 send_seq_number = data->send_seq_num-1;
|
||||
uint16 mid;
|
||||
|
||||
if (!si->doing_signing) {
|
||||
@ -680,13 +587,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
mid = SVAL(outbuf, smb_mid);
|
||||
|
||||
/* See if this is a reply for a deferred packet. */
|
||||
was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
|
||||
|
||||
if (data->trans_info && (data->trans_info->mid == mid)) {
|
||||
/* This is a reply in a trans stream. Use the sequence
|
||||
* number associated with the stream mid. */
|
||||
send_seq_number = data->trans_info->send_seq_num;
|
||||
}
|
||||
get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
|
||||
|
||||
simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
|
||||
|
||||
@ -697,36 +598,6 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
|
||||
|
||||
/* cli->outbuf[smb_ss_field+2]=0;
|
||||
Uncomment this to test if the remote client actually verifies signatures...*/
|
||||
|
||||
/* Don't mess with the sequence number for a deferred packet. */
|
||||
if (was_deferred_packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data->trans_info) {
|
||||
/* Always increment if not in a trans stream. */
|
||||
data->send_seq_num++;
|
||||
} else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
|
||||
/* Increment if this is the first reply in a trans stream or a
|
||||
* packet that doesn't belong to this stream (different mid). */
|
||||
data->send_seq_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Is an incoming packet an oplock break reply ?
|
||||
************************************************************/
|
||||
|
||||
static BOOL is_oplock_break(char *inbuf)
|
||||
{
|
||||
if (CVAL(inbuf,smb_com) != SMBlockingX)
|
||||
return False;
|
||||
|
||||
if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
|
||||
return False;
|
||||
|
||||
DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
|
||||
return True;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
@ -753,23 +624,8 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BO
|
||||
|
||||
mid = SVAL(inbuf, smb_mid);
|
||||
|
||||
/* Is this part of a trans stream ? */
|
||||
if (data->trans_info && (data->trans_info->mid == mid)) {
|
||||
/* If so we don't increment the sequence. */
|
||||
reply_seq_number = data->trans_info->reply_seq_num;
|
||||
} else {
|
||||
/* We always increment the sequence number. */
|
||||
data->send_seq_num++;
|
||||
|
||||
/* If we get an asynchronous oplock break reply and there
|
||||
* isn't a reply pending we need to re-sync the sequence
|
||||
* number.
|
||||
*/
|
||||
if (is_oplock_break(inbuf)) {
|
||||
DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
|
||||
data->send_seq_num++;
|
||||
}
|
||||
}
|
||||
/* We always increment the sequence number. */
|
||||
data->send_seq_num += 2;
|
||||
|
||||
saved_seq = reply_seq_number;
|
||||
simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
|
||||
@ -885,9 +741,8 @@ void srv_defer_sign_response(uint16 mid)
|
||||
* Ensure we only store this mid reply once...
|
||||
*/
|
||||
|
||||
if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
|
||||
data->send_seq_num++;
|
||||
}
|
||||
store_sequence_for_reply(&data->outstanding_packet_list, mid,
|
||||
data->send_seq_num-1);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
@ -974,63 +829,6 @@ BOOL srv_signing_started(void)
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************
|
||||
Tell server code we are in a multiple trans reply state.
|
||||
************************************************************/
|
||||
|
||||
void srv_signing_trans_start(uint16 mid)
|
||||
{
|
||||
struct smb_basic_signing_context *data;
|
||||
|
||||
if (!srv_sign_info.doing_signing)
|
||||
return;
|
||||
|
||||
data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
|
||||
ZERO_STRUCTP(data->trans_info);
|
||||
|
||||
data->trans_info->reply_seq_num = data->send_seq_num-1;
|
||||
data->trans_info->mid = mid;
|
||||
data->trans_info->send_seq_num = data->send_seq_num;
|
||||
|
||||
DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
|
||||
data->send_seq_num = %u\n",
|
||||
(unsigned int)mid,
|
||||
(unsigned int)data->trans_info->reply_seq_num,
|
||||
(unsigned int)data->trans_info->send_seq_num,
|
||||
(unsigned int)data->send_seq_num ));
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Tell server code we are out of a multiple trans reply state.
|
||||
************************************************************/
|
||||
|
||||
void srv_signing_trans_stop(void)
|
||||
{
|
||||
struct smb_basic_signing_context *data;
|
||||
|
||||
if (!srv_sign_info.doing_signing)
|
||||
return;
|
||||
|
||||
data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
|
||||
if (!data || !data->trans_info)
|
||||
return;
|
||||
|
||||
DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
|
||||
data->send_seq_num = %u\n",
|
||||
(unsigned int)data->trans_info->mid,
|
||||
(unsigned int)data->trans_info->reply_seq_num,
|
||||
(unsigned int)data->trans_info->send_seq_num,
|
||||
(unsigned int)data->send_seq_num ));
|
||||
|
||||
SAFE_FREE(data->trans_info);
|
||||
data->trans_info = NULL;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Turn on signing from this packet onwards.
|
||||
************************************************************/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
Locking functions
|
||||
Copyright (C) Andrew Tridgell 1992-2000
|
||||
Copyright (C) Jeremy Allison 1992-2000
|
||||
Copyright (C) Jeremy Allison 1992-2006
|
||||
Copyright (C) Volker Lendecke 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -33,6 +33,7 @@
|
||||
rewrtten completely to use new tdb code. Tridge, Dec '99
|
||||
|
||||
Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
|
||||
Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -45,120 +46,179 @@ uint16 global_smbpid;
|
||||
static TDB_CONTEXT *tdb;
|
||||
|
||||
/****************************************************************************
|
||||
Debugging aid :-).
|
||||
Debugging aids :-).
|
||||
****************************************************************************/
|
||||
|
||||
static const char *lock_type_name(enum brl_type lock_type)
|
||||
const char *lock_type_name(enum brl_type lock_type)
|
||||
{
|
||||
return (lock_type == READ_LOCK) ? "READ" : "WRITE";
|
||||
switch (lock_type) {
|
||||
case READ_LOCK:
|
||||
return "READ";
|
||||
case WRITE_LOCK:
|
||||
return "WRITE";
|
||||
case PENDING_LOCK:
|
||||
return "PENDING";
|
||||
default:
|
||||
return "other";
|
||||
}
|
||||
}
|
||||
|
||||
const char *lock_flav_name(enum brl_flavour lock_flav)
|
||||
{
|
||||
return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Utility function called to see if a file region is locked.
|
||||
Called in the read/write codepath.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL is_locked(files_struct *fsp,connection_struct *conn,
|
||||
SMB_BIG_UINT count,SMB_BIG_UINT offset,
|
||||
enum brl_type lock_type)
|
||||
BOOL is_locked(files_struct *fsp,
|
||||
SMB_BIG_UINT count,
|
||||
SMB_BIG_UINT offset,
|
||||
enum brl_type lock_type)
|
||||
{
|
||||
int snum = SNUM(conn);
|
||||
int snum = SNUM(fsp->conn);
|
||||
int strict_locking = lp_strict_locking(snum);
|
||||
BOOL ret;
|
||||
enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
|
||||
BOOL ret = True;
|
||||
|
||||
if (count == 0)
|
||||
return(False);
|
||||
if (count == 0) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!lp_locking(snum) || !strict_locking)
|
||||
return(False);
|
||||
if (!lp_locking(snum) || !strict_locking) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (strict_locking == Auto) {
|
||||
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
|
||||
DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
|
||||
ret = 0;
|
||||
ret = False;
|
||||
} else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
|
||||
(lock_type == READ_LOCK)) {
|
||||
DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
|
||||
ret = 0;
|
||||
ret = False;
|
||||
} else {
|
||||
ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
|
||||
global_smbpid, procid_self(), conn->cnum,
|
||||
offset, count, lock_type);
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
if (!br_lck) {
|
||||
return False;
|
||||
}
|
||||
ret = !brl_locktest(br_lck,
|
||||
global_smbpid,
|
||||
procid_self(),
|
||||
offset,
|
||||
count,
|
||||
lock_type,
|
||||
lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
} else {
|
||||
ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
|
||||
global_smbpid, procid_self(), conn->cnum,
|
||||
offset, count, lock_type);
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
if (!br_lck) {
|
||||
return False;
|
||||
}
|
||||
ret = !brl_locktest(br_lck,
|
||||
global_smbpid,
|
||||
procid_self(),
|
||||
offset,
|
||||
count,
|
||||
lock_type,
|
||||
lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
|
||||
DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
|
||||
lock_flav_name(lock_flav),
|
||||
(double)offset, (double)count, ret ? "locked" : "unlocked",
|
||||
fsp->fsp_name ));
|
||||
|
||||
/*
|
||||
* There is no lock held by an SMB daemon, check to
|
||||
* see if there is a POSIX lock from a UNIX or NFS process.
|
||||
*/
|
||||
|
||||
if(!ret && lp_posix_locking(snum)) {
|
||||
ret = is_posix_locked(fsp, offset, count, lock_type);
|
||||
|
||||
DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
|
||||
(double)offset, (double)count, ret ? "locked" : "unlocked",
|
||||
fsp->fsp_name ));
|
||||
}
|
||||
fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Find out if a lock could be granted - return who is blocking us if we can't.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS query_lock(files_struct *fsp,
|
||||
uint16 *psmbpid,
|
||||
SMB_BIG_UINT *pcount,
|
||||
SMB_BIG_UINT *poffset,
|
||||
enum brl_type *plock_type,
|
||||
enum brl_flavour lock_flav)
|
||||
{
|
||||
struct byte_range_lock *br_lck = NULL;
|
||||
NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
|
||||
|
||||
if (!OPEN_FSP(fsp) || !fsp->can_lock) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (!lp_locking(SNUM(fsp->conn))) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
br_lck = brl_get_locks(NULL, fsp);
|
||||
if (!br_lck) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = brl_lockquery(br_lck,
|
||||
psmbpid,
|
||||
procid_self(),
|
||||
poffset,
|
||||
pcount,
|
||||
plock_type,
|
||||
lock_flav);
|
||||
|
||||
TALLOC_FREE(br_lck);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Utility function called by locking requests.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
|
||||
SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
|
||||
NTSTATUS do_lock(files_struct *fsp,
|
||||
uint16 lock_pid,
|
||||
SMB_BIG_UINT count,
|
||||
SMB_BIG_UINT offset,
|
||||
enum brl_type lock_type,
|
||||
enum brl_flavour lock_flav,
|
||||
BOOL *my_lock_ctx)
|
||||
{
|
||||
struct byte_range_lock *br_lck = NULL;
|
||||
NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
|
||||
|
||||
if (!lp_locking(SNUM(conn)))
|
||||
if (!OPEN_FSP(fsp) || !fsp->can_lock) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (!lp_locking(SNUM(fsp->conn))) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
|
||||
|
||||
DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
|
||||
lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
|
||||
DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
|
||||
lock_flav_name(lock_flav), lock_type_name(lock_type),
|
||||
(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
|
||||
status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
lock_pid, procid_self(), conn->cnum,
|
||||
offset, count,
|
||||
lock_type, my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
|
||||
|
||||
/*
|
||||
* Try and get a POSIX lock on this range.
|
||||
* Note that this is ok if it is a read lock
|
||||
* overlapping on a different fd. JRA.
|
||||
*/
|
||||
|
||||
if (!set_posix_lock(fsp, offset, count, lock_type)) {
|
||||
if (errno == EACCES || errno == EAGAIN)
|
||||
status = NT_STATUS_FILE_LOCK_CONFLICT;
|
||||
else
|
||||
status = map_nt_error_from_unix(errno);
|
||||
|
||||
/*
|
||||
* We failed to map - we must now remove the brl
|
||||
* lock entry.
|
||||
*/
|
||||
(void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
lock_pid, procid_self(), conn->cnum,
|
||||
offset, count, False,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
br_lck = brl_get_locks(NULL, fsp);
|
||||
if (!br_lck) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = brl_lock(br_lck,
|
||||
lock_pid,
|
||||
procid_self(),
|
||||
offset,
|
||||
count,
|
||||
lock_type,
|
||||
lock_flav,
|
||||
my_lock_ctx);
|
||||
|
||||
TALLOC_FREE(br_lck);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -169,20 +229,33 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
|
||||
it, we need this. JRA.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
|
||||
SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
|
||||
NTSTATUS do_lock_spin(files_struct *fsp,
|
||||
uint16 lock_pid,
|
||||
SMB_BIG_UINT count,
|
||||
SMB_BIG_UINT offset,
|
||||
enum brl_type lock_type,
|
||||
enum brl_flavour lock_flav,
|
||||
BOOL *my_lock_ctx)
|
||||
{
|
||||
int j, maxj = lp_lock_spin_count();
|
||||
int sleeptime = lp_lock_sleep_time();
|
||||
NTSTATUS status, ret;
|
||||
|
||||
if (maxj <= 0)
|
||||
if (maxj <= 0) {
|
||||
maxj = 1;
|
||||
}
|
||||
|
||||
ret = NT_STATUS_OK; /* to keep dumb compilers happy */
|
||||
|
||||
for (j = 0; j < maxj; j++) {
|
||||
status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx);
|
||||
status = do_lock(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
lock_type,
|
||||
lock_flav,
|
||||
my_lock_ctx);
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
return status;
|
||||
@ -191,72 +264,66 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid
|
||||
if (j == 0) {
|
||||
ret = status;
|
||||
/* Don't spin if we blocked ourselves. */
|
||||
if (*my_lock_ctx)
|
||||
if (*my_lock_ctx) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Only spin for Windows locks. */
|
||||
if (lock_flav == POSIX_LOCK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (sleeptime)
|
||||
|
||||
if (sleeptime) {
|
||||
sys_usleep(sleeptime);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Struct passed to brl_unlock. */
|
||||
struct posix_unlock_data_struct {
|
||||
files_struct *fsp;
|
||||
SMB_BIG_UINT offset;
|
||||
SMB_BIG_UINT count;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
Function passed to brl_unlock to allow POSIX unlock to be done first.
|
||||
****************************************************************************/
|
||||
|
||||
static void posix_unlock(void *pre_data)
|
||||
{
|
||||
struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data;
|
||||
|
||||
if (lp_posix_locking(SNUM(pdata->fsp->conn)))
|
||||
release_posix_lock(pdata->fsp, pdata->offset, pdata->count);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Utility function called by unlocking requests.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
|
||||
SMB_BIG_UINT count,SMB_BIG_UINT offset)
|
||||
NTSTATUS do_unlock(files_struct *fsp,
|
||||
uint16 lock_pid,
|
||||
SMB_BIG_UINT count,
|
||||
SMB_BIG_UINT offset,
|
||||
enum brl_flavour lock_flav)
|
||||
{
|
||||
BOOL ok = False;
|
||||
struct posix_unlock_data_struct posix_data;
|
||||
struct byte_range_lock *br_lck = NULL;
|
||||
|
||||
if (!lp_locking(SNUM(conn)))
|
||||
if (!lp_locking(SNUM(fsp->conn))) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
|
||||
if (!OPEN_FSP(fsp) || !fsp->can_lock) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
|
||||
(double)offset, (double)count, fsp->fsp_name ));
|
||||
DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
|
||||
(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
/*
|
||||
* Remove the existing lock record from the tdb lockdb
|
||||
* before looking at POSIX locks. If this record doesn't
|
||||
* match then don't bother looking to remove POSIX locks.
|
||||
*/
|
||||
br_lck = brl_get_locks(NULL, fsp);
|
||||
if (!br_lck) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
posix_data.fsp = fsp;
|
||||
posix_data.offset = offset;
|
||||
posix_data.count = count;
|
||||
|
||||
ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
lock_pid, procid_self(), conn->cnum, offset, count,
|
||||
False, posix_unlock, (void *)&posix_data);
|
||||
ok = brl_unlock(br_lck,
|
||||
lock_pid,
|
||||
procid_self(),
|
||||
offset,
|
||||
count,
|
||||
lock_flav);
|
||||
|
||||
TALLOC_FREE(br_lck);
|
||||
|
||||
if (!ok) {
|
||||
DEBUG(10,("do_unlock: returning ERRlock.\n" ));
|
||||
return NT_STATUS_RANGE_NOT_LOCKED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -266,6 +333,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
|
||||
|
||||
void locking_close_file(files_struct *fsp)
|
||||
{
|
||||
struct byte_range_lock *br_lck;
|
||||
struct process_id pid = procid_self();
|
||||
|
||||
if (!lp_locking(SNUM(fsp->conn)))
|
||||
@ -275,13 +343,14 @@ void locking_close_file(files_struct *fsp)
|
||||
* Just release all the brl locks, no need to release individually.
|
||||
*/
|
||||
|
||||
brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
|
||||
br_lck = brl_get_locks(NULL,fsp);
|
||||
if (br_lck) {
|
||||
brl_close_fnum(br_lck, pid);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
if(lp_posix_locking(SNUM(fsp->conn))) {
|
||||
|
||||
/*
|
||||
* Release all the POSIX locks.
|
||||
*/
|
||||
/* Release all the POSIX locks.*/
|
||||
posix_locking_close_file(fsp);
|
||||
|
||||
}
|
||||
|
@ -644,8 +644,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
|
||||
|
||||
/****************************************************************************
|
||||
Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
|
||||
broken NFS implementations. Returns True if we got the lock or the region
|
||||
is unlocked in the F_GETLK case, False otherwise.
|
||||
broken NFS implementations.
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
|
||||
@ -654,9 +653,6 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF
|
||||
|
||||
DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
|
||||
|
||||
/* In the F_GETLK case this returns True if the region
|
||||
was locked, False if unlocked. */
|
||||
|
||||
ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
|
||||
|
||||
if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) {
|
||||
@ -686,39 +682,97 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF
|
||||
}
|
||||
|
||||
DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
|
||||
broken NFS implementations.
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
|
||||
{
|
||||
pid_t pid;
|
||||
BOOL ret;
|
||||
|
||||
DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
|
||||
fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
|
||||
|
||||
ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
|
||||
|
||||
if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) {
|
||||
|
||||
DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
|
||||
(double)*poffset,(double)*pcount));
|
||||
DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
|
||||
DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
|
||||
|
||||
/*
|
||||
* If the offset is > 0x7FFFFFFF then this will cause problems on
|
||||
* 32 bit NFS mounted filesystems. Just ignore it.
|
||||
*/
|
||||
|
||||
if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
|
||||
DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
|
||||
return True;
|
||||
}
|
||||
|
||||
if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
|
||||
/* 32 bit NFS file system, retry with smaller offset */
|
||||
DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
|
||||
errno = 0;
|
||||
*pcount &= 0x7fffffff;
|
||||
ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
POSIX function to see if a file region is locked. Returns True if the
|
||||
region is locked, False otherwise.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
|
||||
BOOL is_posix_locked(files_struct *fsp,
|
||||
SMB_BIG_UINT *pu_offset,
|
||||
SMB_BIG_UINT *pu_count,
|
||||
enum brl_type *plock_type,
|
||||
enum brl_flavour lock_flav)
|
||||
{
|
||||
SMB_OFF_T offset;
|
||||
SMB_OFF_T count;
|
||||
int posix_lock_type = map_posix_lock_type(fsp,lock_type);
|
||||
int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
|
||||
|
||||
DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
|
||||
fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
|
||||
fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
|
||||
|
||||
/*
|
||||
* If the requested lock won't fit in the POSIX range, we will
|
||||
* never set it, so presume it is not locked.
|
||||
*/
|
||||
|
||||
if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
|
||||
if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that most UNIX's can *test* for a write lock on
|
||||
* a read-only fd, just not *set* a write lock on a read-only
|
||||
* fd. So we don't need to use map_lock_type here.
|
||||
*/
|
||||
if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type);
|
||||
if (posix_lock_type == F_UNLCK) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (lock_flav == POSIX_LOCK) {
|
||||
/* Only POSIX lock queries need to know the details. */
|
||||
*pu_offset = (SMB_BIG_UINT)offset;
|
||||
*pu_count = (SMB_BIG_UINT)count;
|
||||
*plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -958,9 +1012,14 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size,
|
||||
/****************************************************************************
|
||||
POSIX function to acquire a lock. Returns True if the
|
||||
lock could be granted, False if not.
|
||||
TODO -- Fix POSIX lock flavour semantics.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
|
||||
BOOL set_posix_lock(files_struct *fsp,
|
||||
SMB_BIG_UINT u_offset,
|
||||
SMB_BIG_UINT u_count,
|
||||
enum brl_type lock_type,
|
||||
enum brl_flavour lock_flav)
|
||||
{
|
||||
SMB_OFF_T offset;
|
||||
SMB_OFF_T count;
|
||||
|
@ -161,6 +161,8 @@ static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp
|
||||
int fd, SMB_OFF_T len);
|
||||
static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int fd,
|
||||
int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
|
||||
static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd,
|
||||
SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid);
|
||||
static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
|
||||
const char *oldpath, const char *newpath);
|
||||
static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
|
||||
@ -399,6 +401,8 @@ static vfs_op_tuple audit_op_tuples[] = {
|
||||
SMB_VFS_LAYER_LOGGER},
|
||||
{SMB_VFS_OP(smb_full_audit_lock), SMB_VFS_OP_LOCK,
|
||||
SMB_VFS_LAYER_LOGGER},
|
||||
{SMB_VFS_OP(smb_full_audit_getlock), SMB_VFS_OP_GETLOCK,
|
||||
SMB_VFS_LAYER_LOGGER},
|
||||
{SMB_VFS_OP(smb_full_audit_symlink), SMB_VFS_OP_SYMLINK,
|
||||
SMB_VFS_LAYER_LOGGER},
|
||||
{SMB_VFS_OP(smb_full_audit_readlink), SMB_VFS_OP_READLINK,
|
||||
@ -564,6 +568,7 @@ static struct {
|
||||
{ SMB_VFS_OP_UTIME, "utime" },
|
||||
{ SMB_VFS_OP_FTRUNCATE, "ftruncate" },
|
||||
{ SMB_VFS_OP_LOCK, "lock" },
|
||||
{ SMB_VFS_OP_GETLOCK, "getlock" },
|
||||
{ SMB_VFS_OP_SYMLINK, "symlink" },
|
||||
{ SMB_VFS_OP_READLINK, "readlink" },
|
||||
{ SMB_VFS_OP_LINK, "link" },
|
||||
@ -1313,6 +1318,18 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd,
|
||||
SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
result = SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid);
|
||||
|
||||
do_log(SMB_VFS_OP_GETLOCK, (result >= 0), handle, "%s", fsp->fsp_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
|
||||
const char *oldpath, const char *newpath)
|
||||
{
|
||||
|
@ -5444,3 +5444,22 @@ void lp_set_posix_pathnames(void)
|
||||
{
|
||||
posix_pathnames = True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Global state for POSIX lock processing - CIFS unix extensions.
|
||||
********************************************************************/
|
||||
|
||||
static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
|
||||
|
||||
enum brl_flavour lp_posix_cifsu_locktype(void)
|
||||
{
|
||||
return posix_cifsx_locktype;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
********************************************************************/
|
||||
|
||||
void lp_set_posix_cifsx_locktype(enum brl_flavour val)
|
||||
{
|
||||
posix_cifsx_locktype = val;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ typedef struct _blocking_lock_record {
|
||||
SMB_BIG_UINT offset;
|
||||
SMB_BIG_UINT count;
|
||||
uint16 lock_pid;
|
||||
enum brl_flavour lock_flav;
|
||||
enum brl_type lock_type;
|
||||
char *inbuf;
|
||||
int length;
|
||||
} blocking_lock_record;
|
||||
@ -52,25 +54,6 @@ static void free_blocking_lock_record(blocking_lock_record *blr)
|
||||
SAFE_FREE(blr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Get the files_struct given a particular queued SMB.
|
||||
*****************************************************************************/
|
||||
|
||||
static files_struct *get_fsp_from_pkt(char *inbuf)
|
||||
{
|
||||
switch(CVAL(inbuf,smb_com)) {
|
||||
case SMBlock:
|
||||
case SMBlockread:
|
||||
return file_fsp(inbuf,smb_vwv0);
|
||||
case SMBlockingX:
|
||||
return file_fsp(inbuf,smb_vwv2);
|
||||
default:
|
||||
DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n"));
|
||||
exit_server("PANIC - unknown type on blocking lock queue");
|
||||
}
|
||||
return NULL; /* Keep compiler happy. */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Determine if this is a secondary element of a chained SMB.
|
||||
**************************************************************************/
|
||||
@ -87,12 +70,19 @@ static void received_unlock_msg(int msg_type, struct process_id src,
|
||||
Function to push a blocking lock request onto the lock queue.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
|
||||
int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count)
|
||||
BOOL push_blocking_lock_request( char *inbuf, int length,
|
||||
files_struct *fsp,
|
||||
int lock_timeout,
|
||||
int lock_num,
|
||||
uint16 lock_pid,
|
||||
enum brl_type lock_type,
|
||||
enum brl_flavour lock_flav,
|
||||
SMB_BIG_UINT offset, SMB_BIG_UINT count)
|
||||
{
|
||||
static BOOL set_lock_msg;
|
||||
blocking_lock_record *blr, *tmp;
|
||||
BOOL my_lock_ctx = False;
|
||||
struct byte_range_lock *br_lck = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if(in_chained_smb() ) {
|
||||
@ -110,6 +100,9 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
|
||||
return False;
|
||||
}
|
||||
|
||||
blr->next = NULL;
|
||||
blr->prev = NULL;
|
||||
|
||||
if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) {
|
||||
DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
|
||||
SAFE_FREE(blr);
|
||||
@ -117,19 +110,33 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
|
||||
}
|
||||
|
||||
blr->com_type = CVAL(inbuf,smb_com);
|
||||
blr->fsp = get_fsp_from_pkt(inbuf);
|
||||
blr->fsp = fsp;
|
||||
blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
|
||||
blr->lock_num = lock_num;
|
||||
blr->lock_pid = lock_pid;
|
||||
blr->lock_flav = lock_flav;
|
||||
blr->lock_type = lock_type;
|
||||
blr->offset = offset;
|
||||
blr->count = count;
|
||||
memcpy(blr->inbuf, inbuf, length);
|
||||
blr->length = length;
|
||||
|
||||
br_lck = brl_get_locks(NULL, blr->fsp);
|
||||
if (!br_lck) {
|
||||
free_blocking_lock_record(blr);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Add a pending lock record for this. */
|
||||
status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
|
||||
lock_pid, procid_self(), blr->fsp->conn->cnum,
|
||||
offset, count, PENDING_LOCK, &my_lock_ctx);
|
||||
status = brl_lock(br_lck,
|
||||
lock_pid,
|
||||
procid_self(),
|
||||
offset,
|
||||
count,
|
||||
PENDING_LOCK,
|
||||
blr->lock_flav,
|
||||
&my_lock_ctx);
|
||||
TALLOC_FREE(br_lck);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
|
||||
@ -227,7 +234,6 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
|
||||
{
|
||||
char *inbuf = blr->inbuf;
|
||||
files_struct *fsp = blr->fsp;
|
||||
connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
|
||||
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
|
||||
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0;
|
||||
uint16 lock_pid;
|
||||
@ -261,7 +267,11 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
|
||||
* request would never have been queued. JRA.
|
||||
*/
|
||||
|
||||
do_unlock(fsp,conn,lock_pid,count,offset);
|
||||
do_unlock(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
WINDOWS_LOCK);
|
||||
}
|
||||
|
||||
generic_blocking_lock_error(blr, status);
|
||||
@ -274,19 +284,41 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
|
||||
static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status)
|
||||
{
|
||||
switch(blr->com_type) {
|
||||
#if 0
|
||||
/* We no longer push blocking lock requests for anything but lockingX and trans2. */
|
||||
case SMBlock:
|
||||
case SMBlockread:
|
||||
generic_blocking_lock_error(blr, status);
|
||||
break;
|
||||
#endif
|
||||
case SMBlockingX:
|
||||
reply_lockingX_error(blr, status);
|
||||
break;
|
||||
case SMBtrans2:
|
||||
case SMBtranss2:
|
||||
{
|
||||
char *outbuf = get_OutBuffer();
|
||||
char *inbuf = blr->inbuf;
|
||||
construct_reply_common(inbuf, outbuf);
|
||||
/* construct_reply_common has done us the favor to pre-fill the
|
||||
* command field with SMBtranss2 which is wrong :-)
|
||||
*/
|
||||
SCVAL(outbuf,smb_com,SMBtrans2);
|
||||
ERROR_NT(status);
|
||||
if (!send_smb(smbd_server_fd(),outbuf)) {
|
||||
exit_server("blocking_lock_reply_error: send_smb failed.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
|
||||
exit_server("PANIC - unknown type on blocking lock queue");
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* We no longer push blocking lock requests for anything but lockingX and trans2. */
|
||||
|
||||
/****************************************************************************
|
||||
Attempt to finish off getting all pending blocking locks for a lockread call.
|
||||
Returns True if we want to be removed from the list.
|
||||
@ -302,7 +334,6 @@ static BOOL process_lockread(blocking_lock_record *blr)
|
||||
SMB_BIG_UINT startpos;
|
||||
size_t numtoread;
|
||||
NTSTATUS status;
|
||||
connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
|
||||
files_struct *fsp = blr->fsp;
|
||||
BOOL my_lock_ctx = False;
|
||||
|
||||
@ -312,7 +343,14 @@ static BOOL process_lockread(blocking_lock_record *blr)
|
||||
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
|
||||
data = smb_buf(outbuf) + 3;
|
||||
|
||||
status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx);
|
||||
status = do_lock_spin(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
(SMB_BIG_UINT)numtoread,
|
||||
startpos,
|
||||
READ_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
@ -371,7 +409,6 @@ static BOOL process_lock(blocking_lock_record *blr)
|
||||
int outsize;
|
||||
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
|
||||
NTSTATUS status;
|
||||
connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
|
||||
files_struct *fsp = blr->fsp;
|
||||
BOOL my_lock_ctx = False;
|
||||
|
||||
@ -379,7 +416,14 @@ static BOOL process_lock(blocking_lock_record *blr)
|
||||
offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
|
||||
|
||||
errno = 0;
|
||||
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
|
||||
status = do_lock_spin(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
count,
|
||||
offset,
|
||||
WRITE_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
@ -412,6 +456,7 @@ static BOOL process_lock(blocking_lock_record *blr)
|
||||
send_blocking_reply(outbuf,outsize);
|
||||
return True;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Attempt to finish off getting all pending blocking locks for a lockingX call.
|
||||
@ -423,7 +468,6 @@ static BOOL process_lockingX(blocking_lock_record *blr)
|
||||
char *inbuf = blr->inbuf;
|
||||
unsigned char locktype = CVAL(inbuf,smb_vwv3);
|
||||
files_struct *fsp = blr->fsp;
|
||||
connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
|
||||
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
|
||||
uint16 num_locks = SVAL(inbuf,smb_vwv7);
|
||||
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
|
||||
@ -452,9 +496,17 @@ static BOOL process_lockingX(blocking_lock_record *blr)
|
||||
* request would never have been queued. JRA.
|
||||
*/
|
||||
errno = 0;
|
||||
status = do_lock_spin(fsp,conn,lock_pid,count,offset,
|
||||
((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
|
||||
if (NT_STATUS_IS_ERR(status)) break;
|
||||
status = do_lock_spin(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
((locktype & 1) ? READ_LOCK : WRITE_LOCK),
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(blr->lock_num == num_locks) {
|
||||
@ -490,6 +542,51 @@ Waiting....\n",
|
||||
return False;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Attempt to get the posix lock request from a SMBtrans2 call.
|
||||
Returns True if we want to be removed from the list.
|
||||
*****************************************************************************/
|
||||
|
||||
static BOOL process_trans2(blocking_lock_record *blr)
|
||||
{
|
||||
extern int max_send;
|
||||
char *inbuf = blr->inbuf;
|
||||
char *outbuf;
|
||||
BOOL my_lock_ctx = False;
|
||||
char params[2];
|
||||
NTSTATUS status;
|
||||
|
||||
status = do_lock(blr->fsp,
|
||||
blr->lock_pid,
|
||||
blr->count,
|
||||
blr->offset,
|
||||
blr->lock_type,
|
||||
blr->lock_flav,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (ERROR_WAS_LOCK_DENIED(status)) {
|
||||
/* Still can't get the lock, just keep waiting. */
|
||||
return False;
|
||||
}
|
||||
/*
|
||||
* We have other than a "can't get lock"
|
||||
* error. Send an error and return True so we get dequeued.
|
||||
*/
|
||||
blocking_lock_reply_error(blr, status);
|
||||
return True;
|
||||
}
|
||||
|
||||
/* We finally got the lock, return success. */
|
||||
outbuf = get_OutBuffer();
|
||||
construct_reply_common(inbuf, outbuf);
|
||||
SCVAL(outbuf,smb_com,SMBtrans2);
|
||||
SSVAL(params,0,0);
|
||||
send_trans2_replies(outbuf, max_send, params, 2, NULL, 0);
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Process a blocking lock SMB.
|
||||
Returns True if we want to be removed from the list.
|
||||
@ -498,12 +595,18 @@ Waiting....\n",
|
||||
static BOOL blocking_lock_record_process(blocking_lock_record *blr)
|
||||
{
|
||||
switch(blr->com_type) {
|
||||
#if 0
|
||||
/* We no longer push blocking lock requests for anything but lockingX and trans2. */
|
||||
case SMBlock:
|
||||
return process_lock(blr);
|
||||
case SMBlockread:
|
||||
return process_lockread(blr);
|
||||
#endif
|
||||
case SMBlockingX:
|
||||
return process_lockingX(blr);
|
||||
case SMBtrans2:
|
||||
case SMBtranss2:
|
||||
return process_trans2(blr);
|
||||
default:
|
||||
DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
|
||||
exit_server("PANIC - unknown type on blocking lock queue");
|
||||
@ -522,13 +625,21 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp)
|
||||
for(blr = blocking_lock_queue; blr; blr = next) {
|
||||
next = blr->next;
|
||||
if(blr->fsp->fnum == fsp->fnum) {
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
|
||||
if (br_lck) {
|
||||
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
|
||||
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
|
||||
|
||||
brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
|
||||
blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
|
||||
}
|
||||
|
||||
free_blocking_lock_record(blr);
|
||||
}
|
||||
@ -547,14 +658,22 @@ void remove_pending_lock_requests_by_mid(int mid)
|
||||
next = blr->next;
|
||||
if(SVAL(blr->inbuf,smb_mid) == mid) {
|
||||
files_struct *fsp = blr->fsp;
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
|
||||
if (br_lck) {
|
||||
DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
|
||||
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
|
||||
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
|
||||
brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
|
||||
blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
free_blocking_lock_record(blr);
|
||||
}
|
||||
}
|
||||
@ -635,16 +754,25 @@ void process_blocking_lock_queue(time_t t)
|
||||
fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
if((blr->expire_time != -1) && (blr->expire_time <= t)) {
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
/*
|
||||
* Lock expired - throw away all previously
|
||||
* obtained locks and return lock error.
|
||||
*/
|
||||
DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
|
||||
fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
blr->lock_pid, procid_self(), conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
if (br_lck) {
|
||||
DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
|
||||
fsp->fnum, fsp->fsp_name ));
|
||||
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
|
||||
free_blocking_lock_record(blr);
|
||||
@ -652,32 +780,48 @@ void process_blocking_lock_queue(time_t t)
|
||||
}
|
||||
|
||||
if(!change_to_user(conn,vuid)) {
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
|
||||
vuid ));
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
/*
|
||||
* Remove the entry and return an error to the client.
|
||||
*/
|
||||
|
||||
if (br_lck) {
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
|
||||
vuid ));
|
||||
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
|
||||
|
||||
brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
blr->lock_pid, procid_self(), conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
|
||||
free_blocking_lock_record(blr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
/*
|
||||
* Remove the entry and return an error to the client.
|
||||
*/
|
||||
|
||||
if (br_lck) {
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
|
||||
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
|
||||
|
||||
brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
blr->lock_pid, procid_self(), conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
|
||||
free_blocking_lock_record(blr);
|
||||
change_to_root_user();
|
||||
continue;
|
||||
@ -690,10 +834,17 @@ void process_blocking_lock_queue(time_t t)
|
||||
*/
|
||||
|
||||
if(blocking_lock_record_process(blr)) {
|
||||
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
|
||||
|
||||
brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
|
||||
blr->lock_pid, procid_self(), conn->cnum,
|
||||
blr->offset, blr->count, True, NULL, NULL);
|
||||
if (br_lck) {
|
||||
brl_remove_pending_lock(br_lck,
|
||||
blr->lock_pid,
|
||||
procid_self(),
|
||||
blr->offset,
|
||||
blr->count,
|
||||
blr->lock_flav);
|
||||
TALLOC_FREE(br_lck);
|
||||
}
|
||||
|
||||
free_blocking_lock_record(blr);
|
||||
}
|
||||
|
@ -355,259 +355,349 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS handle_trans(connection_struct *conn,
|
||||
struct trans_state *state,
|
||||
char *outbuf, int *outsize)
|
||||
{
|
||||
char *local_machine_name;
|
||||
int name_offset = 0;
|
||||
|
||||
DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
|
||||
state->name,state->total_data,state->total_param,
|
||||
state->setup_count));
|
||||
|
||||
/*
|
||||
* WinCE wierdness....
|
||||
*/
|
||||
|
||||
local_machine_name = talloc_asprintf(state, "\\%s\\",
|
||||
get_local_machine_name());
|
||||
|
||||
if (local_machine_name == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (strnequal(state->name, local_machine_name,
|
||||
strlen(local_machine_name))) {
|
||||
name_offset = strlen(local_machine_name)-1;
|
||||
}
|
||||
|
||||
if (!strnequal(&state->name[name_offset], "\\PIPE",
|
||||
strlen("\\PIPE"))) {
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
name_offset += strlen("\\PIPE");
|
||||
|
||||
/* Win9x weirdness. When talking to a unicode server Win9x
|
||||
only sends \PIPE instead of \PIPE\ */
|
||||
|
||||
if (state->name[name_offset] == '\\')
|
||||
name_offset++;
|
||||
|
||||
DEBUG(5,("calling named_pipe\n"));
|
||||
*outsize = named_pipe(conn, state->vuid, outbuf,
|
||||
state->name+name_offset,
|
||||
state->setup,state->data,
|
||||
state->param,
|
||||
state->setup_count,state->total_data,
|
||||
state->total_param,
|
||||
state->max_setup_return,
|
||||
state->max_data_return,
|
||||
state->max_param_return);
|
||||
|
||||
if (*outsize == 0) {
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (state->close_on_completion)
|
||||
close_cnum(conn,state->vuid);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a SMBtrans.
|
||||
****************************************************************************/
|
||||
|
||||
int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
|
||||
int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
int size, int bufsize)
|
||||
{
|
||||
fstring name;
|
||||
int name_offset = 0;
|
||||
char *data=NULL,*params=NULL;
|
||||
uint16 *setup=NULL;
|
||||
int outsize = 0;
|
||||
uint16 vuid = SVAL(inbuf,smb_uid);
|
||||
unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
|
||||
unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
|
||||
unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
|
||||
unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
|
||||
unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
|
||||
BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
|
||||
BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
|
||||
unsigned int pscnt = SVAL(inbuf,smb_vwv9);
|
||||
unsigned int psoff = SVAL(inbuf,smb_vwv10);
|
||||
unsigned int dscnt = SVAL(inbuf,smb_vwv11);
|
||||
unsigned int dsoff = SVAL(inbuf,smb_vwv12);
|
||||
unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
|
||||
char *local_machine_name;
|
||||
unsigned int dsoff = SVAL(inbuf, smb_dsoff);
|
||||
unsigned int dscnt = SVAL(inbuf, smb_dscnt);
|
||||
unsigned int psoff = SVAL(inbuf, smb_psoff);
|
||||
unsigned int pscnt = SVAL(inbuf, smb_pscnt);
|
||||
struct trans_state *state;
|
||||
NTSTATUS result;
|
||||
|
||||
START_PROFILE(SMBtrans);
|
||||
|
||||
memset(name, '\0',sizeof(name));
|
||||
srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE);
|
||||
if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
|
||||
SVAL(inbuf, smb_mid)))) {
|
||||
DEBUG(2, ("Got invalid trans request: %s\n",
|
||||
nt_errstr(result)));
|
||||
END_PROFILE(SMBtrans);
|
||||
return ERROR_NT(result);
|
||||
}
|
||||
|
||||
if (dscnt > tdscnt || pscnt > tpscnt)
|
||||
if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
|
||||
DEBUG(0, ("talloc failed\n"));
|
||||
END_PROFILE(SMBtrans);
|
||||
return ERROR_NT(NT_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
state->cmd = SMBtrans;
|
||||
|
||||
state->mid = SVAL(inbuf, smb_mid);
|
||||
state->vuid = SVAL(inbuf, smb_uid);
|
||||
state->setup_count = CVAL(inbuf, smb_suwcnt);
|
||||
state->total_param = SVAL(inbuf, smb_tpscnt);
|
||||
state->param = NULL;
|
||||
state->total_data = SVAL(inbuf, smb_tdscnt);
|
||||
state->data = NULL;
|
||||
state->max_param_return = SVAL(inbuf, smb_mprcnt);
|
||||
state->max_data_return = SVAL(inbuf, smb_mdrcnt);
|
||||
state->max_setup_return = CVAL(inbuf, smb_msrcnt);
|
||||
state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
|
||||
state->one_way = BITSETW(inbuf+smb_vwv5,1);
|
||||
|
||||
memset(state->name, '\0',sizeof(state->name));
|
||||
srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
|
||||
sizeof(state->name), STR_TERMINATE);
|
||||
|
||||
if ((dscnt > state->total_data) || (pscnt > state->total_param))
|
||||
goto bad_param;
|
||||
|
||||
if (tdscnt) {
|
||||
if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) {
|
||||
DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
|
||||
|
||||
if (state->total_data) {
|
||||
/* Can't use talloc here, the core routines do realloc on the
|
||||
* params and data. */
|
||||
state->data = SMB_MALLOC(state->total_data);
|
||||
if (state->data == NULL) {
|
||||
DEBUG(0,("reply_trans: data malloc fail for %u "
|
||||
"bytes !\n", state->total_data));
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRDOS,ERRnomem));
|
||||
}
|
||||
if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
|
||||
(smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
|
||||
(smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
|
||||
memcpy(data,smb_base(inbuf)+dsoff,dscnt);
|
||||
memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
|
||||
}
|
||||
|
||||
if (tpscnt) {
|
||||
if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) {
|
||||
DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
|
||||
SAFE_FREE(data);
|
||||
if (state->total_param) {
|
||||
/* Can't use talloc here, the core routines do realloc on the
|
||||
* params and data. */
|
||||
state->param = SMB_MALLOC(state->total_param);
|
||||
if (state->param == NULL) {
|
||||
DEBUG(0,("reply_trans: param malloc fail for %u "
|
||||
"bytes !\n", state->total_param));
|
||||
SAFE_FREE(state->data);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRDOS,ERRnomem));
|
||||
}
|
||||
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
|
||||
(smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
|
||||
(smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
|
||||
memcpy(params,smb_base(inbuf)+psoff,pscnt);
|
||||
memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
|
||||
}
|
||||
|
||||
if (suwcnt) {
|
||||
state->received_data = dscnt;
|
||||
state->received_param = pscnt;
|
||||
|
||||
if (state->setup_count) {
|
||||
unsigned int i;
|
||||
if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) {
|
||||
DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(params);
|
||||
if((state->setup = TALLOC_ARRAY(
|
||||
state, uint16, state->setup_count)) == NULL) {
|
||||
DEBUG(0,("reply_trans: setup malloc fail for %u "
|
||||
"bytes !\n", (unsigned int)
|
||||
(state->setup_count * sizeof(uint16))));
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRDOS,ERRnomem));
|
||||
}
|
||||
if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
|
||||
if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) >
|
||||
inbuf + size)
|
||||
goto bad_param;
|
||||
if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
|
||||
if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) ||
|
||||
(smb_vwv14+(state->setup_count*SIZEOFWORD) <
|
||||
(state->setup_count*SIZEOFWORD)))
|
||||
goto bad_param;
|
||||
|
||||
for (i=0;i<suwcnt;i++)
|
||||
setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
|
||||
for (i=0;i<state->setup_count;i++)
|
||||
state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
|
||||
}
|
||||
|
||||
state->received_param = pscnt;
|
||||
|
||||
srv_signing_trans_start(SVAL(inbuf,smb_mid));
|
||||
if ((state->received_param == state->total_param) &&
|
||||
(state->received_data == state->total_data)) {
|
||||
|
||||
if (pscnt < tpscnt || dscnt < tdscnt) {
|
||||
/* We need to send an interim response then receive the rest
|
||||
of the parameter/data bytes */
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
show_msg(outbuf);
|
||||
srv_signing_trans_stop();
|
||||
if (!send_smb(smbd_server_fd(),outbuf))
|
||||
exit_server("reply_trans: send_smb failed.");
|
||||
}
|
||||
result = handle_trans(conn, state, outbuf, &outsize);
|
||||
|
||||
/* receive the rest of the trans packet */
|
||||
while (pscnt < tpscnt || dscnt < tdscnt) {
|
||||
BOOL ret;
|
||||
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
|
||||
|
||||
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
|
||||
/*
|
||||
* The sequence number for the trans reply is always
|
||||
* based on the last secondary received.
|
||||
*/
|
||||
|
||||
srv_signing_trans_start(SVAL(inbuf,smb_mid));
|
||||
|
||||
if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
|
||||
if(ret) {
|
||||
DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
|
||||
} else {
|
||||
DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
|
||||
(smb_read_error == READ_ERROR) ? "error" : "timeout" ));
|
||||
}
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(setup);
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
END_PROFILE(SMBtrans);
|
||||
srv_signing_trans_stop();
|
||||
return(ERROR_DOS(ERRSRV,ERRerror));
|
||||
return ERROR_NT(result);
|
||||
}
|
||||
|
||||
show_msg(inbuf);
|
||||
|
||||
/* Revise total_params and total_data in case they have changed downwards */
|
||||
if (SVAL(inbuf,smb_vwv0) < tpscnt)
|
||||
tpscnt = SVAL(inbuf,smb_vwv0);
|
||||
if (SVAL(inbuf,smb_vwv1) < tdscnt)
|
||||
tdscnt = SVAL(inbuf,smb_vwv1);
|
||||
|
||||
pcnt = SVAL(inbuf,smb_vwv2);
|
||||
poff = SVAL(inbuf,smb_vwv3);
|
||||
pdisp = SVAL(inbuf,smb_vwv4);
|
||||
|
||||
dcnt = SVAL(inbuf,smb_vwv5);
|
||||
doff = SVAL(inbuf,smb_vwv6);
|
||||
ddisp = SVAL(inbuf,smb_vwv7);
|
||||
|
||||
pscnt += pcnt;
|
||||
dscnt += dcnt;
|
||||
|
||||
if (dscnt > tdscnt || pscnt > tpscnt)
|
||||
goto bad_param;
|
||||
|
||||
if (pcnt) {
|
||||
if (pdisp+pcnt > tpscnt)
|
||||
goto bad_param;
|
||||
if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
|
||||
goto bad_param;
|
||||
if (pdisp > tpscnt)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + poff + pcnt > inbuf + bufsize) ||
|
||||
(smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (params + pdisp < params)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
|
||||
if (outsize == 0) {
|
||||
END_PROFILE(SMBtrans);
|
||||
return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
if (dcnt) {
|
||||
if (ddisp+dcnt > tdscnt)
|
||||
goto bad_param;
|
||||
if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
|
||||
goto bad_param;
|
||||
if (ddisp > tdscnt)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + doff + dcnt > inbuf + bufsize) ||
|
||||
(smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (data + ddisp < data)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
|
||||
name,tdscnt,tpscnt,suwcnt));
|
||||
|
||||
/*
|
||||
* WinCE wierdness....
|
||||
*/
|
||||
|
||||
asprintf(&local_machine_name, "\\%s\\", get_local_machine_name());
|
||||
|
||||
if (local_machine_name == NULL) {
|
||||
srv_signing_trans_stop();
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(setup);
|
||||
END_PROFILE(SMBtrans);
|
||||
return ERROR_NT(NT_STATUS_NO_MEMORY);
|
||||
return outsize;
|
||||
}
|
||||
|
||||
if (strnequal(name, local_machine_name, strlen(local_machine_name))) {
|
||||
name_offset = strlen(local_machine_name)-1;
|
||||
}
|
||||
DLIST_ADD(conn->pending_trans, state);
|
||||
|
||||
SAFE_FREE(local_machine_name);
|
||||
|
||||
if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) {
|
||||
name_offset += strlen("\\PIPE");
|
||||
|
||||
/* Win9x weirdness. When talking to a unicode server Win9x
|
||||
only sends \PIPE instead of \PIPE\ */
|
||||
|
||||
if (name[name_offset] == '\\')
|
||||
name_offset++;
|
||||
|
||||
DEBUG(5,("calling named_pipe\n"));
|
||||
outsize = named_pipe(conn,vuid,outbuf,
|
||||
name+name_offset,setup,data,params,
|
||||
suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
|
||||
} else {
|
||||
DEBUG(3,("invalid pipe name\n"));
|
||||
outsize = 0;
|
||||
}
|
||||
|
||||
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(setup);
|
||||
|
||||
srv_signing_trans_stop();
|
||||
|
||||
if (close_on_completion)
|
||||
close_cnum(conn,vuid);
|
||||
|
||||
if (one_way) {
|
||||
END_PROFILE(SMBtrans);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (outsize == 0) {
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRSRV,ERRnosupport));
|
||||
}
|
||||
|
||||
/* We need to send an interim response then receive the rest
|
||||
of the parameter/data bytes */
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
show_msg(outbuf);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(outsize);
|
||||
|
||||
return outsize;
|
||||
|
||||
bad_param:
|
||||
|
||||
srv_signing_trans_stop();
|
||||
DEBUG(0,("reply_trans: invalid trans parameters\n"));
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(setup);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a secondary SMBtrans.
|
||||
****************************************************************************/
|
||||
|
||||
int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
int size, int bufsize)
|
||||
{
|
||||
int outsize = 0;
|
||||
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
|
||||
struct trans_state *state;
|
||||
NTSTATUS result;
|
||||
|
||||
START_PROFILE(SMBtranss);
|
||||
|
||||
show_msg(inbuf);
|
||||
|
||||
for (state = conn->pending_trans; state != NULL;
|
||||
state = state->next) {
|
||||
if (state->mid == SVAL(inbuf,smb_mid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state == NULL) || (state->cmd != SMBtrans)) {
|
||||
END_PROFILE(SMBtranss);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Revise total_params and total_data in case they have changed
|
||||
* downwards */
|
||||
|
||||
if (SVAL(inbuf, smb_vwv0) < state->total_param)
|
||||
state->total_param = SVAL(inbuf,smb_vwv0);
|
||||
if (SVAL(inbuf, smb_vwv1) < state->total_data)
|
||||
state->total_data = SVAL(inbuf,smb_vwv1);
|
||||
|
||||
pcnt = SVAL(inbuf, smb_spscnt);
|
||||
poff = SVAL(inbuf, smb_spsoff);
|
||||
pdisp = SVAL(inbuf, smb_spsdisp);
|
||||
|
||||
dcnt = SVAL(inbuf, smb_sdscnt);
|
||||
doff = SVAL(inbuf, smb_sdsoff);
|
||||
ddisp = SVAL(inbuf, smb_sdsdisp);
|
||||
|
||||
state->received_param += pcnt;
|
||||
state->received_data += dcnt;
|
||||
|
||||
if ((state->received_data > state->total_data) ||
|
||||
(state->received_param > state->total_param))
|
||||
goto bad_param;
|
||||
|
||||
if (pcnt) {
|
||||
if (pdisp+pcnt > state->total_param)
|
||||
goto bad_param;
|
||||
if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
|
||||
goto bad_param;
|
||||
if (pdisp > state->total_param)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
|
||||
(smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (state->param + pdisp < state->param)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(state->param+pdisp,smb_base(inbuf)+poff,
|
||||
pcnt);
|
||||
}
|
||||
|
||||
if (dcnt) {
|
||||
if (ddisp+dcnt > state->total_data)
|
||||
goto bad_param;
|
||||
if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
|
||||
goto bad_param;
|
||||
if (ddisp > state->total_data)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
|
||||
(smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (state->data + ddisp < state->data)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(state->data+ddisp, smb_base(inbuf)+doff,
|
||||
dcnt);
|
||||
}
|
||||
|
||||
if ((state->received_param < state->total_param) ||
|
||||
(state->received_data < state->total_data)) {
|
||||
END_PROFILE(SMBtranss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* construct_reply_common has done us the favor to pre-fill the
|
||||
* command field with SMBtranss which is wrong :-)
|
||||
*/
|
||||
SCVAL(outbuf,smb_com,SMBtrans);
|
||||
|
||||
result = handle_trans(conn, state, outbuf, &outsize);
|
||||
|
||||
DLIST_REMOVE(conn->pending_trans, state);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
|
||||
if ((outsize == 0) || !NT_STATUS_IS_OK(result)) {
|
||||
END_PROFILE(SMBtranss);
|
||||
return(ERROR_DOS(ERRSRV,ERRnosupport));
|
||||
}
|
||||
|
||||
END_PROFILE(SMBtranss);
|
||||
return(outsize);
|
||||
|
||||
bad_param:
|
||||
|
||||
DEBUG(0,("reply_transs: invalid trans parameters\n"));
|
||||
DLIST_REMOVE(conn->pending_trans, state);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtranss);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
@ -1811,19 +1811,6 @@ int reply_ntrename(connection_struct *conn,
|
||||
return(outsize);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to an unsolicited SMBNTtranss - just ignore it!
|
||||
****************************************************************************/
|
||||
|
||||
int reply_nttranss(connection_struct *conn,
|
||||
char *inbuf,char *outbuf,int length,int bufsize)
|
||||
{
|
||||
START_PROFILE(SMBnttranss);
|
||||
DEBUG(4,("Ignoring nttranss of length %d\n",length));
|
||||
END_PROFILE(SMBnttranss);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a notify change - queue the request and
|
||||
don't allow a directory to be opened.
|
||||
@ -2719,29 +2706,120 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
|
||||
}
|
||||
#endif /* HAVE_SYS_QUOTAS */
|
||||
|
||||
static int handle_nttrans(connection_struct *conn,
|
||||
struct trans_state *state,
|
||||
char *inbuf, char *outbuf, int size, int bufsize)
|
||||
{
|
||||
int outsize;
|
||||
|
||||
if (Protocol >= PROTOCOL_NT1) {
|
||||
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
|
||||
}
|
||||
|
||||
/* Now we must call the relevant NT_TRANS function */
|
||||
switch(state->call) {
|
||||
case NT_TRANSACT_CREATE:
|
||||
START_PROFILE_NESTED(NT_transact_create);
|
||||
outsize = call_nt_transact_create(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data,
|
||||
state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_create);
|
||||
break;
|
||||
case NT_TRANSACT_IOCTL:
|
||||
START_PROFILE_NESTED(NT_transact_ioctl);
|
||||
outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_ioctl);
|
||||
break;
|
||||
case NT_TRANSACT_SET_SECURITY_DESC:
|
||||
START_PROFILE_NESTED(NT_transact_set_security_desc);
|
||||
outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_set_security_desc);
|
||||
break;
|
||||
case NT_TRANSACT_NOTIFY_CHANGE:
|
||||
START_PROFILE_NESTED(NT_transact_notify_change);
|
||||
outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_notify_change);
|
||||
break;
|
||||
case NT_TRANSACT_RENAME:
|
||||
START_PROFILE_NESTED(NT_transact_rename);
|
||||
outsize = call_nt_transact_rename(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_rename);
|
||||
break;
|
||||
|
||||
case NT_TRANSACT_QUERY_SECURITY_DESC:
|
||||
START_PROFILE_NESTED(NT_transact_query_security_desc);
|
||||
outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_query_security_desc);
|
||||
break;
|
||||
#ifdef HAVE_SYS_QUOTAS
|
||||
case NT_TRANSACT_GET_USER_QUOTA:
|
||||
START_PROFILE_NESTED(NT_transact_get_user_quota);
|
||||
outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_get_user_quota);
|
||||
break;
|
||||
case NT_TRANSACT_SET_USER_QUOTA:
|
||||
START_PROFILE_NESTED(NT_transact_set_user_quota);
|
||||
outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
|
||||
size, bufsize,
|
||||
(char **)&state->setup, state->setup_count,
|
||||
&state->param, state->total_param,
|
||||
&state->data, state->total_data, state->max_data_return);
|
||||
END_PROFILE_NESTED(NT_transact_set_user_quota);
|
||||
break;
|
||||
#endif /* HAVE_SYS_QUOTAS */
|
||||
default:
|
||||
/* Error in request */
|
||||
DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n",
|
||||
state->call));
|
||||
return ERROR_DOS(ERRSRV,ERRerror);
|
||||
}
|
||||
return outsize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a SMBNTtrans.
|
||||
****************************************************************************/
|
||||
|
||||
int reply_nttrans(connection_struct *conn,
|
||||
char *inbuf,char *outbuf,int length,int bufsize)
|
||||
char *inbuf,char *outbuf,int size,int bufsize)
|
||||
{
|
||||
int outsize = 0;
|
||||
uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
|
||||
#if 0 /* Not used. */
|
||||
uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
|
||||
uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
|
||||
#endif /* Not used. */
|
||||
uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
|
||||
uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
|
||||
uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
|
||||
uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
|
||||
uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
|
||||
uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
|
||||
uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */
|
||||
uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount);
|
||||
uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset);
|
||||
uint32 dscnt = IVAL(inbuf,smb_nt_DataCount);
|
||||
uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset);
|
||||
|
||||
uint16 function_code = SVAL( inbuf, smb_nt_Function);
|
||||
char *params = NULL, *data = NULL, *setup = NULL;
|
||||
uint32 num_params_sofar, num_data_sofar;
|
||||
NTSTATUS result;
|
||||
struct trans_state *state;
|
||||
|
||||
START_PROFILE(SMBnttrans);
|
||||
|
||||
if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
|
||||
@ -2749,319 +2827,269 @@ int reply_nttrans(connection_struct *conn,
|
||||
return ERROR_DOS(ERRSRV,ERRaccess);
|
||||
}
|
||||
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
|
||||
SVAL(inbuf, smb_mid)))) {
|
||||
DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
|
||||
END_PROFILE(SMBnttrans);
|
||||
return ERROR_NT(result);
|
||||
}
|
||||
|
||||
if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
|
||||
END_PROFILE(SMBnttrans);
|
||||
return ERROR_DOS(ERRSRV,ERRaccess);
|
||||
}
|
||||
|
||||
state->cmd = SMBnttrans;
|
||||
|
||||
state->mid = SVAL(inbuf,smb_mid);
|
||||
state->vuid = SVAL(inbuf,smb_uid);
|
||||
state->total_data = IVAL(inbuf, smb_nt_TotalDataCount);
|
||||
state->data = NULL;
|
||||
state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
|
||||
state->param = NULL;
|
||||
state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);
|
||||
|
||||
/* setup count is in *words* */
|
||||
state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount);
|
||||
state->call = function_code;
|
||||
|
||||
/*
|
||||
* All nttrans messages we handle have smb_wct == 19 + setup_count.
|
||||
* Ensure this is so as a sanity check.
|
||||
* All nttrans messages we handle have smb_wct == 19 +
|
||||
* state->setup_count. Ensure this is so as a sanity check.
|
||||
*/
|
||||
|
||||
if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) {
|
||||
if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) {
|
||||
DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
|
||||
CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
|
||||
CVAL(inbuf, smb_wct), 19 + (state->setup_count/2)));
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
/* Don't allow more than 128mb for each value. */
|
||||
if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) {
|
||||
if ((state->total_data > (1024*1024*128)) ||
|
||||
(state->total_param > (1024*1024*128))) {
|
||||
END_PROFILE(SMBnttrans);
|
||||
return ERROR_DOS(ERRDOS,ERRnomem);
|
||||
}
|
||||
|
||||
/* Allocate the space for the setup, the maximum needed parameters and data */
|
||||
|
||||
if(setup_count > 0) {
|
||||
setup = (char *)SMB_MALLOC(setup_count);
|
||||
}
|
||||
if (total_parameter_count > 0) {
|
||||
params = (char *)SMB_MALLOC(total_parameter_count);
|
||||
}
|
||||
if (total_data_count > 0) {
|
||||
data = (char *)SMB_MALLOC(total_data_count);
|
||||
}
|
||||
|
||||
if ((total_parameter_count && !params) || (total_data_count && !data) ||
|
||||
(setup_count && !setup)) {
|
||||
SAFE_FREE(setup);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(data);
|
||||
DEBUG(0,("reply_nttrans : Out of memory\n"));
|
||||
END_PROFILE(SMBnttrans);
|
||||
return ERROR_DOS(ERRDOS,ERRnomem);
|
||||
}
|
||||
|
||||
/* Copy the param and data bytes sent with this request into the params buffer */
|
||||
num_params_sofar = parameter_count;
|
||||
num_data_sofar = data_count;
|
||||
|
||||
if (parameter_count > total_parameter_count || data_count > total_data_count)
|
||||
if ((dscnt > state->total_data) || (pscnt > state->total_param))
|
||||
goto bad_param;
|
||||
|
||||
if(setup) {
|
||||
DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
|
||||
if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
|
||||
(smb_nt_SetupStart + setup_count < setup_count)) {
|
||||
if (state->total_data) {
|
||||
/* Can't use talloc here, the core routines do realloc on the
|
||||
* params and data. */
|
||||
if ((state->data = SMB_MALLOC(state->total_data)) == NULL) {
|
||||
DEBUG(0,("reply_nttrans: data malloc fail for %u "
|
||||
"bytes !\n", state->total_data));
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRDOS,ERRnomem));
|
||||
}
|
||||
if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
|
||||
goto bad_param;
|
||||
}
|
||||
if (smb_nt_SetupStart + setup_count > length) {
|
||||
if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
|
||||
(smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
|
||||
dump_data(10, setup, setup_count);
|
||||
}
|
||||
if(params) {
|
||||
DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
|
||||
if ((parameter_offset + parameter_count < parameter_offset) ||
|
||||
(parameter_offset + parameter_count < parameter_count)) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)||
|
||||
(smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
|
||||
dump_data(10, params, parameter_count);
|
||||
}
|
||||
if(data) {
|
||||
DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
|
||||
if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
|
||||
(smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( data, smb_base(inbuf) + data_offset, data_count);
|
||||
dump_data(10, data, data_count);
|
||||
memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
|
||||
}
|
||||
|
||||
srv_signing_trans_start(SVAL(inbuf,smb_mid));
|
||||
if (state->total_param) {
|
||||
/* Can't use talloc here, the core routines do realloc on the
|
||||
* params and data. */
|
||||
if ((state->param = SMB_MALLOC(state->total_param)) == NULL) {
|
||||
DEBUG(0,("reply_nttrans: param malloc fail for %u "
|
||||
"bytes !\n", state->total_param));
|
||||
SAFE_FREE(state->data);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBtrans);
|
||||
return(ERROR_DOS(ERRDOS,ERRnomem));
|
||||
}
|
||||
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
|
||||
(smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
|
||||
if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
|
||||
/* We need to send an interim response then receive the rest
|
||||
of the parameter/data bytes */
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
srv_signing_trans_stop();
|
||||
show_msg(outbuf);
|
||||
if (!send_smb(smbd_server_fd(),outbuf)) {
|
||||
exit_server("reply_nttrans: send_smb failed.");
|
||||
}
|
||||
|
||||
while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
|
||||
BOOL ret;
|
||||
uint32 parameter_displacement;
|
||||
uint32 data_displacement;
|
||||
|
||||
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
|
||||
|
||||
/* We need to re-calcuate the new length after we've read the secondary packet. */
|
||||
length = smb_len(inbuf) + 4;
|
||||
|
||||
/*
|
||||
* The sequence number for the trans reply is always
|
||||
* based on the last secondary received.
|
||||
*/
|
||||
|
||||
srv_signing_trans_start(SVAL(inbuf,smb_mid));
|
||||
|
||||
if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
if(ret) {
|
||||
DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
|
||||
} else {
|
||||
DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
|
||||
(smb_read_error == READ_ERROR) ? "error" : "timeout" ));
|
||||
}
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
/* Revise total_params and total_data in case they have changed downwards */
|
||||
if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) {
|
||||
total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
|
||||
}
|
||||
if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) {
|
||||
total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
|
||||
}
|
||||
|
||||
parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
|
||||
parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
|
||||
parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
|
||||
num_params_sofar += parameter_count;
|
||||
|
||||
data_count = IVAL(inbuf, smb_nts_DataCount);
|
||||
data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
|
||||
data_offset = IVAL(inbuf, smb_nts_DataOffset);
|
||||
num_data_sofar += data_count;
|
||||
|
||||
if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
|
||||
DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
if (parameter_count) {
|
||||
if (parameter_displacement + parameter_count > total_parameter_count) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((parameter_displacement + parameter_count < parameter_displacement) ||
|
||||
(parameter_displacement + parameter_count < parameter_count)) {
|
||||
goto bad_param;
|
||||
}
|
||||
if (parameter_displacement > total_parameter_count) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) ||
|
||||
(smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
|
||||
goto bad_param;
|
||||
}
|
||||
if (parameter_displacement + params < params) {
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( ¶ms[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
|
||||
}
|
||||
|
||||
if (data_count) {
|
||||
if (data_displacement + data_count > total_data_count) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((data_displacement + data_count < data_displacement) ||
|
||||
(data_displacement + data_count < data_count)) {
|
||||
goto bad_param;
|
||||
}
|
||||
if (data_displacement > total_data_count) {
|
||||
goto bad_param;
|
||||
}
|
||||
if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
|
||||
(smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
|
||||
goto bad_param;
|
||||
}
|
||||
if (data_displacement + data < data) {
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
|
||||
}
|
||||
}
|
||||
memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
|
||||
}
|
||||
|
||||
if (Protocol >= PROTOCOL_NT1) {
|
||||
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
|
||||
}
|
||||
state->received_data = dscnt;
|
||||
state->received_param = pscnt;
|
||||
|
||||
/* Now we must call the relevant NT_TRANS function */
|
||||
switch(function_code) {
|
||||
case NT_TRANSACT_CREATE:
|
||||
START_PROFILE_NESTED(NT_transact_create);
|
||||
outsize = call_nt_transact_create(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_create);
|
||||
break;
|
||||
case NT_TRANSACT_IOCTL:
|
||||
START_PROFILE_NESTED(NT_transact_ioctl);
|
||||
outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_ioctl);
|
||||
break;
|
||||
case NT_TRANSACT_SET_SECURITY_DESC:
|
||||
START_PROFILE_NESTED(NT_transact_set_security_desc);
|
||||
outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_set_security_desc);
|
||||
break;
|
||||
case NT_TRANSACT_NOTIFY_CHANGE:
|
||||
START_PROFILE_NESTED(NT_transact_notify_change);
|
||||
outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_notify_change);
|
||||
break;
|
||||
case NT_TRANSACT_RENAME:
|
||||
START_PROFILE_NESTED(NT_transact_rename);
|
||||
outsize = call_nt_transact_rename(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_rename);
|
||||
break;
|
||||
|
||||
case NT_TRANSACT_QUERY_SECURITY_DESC:
|
||||
START_PROFILE_NESTED(NT_transact_query_security_desc);
|
||||
outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_query_security_desc);
|
||||
break;
|
||||
#ifdef HAVE_SYS_QUOTAS
|
||||
case NT_TRANSACT_GET_USER_QUOTA:
|
||||
START_PROFILE_NESTED(NT_transact_get_user_quota);
|
||||
outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_get_user_quota);
|
||||
break;
|
||||
case NT_TRANSACT_SET_USER_QUOTA:
|
||||
START_PROFILE_NESTED(NT_transact_set_user_quota);
|
||||
outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
|
||||
length, bufsize,
|
||||
&setup, setup_count,
|
||||
¶ms, total_parameter_count,
|
||||
&data, total_data_count, max_data_count);
|
||||
END_PROFILE_NESTED(NT_transact_set_user_quota);
|
||||
break;
|
||||
#endif /* HAVE_SYS_QUOTAS */
|
||||
default:
|
||||
/* Error in request */
|
||||
DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code));
|
||||
SAFE_FREE(setup);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(data);
|
||||
if(state->setup_count > 0) {
|
||||
DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
|
||||
state->setup_count));
|
||||
state->setup = TALLOC(state, state->setup_count);
|
||||
if (state->setup == NULL) {
|
||||
DEBUG(0,("reply_nttrans : Out of memory\n"));
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBnttrans);
|
||||
srv_signing_trans_stop();
|
||||
return ERROR_DOS(ERRSRV,ERRerror);
|
||||
return ERROR_DOS(ERRDOS,ERRnomem);
|
||||
}
|
||||
|
||||
if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) ||
|
||||
(smb_nt_SetupStart + state->setup_count < state->setup_count)) {
|
||||
goto bad_param;
|
||||
}
|
||||
if (smb_nt_SetupStart + state->setup_count > size) {
|
||||
goto bad_param;
|
||||
}
|
||||
|
||||
memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
|
||||
dump_data(10, (char *)state->setup, state->setup_count);
|
||||
}
|
||||
|
||||
/* As we do not know how many data packets will need to be
|
||||
returned here the various call_nt_transact_xxxx calls
|
||||
must send their own. Thus a call_nt_transact_xxxx routine only
|
||||
returns a value other than -1 when it wants to send
|
||||
an error packet.
|
||||
*/
|
||||
if ((state->received_data == state->total_data) &&
|
||||
(state->received_param == state->total_param)) {
|
||||
outsize = handle_nttrans(conn, state, inbuf, outbuf,
|
||||
size, bufsize);
|
||||
SAFE_FREE(state->param);
|
||||
SAFE_FREE(state->data);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBnttrans);
|
||||
return outsize;
|
||||
}
|
||||
|
||||
srv_signing_trans_stop();
|
||||
DLIST_ADD(conn->pending_trans, state);
|
||||
|
||||
SAFE_FREE(setup);
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(data);
|
||||
/* We need to send an interim response then receive the rest
|
||||
of the parameter/data bytes */
|
||||
outsize = set_message(outbuf,0,0,True);
|
||||
show_msg(outbuf);
|
||||
END_PROFILE(SMBnttrans);
|
||||
return outsize; /* If a correct response was needed the call_nt_transact_xxxx
|
||||
calls have already sent it. If outsize != -1 then it is
|
||||
returning an error packet. */
|
||||
return outsize;
|
||||
|
||||
bad_param:
|
||||
bad_param:
|
||||
|
||||
srv_signing_trans_stop();
|
||||
SAFE_FREE(params);
|
||||
SAFE_FREE(data);
|
||||
SAFE_FREE(setup);
|
||||
DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBnttrans);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a SMBnttranss
|
||||
****************************************************************************/
|
||||
|
||||
int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
int size,int bufsize)
|
||||
{
|
||||
int outsize = 0;
|
||||
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
|
||||
struct trans_state *state;
|
||||
|
||||
START_PROFILE(SMBnttranss);
|
||||
|
||||
show_msg(inbuf);
|
||||
|
||||
for (state = conn->pending_trans; state != NULL;
|
||||
state = state->next) {
|
||||
if (state->mid == SVAL(inbuf,smb_mid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state == NULL) || (state->cmd != SMBnttrans)) {
|
||||
END_PROFILE(SMBnttranss);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Revise state->total_param and state->total_data in case they have
|
||||
changed downwards */
|
||||
if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) {
|
||||
state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount);
|
||||
}
|
||||
if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) {
|
||||
state->total_data = IVAL(inbuf, smb_nts_TotalDataCount);
|
||||
}
|
||||
|
||||
pcnt = IVAL(inbuf,smb_nts_ParameterCount);
|
||||
poff = IVAL(inbuf, smb_nts_ParameterOffset);
|
||||
pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement);
|
||||
|
||||
dcnt = IVAL(inbuf, smb_nts_DataCount);
|
||||
ddisp = IVAL(inbuf, smb_nts_DataDisplacement);
|
||||
doff = IVAL(inbuf, smb_nts_DataOffset);
|
||||
|
||||
state->received_param += pcnt;
|
||||
state->received_data += dcnt;
|
||||
|
||||
if ((state->received_data > state->total_data) ||
|
||||
(state->received_param > state->total_param))
|
||||
goto bad_param;
|
||||
|
||||
if (pcnt) {
|
||||
if (pdisp+pcnt > state->total_param)
|
||||
goto bad_param;
|
||||
if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
|
||||
goto bad_param;
|
||||
if (pdisp > state->total_param)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
|
||||
(smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (state->param + pdisp < state->param)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(state->param+pdisp,smb_base(inbuf)+poff,
|
||||
pcnt);
|
||||
}
|
||||
|
||||
if (dcnt) {
|
||||
if (ddisp+dcnt > state->total_data)
|
||||
goto bad_param;
|
||||
if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
|
||||
goto bad_param;
|
||||
if (ddisp > state->total_data)
|
||||
goto bad_param;
|
||||
if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
|
||||
(smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
|
||||
goto bad_param;
|
||||
if (state->data + ddisp < state->data)
|
||||
goto bad_param;
|
||||
|
||||
memcpy(state->data+ddisp, smb_base(inbuf)+doff,
|
||||
dcnt);
|
||||
}
|
||||
|
||||
if ((state->received_param < state->total_param) ||
|
||||
(state->received_data < state->total_data)) {
|
||||
END_PROFILE(SMBnttranss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* construct_reply_common has done us the favor to pre-fill the
|
||||
* command field with SMBnttranss which is wrong :-)
|
||||
*/
|
||||
SCVAL(outbuf,smb_com,SMBnttrans);
|
||||
|
||||
outsize = handle_nttrans(conn, state, inbuf, outbuf,
|
||||
size, bufsize);
|
||||
|
||||
DLIST_REMOVE(conn->pending_trans, state);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
|
||||
if (outsize == 0) {
|
||||
END_PROFILE(SMBnttranss);
|
||||
return(ERROR_DOS(ERRSRV,ERRnosupport));
|
||||
}
|
||||
|
||||
END_PROFILE(SMBnttranss);
|
||||
return(outsize);
|
||||
|
||||
bad_param:
|
||||
|
||||
DEBUG(0,("reply_nttranss: invalid trans parameters\n"));
|
||||
DLIST_REMOVE(conn->pending_trans, state);
|
||||
SAFE_FREE(state->data);
|
||||
SAFE_FREE(state->param);
|
||||
TALLOC_FREE(state);
|
||||
END_PROFILE(SMBnttranss);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
@ -505,22 +505,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
|
||||
return receive_smb(smbd_server_fd(), buffer, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Get the next SMB packet, doing the local message processing automatically.
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Only allow 5 outstanding trans requests. We're allocating memory, so
|
||||
* prevent a DoS.
|
||||
*/
|
||||
|
||||
BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
|
||||
NTSTATUS allow_new_trans(struct trans_state *list, int mid)
|
||||
{
|
||||
BOOL got_keepalive;
|
||||
BOOL ret;
|
||||
int count = 0;
|
||||
for (; list != NULL; list = list->next) {
|
||||
|
||||
do {
|
||||
ret = receive_message_or_smb(inbuf,bufsize,timeout);
|
||||
|
||||
got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
|
||||
} while (ret && got_keepalive);
|
||||
if (list->mid == mid) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return ret;
|
||||
count += 1;
|
||||
}
|
||||
if (count > 5) {
|
||||
return NT_STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -611,7 +616,7 @@ static const struct smb_message_struct {
|
||||
/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
|
||||
/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
|
||||
/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
|
||||
/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
|
||||
/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
|
||||
/* 0x27 */ { "SMBioctl",reply_ioctl,0},
|
||||
/* 0x28 */ { "SMBioctls",NULL,AS_USER},
|
||||
/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
|
||||
|
@ -269,10 +269,13 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
|
||||
switch(next_mb_char_size(s)) {
|
||||
case 4:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 3:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 2:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 1:
|
||||
*d++ = *s++;
|
||||
break;
|
||||
@ -374,10 +377,13 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
|
||||
switch(next_mb_char_size(s)) {
|
||||
case 4:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 3:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 2:
|
||||
*d++ = *s++;
|
||||
/*fall through*/
|
||||
case 1:
|
||||
*d++ = *s++;
|
||||
break;
|
||||
@ -2319,7 +2325,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
|
||||
/* ensure we don't overrun the packet size */
|
||||
maxcount = MIN(65535,maxcount);
|
||||
|
||||
if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
SMB_STRUCT_STAT st;
|
||||
SMB_OFF_T size = 0;
|
||||
|
||||
@ -2390,8 +2396,13 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
|
||||
* Note that the requested lock size is unaffected by max_recv.
|
||||
*/
|
||||
|
||||
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
|
||||
(SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
|
||||
status = do_lock_spin(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
(SMB_BIG_UINT)numtoread,
|
||||
(SMB_BIG_UINT)startpos,
|
||||
WRITE_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
#if 0
|
||||
@ -2407,8 +2418,15 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
|
||||
* this smb into a queued request and push it
|
||||
* onto the blocking lock queue.
|
||||
*/
|
||||
if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
|
||||
(SMB_BIG_UINT)numtoread)) {
|
||||
if(push_blocking_lock_request(inbuf, length,
|
||||
fsp,
|
||||
-1,
|
||||
0,
|
||||
SVAL(inbuf,smb_pid),
|
||||
WRITE_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
(SMB_BIG_UINT)startpos,
|
||||
(SMB_BIG_UINT)numtoread)) {
|
||||
END_PROFILE(SMBlockread);
|
||||
return -1;
|
||||
}
|
||||
@ -2486,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
|
||||
|
||||
data = smb_buf(outbuf) + 3;
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
END_PROFILE(SMBread);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -2694,7 +2712,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
|
||||
|
||||
}
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
END_PROFILE(SMBreadX);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -2757,7 +2775,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
SCVAL(inbuf,smb_com,SMBwritec);
|
||||
SCVAL(outbuf,smb_com,SMBwritec);
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwritebraw);
|
||||
return(ERROR_DOS(ERRDOS,ERRlock));
|
||||
}
|
||||
@ -2878,7 +2896,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
|
||||
data = smb_buf(inbuf) + 3;
|
||||
|
||||
if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwriteunlock);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -2900,8 +2918,12 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
}
|
||||
|
||||
if (numtowrite) {
|
||||
status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
|
||||
(SMB_BIG_UINT)startpos);
|
||||
status = do_unlock(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
(SMB_BIG_UINT)numtowrite,
|
||||
(SMB_BIG_UINT)startpos,
|
||||
WINDOWS_LOCK);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
END_PROFILE(SMBwriteunlock);
|
||||
return ERROR_NT(status);
|
||||
@ -2951,7 +2973,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
|
||||
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
|
||||
data = smb_buf(inbuf) + 3;
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwrite);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -3066,7 +3088,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
|
||||
#endif /* LARGE_SMB_OFF_T */
|
||||
}
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwriteX);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -3340,7 +3362,7 @@ int reply_writeclose(connection_struct *conn,
|
||||
mtime = srv_make_unix_date3(inbuf+smb_vwv4);
|
||||
data = smb_buf(inbuf) + 1;
|
||||
|
||||
if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwriteclose);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -3410,7 +3432,13 @@ int reply_lock(connection_struct *conn,
|
||||
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
|
||||
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
|
||||
|
||||
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
|
||||
status = do_lock_spin(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
count,
|
||||
offset,
|
||||
WRITE_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
if (NT_STATUS_V(status)) {
|
||||
#if 0
|
||||
/* Tests using Samba4 against W2K show this call never creates a blocking lock. */
|
||||
@ -3420,7 +3448,14 @@ int reply_lock(connection_struct *conn,
|
||||
* this smb into a queued request and push it
|
||||
* onto the blocking lock queue.
|
||||
*/
|
||||
if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
|
||||
if(push_blocking_lock_request(inbuf, length,
|
||||
fsp,
|
||||
-1,
|
||||
0,
|
||||
SVAL(inbuf,smb_pid),
|
||||
WRITE_LOCK,
|
||||
WINDOWS_LOCK,
|
||||
offset, count)) {
|
||||
END_PROFILE(SMBlock);
|
||||
return -1;
|
||||
}
|
||||
@ -3452,7 +3487,12 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
|
||||
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
|
||||
|
||||
status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
|
||||
status = do_unlock(fsp,
|
||||
SVAL(inbuf,smb_pid),
|
||||
count,
|
||||
offset,
|
||||
WINDOWS_LOCK);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
END_PROFILE(SMBunlock);
|
||||
return ERROR_NT(status);
|
||||
@ -5279,7 +5319,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
"pid %u, file %s\n", (double)offset, (double)count,
|
||||
(unsigned int)lock_pid, fsp->fsp_name ));
|
||||
|
||||
status = do_unlock(fsp,conn,lock_pid,count,offset);
|
||||
status = do_unlock(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
WINDOWS_LOCK);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
END_PROFILE(SMBlockingX);
|
||||
return ERROR_NT(status);
|
||||
@ -5297,6 +5342,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
of smb_lkrng structs */
|
||||
|
||||
for(i = 0; i < (int)num_locks; i++) {
|
||||
enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
|
||||
lock_pid = get_lock_pid( data, i, large_file_format);
|
||||
count = get_lock_count( data, i, large_file_format);
|
||||
offset = get_lock_offset( data, i, large_file_format, &err);
|
||||
@ -5314,9 +5360,14 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
(double)count, (unsigned int)lock_pid,
|
||||
fsp->fsp_name, (int)lock_timeout ));
|
||||
|
||||
status = do_lock_spin(fsp,conn,lock_pid, count,offset,
|
||||
((locktype & 1) ? READ_LOCK:WRITE_LOCK),
|
||||
&my_lock_ctx);
|
||||
status = do_lock_spin(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
lock_type,
|
||||
WINDOWS_LOCK,
|
||||
&my_lock_ctx);
|
||||
|
||||
if (NT_STATUS_V(status)) {
|
||||
/*
|
||||
* Interesting fact found by IFSTEST /t
|
||||
@ -5334,8 +5385,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
* onto the blocking lock queue.
|
||||
*/
|
||||
if(push_blocking_lock_request(inbuf, length,
|
||||
lock_timeout, i,
|
||||
lock_pid, offset,
|
||||
fsp,
|
||||
lock_timeout,
|
||||
i,
|
||||
lock_pid,
|
||||
lock_type,
|
||||
WINDOWS_LOCK,
|
||||
offset,
|
||||
count)) {
|
||||
END_PROFILE(SMBlockingX);
|
||||
return -1;
|
||||
@ -5368,7 +5424,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
return ERROR_DOS(ERRDOS,ERRnoaccess);
|
||||
}
|
||||
|
||||
do_unlock(fsp,conn,lock_pid,count,offset);
|
||||
do_unlock(fsp,
|
||||
lock_pid,
|
||||
count,
|
||||
offset,
|
||||
WINDOWS_LOCK);
|
||||
}
|
||||
END_PROFILE(SMBlockingX);
|
||||
return ERROR_NT(status);
|
||||
@ -5430,7 +5490,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
|
||||
tcount = maxcount;
|
||||
total_read = 0;
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
|
||||
END_PROFILE(SMBreadBmpx);
|
||||
return ERROR_DOS(ERRDOS,ERRlock);
|
||||
}
|
||||
@ -5562,7 +5622,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
not an SMBwritebmpx - set this up now so we don't forget */
|
||||
SCVAL(outbuf,smb_com,SMBwritec);
|
||||
|
||||
if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
|
||||
if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
|
||||
END_PROFILE(SMBwriteBmpx);
|
||||
return(ERROR_DOS(ERRDOS,ERRlock));
|
||||
}
|
||||
|
@ -898,9 +898,8 @@ void build_options(BOOL screen);
|
||||
* If we're interactive we want to set our own process group for
|
||||
* signal management.
|
||||
*/
|
||||
if (interactive && !no_process_group) {
|
||||
if (interactive && !no_process_group)
|
||||
setpgid( (pid_t)0, (pid_t)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!directory_exist(lp_lockdir(), NULL))
|
||||
|
1015
source/smbd/trans2.c
1015
source/smbd/trans2.c
File diff suppressed because it is too large
Load Diff
@ -759,11 +759,21 @@ BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op,
|
||||
BOOL result;
|
||||
|
||||
START_PROFILE(syscall_fcntl_lock);
|
||||
result = fcntl_lock(fd, op, offset, count,type);
|
||||
result = fcntl_lock(fd, op, offset, count, type);
|
||||
END_PROFILE(syscall_fcntl_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
START_PROFILE(syscall_fcntl_getlock);
|
||||
result = fcntl_getlock(fd, poffset, pcount, ptype, ppid);
|
||||
END_PROFILE(syscall_fcntl_getlock);
|
||||
return result;
|
||||
}
|
||||
|
||||
int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
|
||||
{
|
||||
int result;
|
||||
|
@ -95,6 +95,7 @@ static struct vfs_ops default_vfs = {
|
||||
vfswrap_utime,
|
||||
vfswrap_ftruncate,
|
||||
vfswrap_lock,
|
||||
vfswrap_getlock,
|
||||
vfswrap_symlink,
|
||||
vfswrap_readlink,
|
||||
vfswrap_link,
|
||||
|
@ -105,3 +105,110 @@ int main(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
test readdir/unlink pattern that OS/2 uses
|
||||
tridge@samba.org July 2005
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define NUM_FILES 700
|
||||
#define READDIR_SIZE 100
|
||||
#define DELETE_SIZE 4
|
||||
|
||||
#define TESTDIR "test.dir"
|
||||
|
||||
#define FAILED(d) (fprintf(stderr, "Failed for %s - %s\n", d, strerror(errno)), exit(1), 1)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
/* I'm a lazy bastard */
|
||||
system("rm -rf " TESTDIR);
|
||||
mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir");
|
||||
}
|
||||
|
||||
static void create_files()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<NUM_FILES;i++) {
|
||||
char fname[40];
|
||||
sprintf(fname, TESTDIR "/test%u.txt", i);
|
||||
close(open(fname, O_CREAT|O_RDWR, 0600)) == 0 || FAILED("close");
|
||||
}
|
||||
}
|
||||
|
||||
static int os2_delete(DIR *d)
|
||||
{
|
||||
off_t offsets[READDIR_SIZE];
|
||||
int i, j;
|
||||
struct dirent *de;
|
||||
char names[READDIR_SIZE][30];
|
||||
|
||||
/* scan, remembering offsets */
|
||||
for (i=0, de=readdir(d);
|
||||
de && i < READDIR_SIZE;
|
||||
de=readdir(d), i++) {
|
||||
offsets[i] = telldir(d);
|
||||
strcpy(names[i], de->d_name);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* delete the first few */
|
||||
for (j=0; j<MIN(i, DELETE_SIZE); j++) {
|
||||
char fname[40];
|
||||
sprintf(fname, TESTDIR "/%s", names[j]);
|
||||
unlink(fname) == 0 || FAILED("unlink");
|
||||
}
|
||||
|
||||
/* seek to just after the deletion */
|
||||
seekdir(d, offsets[j-1]);
|
||||
|
||||
/* return number deleted */
|
||||
return j;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int total_deleted = 0;
|
||||
DIR *d;
|
||||
struct dirent *de;
|
||||
|
||||
cleanup();
|
||||
create_files();
|
||||
|
||||
d = opendir(TESTDIR);
|
||||
|
||||
/* skip past . and .. */
|
||||
de = readdir(d);
|
||||
strcmp(de->d_name, ".") == 0 || FAILED("match .");
|
||||
de = readdir(d);
|
||||
strcmp(de->d_name, "..") == 0 || FAILED("match ..");
|
||||
|
||||
while (1) {
|
||||
int n = os2_delete(d);
|
||||
if (n == 0) break;
|
||||
total_deleted += n;
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
printf("Deleted %d files of %d\n", total_deleted, NUM_FILES);
|
||||
|
||||
rmdir(TESTDIR) == 0 || FAILED("rmdir");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1203,6 +1203,7 @@ failed:
|
||||
talloc_free(tc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/***********************************************************
|
||||
|
@ -159,9 +159,13 @@ static void print_share_mode(const struct share_mode_entry *e, const char *share
|
||||
}
|
||||
}
|
||||
|
||||
static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid,
|
||||
enum brl_type lock_type,
|
||||
br_off start, br_off size)
|
||||
static void print_brl(SMB_DEV_T dev,
|
||||
SMB_INO_T ino,
|
||||
struct process_id pid,
|
||||
enum brl_type lock_type,
|
||||
enum brl_flavour lock_flav,
|
||||
br_off start,
|
||||
br_off size)
|
||||
{
|
||||
static int count;
|
||||
if (count==0) {
|
||||
|
Loading…
Reference in New Issue
Block a user