summaryrefslogtreecommitdiff
path: root/source/smbd
diff options
context:
space:
mode:
authorbubulle <bubulle@alioth.debian.org>2008-11-01 11:09:46 +0000
committerbubulle <bubulle@alioth.debian.org>2008-11-01 11:09:46 +0000
commita2b71a0141763c20552bb45eeb4cb78c4b513118 (patch)
tree85b64d98387145ea4e00c1b529e1820542a979a3 /source/smbd
parent2203bd59918d6d70515f9dad601cb5c0ef098092 (diff)
downloadsamba-a2b71a0141763c20552bb45eeb4cb78c4b513118.tar.gz
Revert the merge of 3.3.0~pre2 in upstream branch
git-svn-id: svn://svn.debian.org/svn/pkg-samba/branches/samba/upstream@2200 fc4039ab-9d04-0410-8cac-899223bdd6b0
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/change_trust_pw.c8
-rw-r--r--source/smbd/close.c18
-rw-r--r--source/smbd/conn.c41
-rw-r--r--source/smbd/connection.c4
-rw-r--r--source/smbd/dfree.c2
-rw-r--r--source/smbd/dir.c76
-rw-r--r--source/smbd/fake_file.c76
-rw-r--r--source/smbd/file_access.c75
-rw-r--r--source/smbd/filename.c3
-rw-r--r--source/smbd/files.c17
-rw-r--r--source/smbd/ipc.c109
-rw-r--r--source/smbd/lanman.c113
-rw-r--r--source/smbd/mangle_hash.c11
-rw-r--r--source/smbd/message.c13
-rw-r--r--source/smbd/msdfs.c152
-rw-r--r--source/smbd/negprot.c5
-rw-r--r--source/smbd/notify.c6
-rw-r--r--source/smbd/ntquotas.c29
-rw-r--r--source/smbd/nttrans.c85
-rw-r--r--source/smbd/open.c81
-rw-r--r--source/smbd/password.c167
-rw-r--r--source/smbd/pipes.c12
-rw-r--r--source/smbd/posix_acls.c95
-rw-r--r--source/smbd/process.c39
-rw-r--r--source/smbd/reply.c90
-rw-r--r--source/smbd/sec_ctx.c2
-rw-r--r--source/smbd/server.c40
-rw-r--r--source/smbd/service.c470
-rw-r--r--source/smbd/session.c8
-rw-r--r--source/smbd/sesssetup.c52
-rw-r--r--source/smbd/share_access.c26
-rw-r--r--source/smbd/trans2.c106
-rw-r--r--source/smbd/uid.c216
-rw-r--r--source/smbd/utmp.c3
-rw-r--r--source/smbd/vfs.c6
35 files changed, 1208 insertions, 1048 deletions
diff --git a/source/smbd/change_trust_pw.c b/source/smbd/change_trust_pw.c
index 72a72a78b5..4773eeff86 100644
--- a/source/smbd/change_trust_pw.c
+++ b/source/smbd/change_trust_pw.c
@@ -73,9 +73,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
/* Shouldn't we open this with schannel ? JRA. */
- nt_status = cli_rpc_pipe_open_noauth(
- cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe);
- if (!NT_STATUS_IS_OK(nt_status)) {
+ netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &nt_status);
+ if (!netlogon_pipe) {
DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n",
dc_name, nt_errstr(nt_status)));
cli_shutdown(cli);
@@ -83,8 +82,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
goto failed;
}
- nt_status = trust_pw_find_change_and_store_it(
- netlogon_pipe, netlogon_pipe, domain);
+ nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, netlogon_pipe->mem_ctx, domain);
cli_shutdown(cli);
cli = NULL;
diff --git a/source/smbd/close.c b/source/smbd/close.c
index 818b4c70a8..3d3c4cf09e 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -581,7 +581,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
}
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
- conn->server_info->unix_name,fsp->fsp_name,
+ conn->user,fsp->fsp_name,
conn->num_files_open,
nt_errstr(status) ));
@@ -703,6 +703,20 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty
}
/****************************************************************************
+ Close a 'stat file' opened internally.
+****************************************************************************/
+
+static NTSTATUS close_stat(files_struct *fsp)
+{
+ /*
+ * Do the code common to files and directories.
+ */
+ close_filestruct(fsp);
+ file_free(fsp);
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Close a files_struct.
****************************************************************************/
@@ -713,6 +727,8 @@ NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
if(fsp->is_directory) {
status = close_directory(fsp, close_type);
+ } else if (fsp->is_stat) {
+ status = close_stat(fsp);
} else if (fsp->fake_file_handle != NULL) {
status = close_fake_file(fsp);
} else {
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index 7f34d2b8e2..c5a2df4773 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -91,6 +91,7 @@ thinking the server is still available.
****************************************************************************/
connection_struct *conn_new(void)
{
+ TALLOC_CTX *mem_ctx;
connection_struct *conn;
int i;
int find_offset = 1;
@@ -138,18 +139,25 @@ find_again:
return NULL;
}
- if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) ||
- !(conn->params = TALLOC_P(conn, struct share_params))) {
+ if ((mem_ctx=talloc_init("connection_struct"))==NULL) {
+ DEBUG(0,("talloc_init(connection_struct) failed!\n"));
+ return NULL;
+ }
+
+ if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) ||
+ !(conn->params = TALLOC_P(mem_ctx, struct share_params))) {
DEBUG(0,("TALLOC_ZERO() failed!\n"));
- TALLOC_FREE(conn);
+ TALLOC_FREE(mem_ctx);
return NULL;
}
+ conn->mem_ctx = mem_ctx;
conn->cnum = i;
bitmap_set(bmap, i);
num_open++;
+ string_set(&conn->user,"");
string_set(&conn->dirpath,"");
string_set(&conn->connectpath,"");
string_set(&conn->origpath,"");
@@ -161,19 +169,16 @@ find_again:
/****************************************************************************
Close all conn structures.
-return true if any were closed
****************************************************************************/
-bool conn_close_all(void)
+
+void conn_close_all(void)
{
connection_struct *conn, *next;
- bool ret = false;
for (conn=Connections;conn;conn=next) {
next=conn->next;
set_current_service(conn, 0, True);
close_cnum(conn, conn->vuid);
- ret = true;
}
- return ret;
}
/****************************************************************************
@@ -228,15 +233,24 @@ bool conn_idle_all(time_t t)
Clear a vuid out of the validity cache, and as the 'owner' of a connection.
****************************************************************************/
-void conn_clear_vuid_caches(uint16_t vuid)
+void conn_clear_vuid_cache(uint16 vuid)
{
connection_struct *conn;
+ unsigned int i;
for (conn=Connections;conn;conn=conn->next) {
if (conn->vuid == vuid) {
conn->vuid = UID_FIELD_INVALID;
}
- conn_clear_vuid_cache(conn, vuid);
+
+ for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
+ if (conn->vuid_cache.array[i].vuid == vuid) {
+ struct vuid_cache_entry *ent = &conn->vuid_cache.array[i];
+ ent->vuid = UID_FIELD_INVALID;
+ ent->read_only = False;
+ ent->admin_user = False;
+ }
+ }
}
}
@@ -247,13 +261,14 @@ void conn_clear_vuid_caches(uint16_t vuid)
void conn_free_internal(connection_struct *conn)
{
vfs_handle_struct *handle = NULL, *thandle = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
struct trans_state *state = NULL;
/* Free vfs_connection_struct */
handle = conn->vfs_handles;
while(handle) {
- thandle = handle->next;
DLIST_REMOVE(conn->vfs_handles, handle);
+ thandle = handle->next;
if (handle->free_data)
handle->free_data(&handle->data);
handle = thandle;
@@ -271,12 +286,14 @@ void conn_free_internal(connection_struct *conn)
free_namearray(conn->veto_oplock_list);
free_namearray(conn->aio_write_behind_list);
+ string_free(&conn->user);
string_free(&conn->dirpath);
string_free(&conn->connectpath);
string_free(&conn->origpath);
+ mem_ctx = conn->mem_ctx;
ZERO_STRUCTP(conn);
- talloc_destroy(conn);
+ talloc_destroy(mem_ctx);
}
/****************************************************************************
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 8dd5964f5f..d7063c9989 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -152,8 +152,8 @@ bool claim_connection(connection_struct *conn, const char *name,
crec.pid = procid_self();
crec.cnum = conn?conn->cnum:-1;
if (conn) {
- crec.uid = conn->server_info->utok.uid;
- crec.gid = conn->server_info->utok.gid;
+ crec.uid = conn->uid;
+ crec.gid = conn->gid;
strlcpy(crec.servicename, lp_servicename(SNUM(conn)),
sizeof(crec.servicename));
}
diff --git a/source/smbd/dfree.c b/source/smbd/dfree.c
index 1ddcd48d40..9e7f18a130 100644
--- a/source/smbd/dfree.c
+++ b/source/smbd/dfree.c
@@ -206,7 +206,7 @@ SMB_BIG_UINT get_dfree_info(connection_struct *conn,
/* No cached info or time to refresh. */
if (!dfc) {
- dfc = TALLOC_P(conn, struct dfree_cached_info);
+ dfc = TALLOC_P(conn->mem_ctx, struct dfree_cached_info);
if (!dfc) {
return dfree_ret;
}
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index c2735c032a..604db984af 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -24,6 +24,8 @@
This module implements directory related functions for Samba.
*/
+extern struct current_user current_user;
+
/* "Special" directory offsets. */
#define END_OF_DIRECTORY_OFFSET ((long)-1)
#define START_OF_DIRECTORY_OFFSET ((long)0)
@@ -921,8 +923,13 @@ bool get_dir_entry(TALLOC_CTX *ctx,
use it for anything security sensitive.
********************************************************************/
-static bool user_can_read_file(connection_struct *conn, char *name)
+static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
{
+ SEC_DESC *psd = NULL;
+ files_struct *fsp;
+ NTSTATUS status;
+ uint32 access_granted;
+
/*
* If user is a member of the Admin group
* we never hide files from them.
@@ -932,7 +939,38 @@ static bool user_can_read_file(connection_struct *conn, char *name)
return True;
}
- return can_access_file_acl(conn, name, FILE_READ_DATA);
+ SMB_ASSERT(VALID_STAT(*pst));
+
+ /* Pseudo-open the file (note - no fd's created). */
+
+ if(S_ISDIR(pst->st_mode)) {
+ status = open_directory(conn, NULL, name, pst,
+ READ_CONTROL_ACCESS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0, /* no create options. */
+ FILE_ATTRIBUTE_DIRECTORY,
+ NULL, &fsp);
+ } else {
+ status = open_file_stat(conn, NULL, name, pst, &fsp);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+
+ /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
+ status = SMB_VFS_FGET_NT_ACL(fsp,
+ (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
+ close_file(fsp, NORMAL_CLOSE);
+
+ /* No access if SD get failed. */
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+
+ return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
+ &access_granted, &status);
}
/*******************************************************************
@@ -944,6 +982,12 @@ static bool user_can_read_file(connection_struct *conn, char *name)
static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
{
+ SEC_DESC *psd = NULL;
+ files_struct *fsp;
+ int info;
+ NTSTATUS status;
+ uint32 access_granted;
+
/*
* If user is a member of the Admin group
* we never hide files from them.
@@ -959,9 +1003,33 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
if(S_ISDIR(pst->st_mode)) {
return True;
+ } else {
+ status = open_file_ntcreate(conn, NULL, name, pst,
+ FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ INTERNAL_OPEN_ONLY,
+ &info, &fsp);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
+
+ /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
+ status = SMB_VFS_FGET_NT_ACL(fsp,
+ (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
+ close_file(fsp, NORMAL_CLOSE);
+
+ /* No access if SD get failed. */
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
}
- return can_write_to_file(conn, name, pst);
+ return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
+ &access_granted, &status);
}
/*******************************************************************
@@ -1035,7 +1103,7 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char *
}
/* Honour _hide unreadable_ option */
- if (hide_unreadable && !user_can_read_file(conn, entry)) {
+ if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
SAFE_FREE(entry);
return False;
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index 8dd9abee1a..31fe030f46 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -19,52 +19,54 @@
#include "includes.h"
-struct fake_file_type {
- const char *name;
- enum FAKE_FILE_TYPE type;
- void *(*init_pd)(TALLOC_CTX *mem_ctx);
-};
+extern struct current_user current_user;
-static struct fake_file_type fake_files[] = {
+static FAKE_FILE fake_files[] = {
#ifdef WITH_QUOTAS
- {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle},
+ {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle},
#endif /* WITH_QUOTAS */
- {NULL, FAKE_FILE_TYPE_NONE, NULL}
+ {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL }
};
/****************************************************************************
Create a fake file handle
****************************************************************************/
-static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type)
+static struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
{
- struct fake_file_handle *fh = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
+ FAKE_FILE_HANDLE *fh = NULL;
int i;
- for (i=0; fake_files[i].name!=NULL; i++) {
+ for (i=0;fake_files[i].name!=NULL;i++) {
if (fake_files[i].type==type) {
- break;
- }
- }
+ DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
- if (fake_files[i].name == NULL) {
- return NULL;
- }
+ if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) {
+ DEBUG(0,("talloc_init(fake_file_handle) failed.\n"));
+ return NULL;
+ }
- DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
+ if ((fh =TALLOC_ZERO_P(mem_ctx, FAKE_FILE_HANDLE))==NULL) {
+ DEBUG(0,("TALLOC_ZERO() failed.\n"));
+ talloc_destroy(mem_ctx);
+ return NULL;
+ }
- fh = talloc(NULL, struct fake_file_handle);
- if (fh == NULL) {
- DEBUG(0,("TALLOC_ZERO() failed.\n"));
- return NULL;
- }
+ fh->type = type;
+ fh->mem_ctx = mem_ctx;
- fh->type = type;
+ if (fake_files[i].init_pd) {
+ fh->pd = fake_files[i].init_pd(fh->mem_ctx);
+ }
- if (fake_files[i].init_pd) {
- fh->private_data = fake_files[i].init_pd(fh);
+ fh->free_pd = fake_files[i].free_pd;
+
+ return fh;
+ }
}
- return fh;
+
+ return NULL;
}
/****************************************************************************
@@ -99,7 +101,6 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname)
****************************************************************************/
NTSTATUS open_fake_file(connection_struct *conn,
- uint16_t current_vuid,
enum FAKE_FILE_TYPE fake_file_type,
const char *fname,
uint32 access_mask,
@@ -109,11 +110,10 @@ NTSTATUS open_fake_file(connection_struct *conn,
NTSTATUS status;
/* access check */
- if (conn->server_info->utok.uid != 0) {
+ if (current_user.ut.uid != 0) {
DEBUG(3, ("open_fake_file_shared: access_denied to "
"service[%s] file[%s] user[%s]\n",
- lp_servicename(SNUM(conn)), fname,
- conn->server_info->unix_name));
+ lp_servicename(SNUM(conn)),fname,conn->user));
return NT_STATUS_ACCESS_DENIED;
}
@@ -128,7 +128,7 @@ NTSTATUS open_fake_file(connection_struct *conn,
fsp->conn = conn;
fsp->fh->fd = -1;
- fsp->vuid = current_vuid;
+ fsp->vuid = current_user.vuid;
fsp->fh->pos = -1;
fsp->can_lock = False; /* Should this be true ? - No, JRA */
fsp->access_mask = access_mask;
@@ -146,12 +146,18 @@ NTSTATUS open_fake_file(connection_struct *conn,
return NT_STATUS_OK;
}
-void destroy_fake_file_handle(struct fake_file_handle **fh)
+void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
{
- if (!fh) {
+ if (!fh||!(*fh)) {
return;
}
- TALLOC_FREE(*fh);
+
+ if ((*fh)->free_pd) {
+ (*fh)->free_pd(&(*fh)->pd);
+ }
+
+ talloc_destroy((*fh)->mem_ctx);
+ (*fh) = NULL;
}
NTSTATUS close_fake_file(files_struct *fsp)
diff --git a/source/smbd/file_access.c b/source/smbd/file_access.c
index 84c993d06b..964d1af258 100644
--- a/source/smbd/file_access.c
+++ b/source/smbd/file_access.c
@@ -20,14 +20,13 @@
#include "includes.h"
+extern struct current_user current_user;
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_ACLS
-/**
- * Security descriptor / NT Token level access check function.
- */
-bool can_access_file_acl(struct connection_struct *conn,
- const char * fname,
+static bool can_access_file_acl(struct connection_struct *conn,
+ const char * fname, SMB_STRUCT_STAT *psbuf,
uint32_t access_mask)
{
bool result;
@@ -45,7 +44,7 @@ bool can_access_file_acl(struct connection_struct *conn,
return false;
}
- result = se_access_check(secdesc, conn->server_info->ptok,
+ result = se_access_check(secdesc, current_user.nt_user_token,
access_mask, &access_granted, &status);
TALLOC_FREE(secdesc);
return result;
@@ -82,11 +81,16 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
if (!S_ISDIR(sbuf.st_mode)) {
return False;
}
- if (conn->server_info->utok.uid == 0 || conn->admin_user) {
+ if (current_user.ut.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
+ /* Check primary owner write access. */
+ if (current_user.ut.uid == sbuf.st_uid) {
+ return (sbuf.st_mode & S_IWUSR) ? True : False;
+ }
+
#ifdef S_ISVTX
/* sticky bit means delete only by owner or root. */
if (sbuf.st_mode & S_ISVTX) {
@@ -104,7 +108,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
* for bug #3348. Don't assume owning sticky bit
* directory means write access allowed.
*/
- if (conn->server_info->utok.uid != sbuf_file.st_uid) {
+ if (current_user.ut.uid != sbuf_file.st_uid) {
return False;
}
}
@@ -112,21 +116,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
/* now for ACL checks */
- /*
- * There's two ways to get the permission to delete a file: First by
- * having the DELETE bit on the file itself and second if that does
- * not help, by the DELETE_CHILD bit on the containing directory.
- *
- * Here we check the other way round because with just posix
- * permissions looking at the file itself will never grant DELETE, so
- * by looking at the directory first we save one get_acl call.
- */
-
- if (can_access_file_acl(conn, dname, FILE_DELETE_CHILD)) {
- return true;
- }
-
- return can_access_file_acl(conn, fname, DELETE_ACCESS);
+ return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA);
}
/****************************************************************************
@@ -135,7 +125,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
Note this doesn't take into account share write permissions.
****************************************************************************/
-bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
+bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
{
if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
return False;
@@ -144,10 +134,10 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT
/* some fast paths first */
- DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n",
+ DEBUG(10,("can_access_file: requesting 0x%x on file %s\n",
(unsigned int)access_mask, fname ));
- if (conn->server_info->utok.uid == 0 || conn->admin_user) {
+ if (current_user.ut.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
@@ -160,7 +150,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT
}
/* Check primary owner access. */
- if (conn->server_info->utok.uid == psbuf->st_uid) {
+ if (current_user.ut.uid == psbuf->st_uid) {
switch (access_mask) {
case FILE_READ_DATA:
return (psbuf->st_mode & S_IRUSR) ? True : False;
@@ -180,7 +170,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT
/* now for ACL checks */
- return can_access_file_acl(conn, fname, access_mask);
+ return can_access_file_acl(conn, fname, psbuf, access_mask);
}
/****************************************************************************
@@ -190,33 +180,6 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT
bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
{
- return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA);
+ return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA);
}
-/****************************************************************************
- Check for an existing default Windows ACL on a directory.
-****************************************************************************/
-
-bool directory_has_default_acl(connection_struct *conn, const char *fname)
-{
- /* returns talloced off tos. */
- struct security_descriptor *secdesc = NULL;
- unsigned int i;
- NTSTATUS status = SMB_VFS_GET_NT_ACL(conn, fname,
- DACL_SECURITY_INFORMATION, &secdesc);
-
- if (!NT_STATUS_IS_OK(status) || secdesc == NULL) {
- return false;
- }
-
- for (i = 0; i < secdesc->dacl->num_aces; i++) {
- struct security_ace *psa = &secdesc->dacl->aces[i];
- if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
- SEC_ACE_FLAG_CONTAINER_INHERIT)) {
- TALLOC_FREE(secdesc);
- return true;
- }
- }
- TALLOC_FREE(secdesc);
- return false;
-}
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index 562f1e8d94..41a0b9296a 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -101,7 +101,8 @@ get any fatal errors that should immediately terminate the calling
SMB processing whilst resolving.
If the saved_last_component != 0, then the unmodified last component
-of the pathname is returned there. If saved_last_component == 0 then nothing
+of the pathname is returned there. This is used in an exceptional
+case in reply_mv (so far). If saved_last_component == 0 then nothing
is returned there.
If last_component_wcard is true then a MS wildcard was detected and
diff --git a/source/smbd/files.c b/source/smbd/files.c
index 8d06e20f81..d6e91c67be 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -122,12 +122,10 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result)
chain_fsp = fsp;
- /* A new fsp invalidates the positive and
- negative fsp_fi_cache as the new fsp is pushed
- at the start of the list and we search from
- a cache hit to the *end* of the list. */
-
- ZERO_STRUCT(fsp_fi_cache);
+ /* A new fsp invalidates a negative fsp_fi_cache. */
+ if (fsp_fi_cache.fsp == NULL) {
+ ZERO_STRUCT(fsp_fi_cache);
+ }
*result = fsp;
return NT_STATUS_OK;
@@ -328,7 +326,8 @@ files_struct *file_find_di_first(struct file_id id)
fsp_fi_cache.id = id;
for (fsp=Files;fsp;fsp=fsp->next) {
- if (file_id_equal(&fsp->file_id, &id)) {
+ if ( fsp->fh->fd != -1 &&
+ file_id_equal(&fsp->file_id, &id)) {
/* Setup positive cache. */
fsp_fi_cache.fsp = fsp;
return fsp;
@@ -349,7 +348,8 @@ files_struct *file_find_di_next(files_struct *start_fsp)
files_struct *fsp;
for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
- if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
+ if ( fsp->fh->fd != -1 &&
+ file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
return fsp;
}
}
@@ -539,6 +539,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp,
dup_fsp->print_file = fsp->print_file;
dup_fsp->modified = fsp->modified;
dup_fsp->is_directory = fsp->is_directory;
+ dup_fsp->is_stat = fsp->is_stat;
dup_fsp->aio_write_behind = fsp->aio_write_behind;
string_set(&dup_fsp->fsp_name,fsp->fsp_name);
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index f4c45999ba..6961a5caf1 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -81,7 +81,8 @@ static void copy_trans_params_and_data(char *outbuf, int align,
Send a trans reply.
****************************************************************************/
-void send_trans_reply(connection_struct *conn, const uint8_t *inbuf,
+void send_trans_reply(connection_struct *conn,
+ struct smb_request *req,
char *rparam, int rparam_len,
char *rdata, int rdata_len,
bool buffer_too_large)
@@ -90,7 +91,6 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf,
int tot_data_sent = 0;
int tot_param_sent = 0;
int align;
- char *outbuf;
int ldata = rdata ? rdata_len : 0;
int lparam = rparam ? rparam_len : 0;
@@ -103,48 +103,47 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf,
align = ((this_lparam)%4);
- if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf,
- 10, 1+align+this_ldata+this_lparam)) {
- smb_panic("could not allocate outbuf");
- }
+ reply_outbuf(req, 10, 1+align+this_ldata+this_lparam);
- copy_trans_params_and_data(outbuf, align,
+ copy_trans_params_and_data((char *)req->outbuf, align,
rparam, tot_param_sent, this_lparam,
rdata, tot_data_sent, this_ldata);
- SSVAL(outbuf,smb_vwv0,lparam);
- SSVAL(outbuf,smb_vwv1,ldata);
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
- SSVAL(outbuf,smb_vwv5,0);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,
- outbuf));
- SSVAL(outbuf,smb_vwv8,0);
- SSVAL(outbuf,smb_vwv9,0);
+ SSVAL(req->outbuf,smb_vwv0,lparam);
+ SSVAL(req->outbuf,smb_vwv1,ldata);
+ SSVAL(req->outbuf,smb_vwv3,this_lparam);
+ SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1,
+ req->outbuf));
+ SSVAL(req->outbuf,smb_vwv5,0);
+ SSVAL(req->outbuf,smb_vwv6,this_ldata);
+ SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+
+ this_lparam+align,
+ req->outbuf));
+ SSVAL(req->outbuf,smb_vwv8,0);
+ SSVAL(req->outbuf,smb_vwv9,0);
if (buffer_too_large) {
- error_packet_set((char *)outbuf, ERRDOS, ERRmoredata,
- STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__);
+ error_packet_set((char *)req->outbuf,
+ ERRDOS, ERRmoredata,
+ STATUS_BUFFER_OVERFLOW,
+ __LINE__, __FILE__);
}
- show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(), (char *)outbuf,
- IS_CONN_ENCRYPTED(conn))) {
+ show_msg((char *)req->outbuf);
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
- }
- TALLOC_FREE(outbuf);
+ TALLOC_FREE(req->outbuf);
tot_data_sent = this_ldata;
tot_param_sent = this_lparam;
while (tot_data_sent < ldata || tot_param_sent < lparam)
{
- this_lparam = MIN(lparam-tot_param_sent,
- max_send - 500); /* hack */
- this_ldata = MIN(ldata -tot_data_sent,
- max_send - (500+this_lparam));
+ this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
+ this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
if(this_lparam < 0)
this_lparam = 0;
@@ -154,39 +153,39 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf,
align = (this_lparam%4);
- if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf,
- 10, 1+align+this_ldata+this_lparam)) {
- smb_panic("could not allocate outbuf");
- }
+ reply_outbuf(req, 10, 1+this_ldata+this_lparam+align);
- copy_trans_params_and_data(outbuf, align,
+ copy_trans_params_and_data((char *)req->outbuf, align,
rparam, tot_param_sent, this_lparam,
rdata, tot_data_sent, this_ldata);
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
- SSVAL(outbuf,smb_vwv5,tot_param_sent);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,
- smb_offset(smb_buf(outbuf)+1+this_lparam+align, outbuf));
- SSVAL(outbuf,smb_vwv8,tot_data_sent);
- SSVAL(outbuf,smb_vwv9,0);
+ SSVAL(req->outbuf,smb_vwv3,this_lparam);
+ SSVAL(req->outbuf,smb_vwv4,smb_offset(smb_buf(req->outbuf)+1,
+ req->outbuf));
+ SSVAL(req->outbuf,smb_vwv5,tot_param_sent);
+ SSVAL(req->outbuf,smb_vwv6,this_ldata);
+ SSVAL(req->outbuf,smb_vwv7,smb_offset(smb_buf(req->outbuf)+1+
+ this_lparam+align,
+ req->outbuf));
+ SSVAL(req->outbuf,smb_vwv8,tot_data_sent);
+ SSVAL(req->outbuf,smb_vwv9,0);
if (buffer_too_large) {
- error_packet_set(outbuf, ERRDOS, ERRmoredata,
+ error_packet_set((char *)req->outbuf,
+ ERRDOS, ERRmoredata,
STATUS_BUFFER_OVERFLOW,
__LINE__, __FILE__);
}
- show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(), outbuf,
- IS_CONN_ENCRYPTED(conn)))
- exit_server_cleanly("send_trans_reply: srv_send_smb "
- "failed.");
+ show_msg((char *)req->outbuf);
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
tot_data_sent += this_ldata;
tot_param_sent += this_lparam;
- TALLOC_FREE(outbuf);
+ TALLOC_FREE(req->outbuf);
}
}
@@ -213,8 +212,7 @@ static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req
return;
}
- send_trans_reply(conn, req->inbuf, NULL, 0, rdata, data_len,
- is_data_outstanding);
+ send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding);
SAFE_FREE(rdata);
return;
}
@@ -238,7 +236,7 @@ static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_s
if (wait_rpc_pipe_hnd_state(p, priority)) {
/* now send the reply */
- send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
api_no_reply(conn,req);
@@ -264,7 +262,7 @@ static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_s
if (set_rpc_pipe_hnd_state(p, id)) {
/* now send the reply */
- send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
api_no_reply(conn,req);
@@ -286,7 +284,7 @@ static void api_no_reply(connection_struct *conn, struct smb_request *req)
DEBUG(3,("Unsupported API fd command\n"));
/* now send the reply */
- send_trans_reply(conn, req->inbuf, rparam, 4, NULL, 0, False);
+ send_trans_reply(conn, req, rparam, 4, NULL, 0, False);
return;
}
@@ -328,8 +326,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
/* Win9x does this call with a unicode pipe name, not a pnum. */
/* Just return success for now... */
DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
- send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0,
- False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
@@ -528,7 +525,7 @@ void reply_trans(struct smb_request *req)
return;
}
- if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
DEBUG(0, ("talloc failed\n"));
reply_nterror(req, NT_STATUS_NO_MEMORY);
END_PROFILE(SMBtrans);
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index fe1d766b9d..6fa4f9698d 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -27,6 +27,9 @@
#include "includes.h"
+extern struct current_user current_user;
+extern userdom_struct current_user_info;
+
#ifdef CHECK_TYPES
#undef CHECK_TYPES
#endif
@@ -98,11 +101,11 @@ static int CopyExpanded(connection_struct *conn,
}
buf = talloc_sub_advanced(ctx,
lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
+ conn->user,
conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ conn->gid,
+ get_current_username(),
+ current_user_info.domain,
buf);
if (!buf) {
*p_space_remaining = 0;
@@ -149,11 +152,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
}
buf = talloc_sub_advanced(ctx,
lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
+ conn->user,
conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ conn->gid,
+ get_current_username(),
+ current_user_info.domain,
buf);
if (!buf) {
return 0;
@@ -179,11 +182,11 @@ static char *Expand(connection_struct *conn, int snum, char *s)
}
return talloc_sub_advanced(ctx,
lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
+ conn->user,
conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ conn->gid,
+ get_current_username(),
+ current_user_info.domain,
buf);
}
@@ -1893,7 +1896,6 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
unsigned int offset;
int snum;
int res = ERRunsup;
- size_t converted_size;
if (!str1 || !str2 || !p) {
return False;
@@ -1954,13 +1956,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
return False;
}
- if (!pull_ascii_talloc(talloc_tos(), &pathname,
- offset ? (data+offset) : "", &converted_size))
- {
- DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
- strerror(errno)));
- }
-
+ pull_ascii_talloc(talloc_tos(), &pathname, offset? (data+offset) : "");
if (!pathname) {
return false;
}
@@ -2680,15 +2676,15 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
switch (function) {
case 81: /* delete */
- if (print_job_delete(conn->server_info, snum, jobid, &werr))
+ if (print_job_delete(&current_user, snum, jobid, &werr))
errcode = NERR_Success;
break;
case 82: /* pause */
- if (print_job_pause(conn->server_info, snum, jobid, &werr))
+ if (print_job_pause(&current_user, snum, jobid, &werr))
errcode = NERR_Success;
break;
case 83: /* resume */
- if (print_job_resume(conn->server_info, snum, jobid, &werr))
+ if (print_job_resume(&current_user, snum, jobid, &werr))
errcode = NERR_Success;
break;
}
@@ -2749,19 +2745,13 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
switch (function) {
case 74: /* Pause queue */
- if (print_queue_pause(conn->server_info, snum, &werr)) {
- errcode = NERR_Success;
- }
+ if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
break;
case 75: /* Resume queue */
- if (print_queue_resume(conn->server_info, snum, &werr)) {
- errcode = NERR_Success;
- }
+ if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
break;
case 103: /* Purge */
- if (print_queue_purge(conn->server_info, snum, &werr)) {
- errcode = NERR_Success;
- }
+ if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
break;
}
@@ -3008,15 +2998,14 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
SIVAL(p,6,0);
} else {
SIVAL(p,6,PTR_DIFF(p2,*rdata));
- comment = talloc_sub_advanced(
- ctx,
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
- comment);
+ comment = talloc_sub_advanced(ctx,
+ lp_servicename(SNUM(conn)),
+ conn->user,
+ conn->connectpath,
+ conn->gid,
+ get_current_username(),
+ current_user_info.domain,
+ comment);
if (comment) {
return false;
}
@@ -3115,7 +3104,7 @@ static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
+ strlcpy(p2,current_user_info.smb_name,PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3349,9 +3338,8 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
Don't depend on vuser being non-null !!. JRA */
user_struct *vuser = get_valid_user_struct(vuid);
if(vuser != NULL) {
- DEBUG(3,(" Username of UID %d is %s\n",
- (int)vuser->server_info->utok.uid,
- vuser->server_info->unix_name));
+ DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
+ vuser->user.unix_name));
}
if (!str1 || !str2 || !UserName || !p) {
@@ -3424,9 +3412,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
/* EEK! the cifsrap.txt doesn't have this in!!!! */
SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
- strlcpy(p2,((vuser != NULL)
- ? pdb_get_fullname(vuser->server_info->sam_account)
- : UserName),PTR_DIFF(endp,p2));
+ strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3434,17 +3420,12 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
}
if (uLevel == 11) {
- const char *homedir = "";
- if (vuser != NULL) {
- homedir = pdb_get_homedir(
- vuser->server_info->sam_account);
- }
/* modelled after NTAS 3.51 reply */
SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
SIVALS(p,usri11_password_age,-1); /* password age */
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
- strlcpy(p2, homedir, PTR_DIFF(endp,p2));
+ strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3495,9 +3476,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
SSVAL(p,42,
conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
- strlcpy(p2, vuser ? pdb_get_homedir(
- vuser->server_info->sam_account) : "",
- PTR_DIFF(endp,p2));
+ strlcpy(p2, vuser && vuser->homedir ? vuser->homedir : "",PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3506,9 +3485,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
*p2++ = 0;
SSVAL(p,52,0); /* flags */
SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
- strlcpy(p2, vuser ? pdb_get_logon_script(
- vuser->server_info->sam_account) : "",
- PTR_DIFF(endp,p2));
+ strlcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "",PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3516,9 +3493,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
if (uLevel == 2) {
SIVAL(p,60,0); /* auth_flags */
SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
- strlcpy(p2,((vuser != NULL)
- ? pdb_get_fullname(vuser->server_info->sam_account)
- : UserName),PTR_DIFF(endp,p2));
+ strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2));
p2 = skip_string(*rdata,*rdata_len,p2);
if (!p2) {
return False;
@@ -3605,9 +3580,8 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
}
if(vuser != NULL) {
- DEBUG(3,(" Username of UID %d is %s\n",
- (int)vuser->server_info->utok.uid,
- vuser->server_info->unix_name));
+ DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
+ vuser->user.unix_name));
}
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
@@ -3664,8 +3638,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
}
PACKS(&desc,"z",lp_workgroup());/* domain */
- PACKS(&desc,"z", vuser ? pdb_get_logon_script(
- vuser->server_info->sam_account) : ""); /* script path */
+ PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
PACKI(&desc,"D",0x00000000); /* reserved */
}
@@ -4587,7 +4560,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
if (api_commands[i].auth_user && lp_restrict_anonymous()) {
user_struct *user = get_valid_user_struct(vuid);
- if (!user || user->server_info->guest) {
+ if (!user || user->guest) {
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
@@ -4632,7 +4605,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
/* If api_Unsupported returns false we can't return anything. */
if (reply) {
- send_trans_reply(conn, req->inbuf, rparam, rparam_len,
+ send_trans_reply(conn, req, rparam, rparam_len,
rdata, rdata_len, False);
}
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 69ecf77834..1dc9c67dcc 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -294,7 +294,8 @@ static bool is_8_3(const char *fname, bool check_case, bool allow_wildcards,
if (strlen(f) > 12)
return False;
- if (!push_ucs2_allocate(&ucs2name, f, &size)) {
+ size = push_ucs2_allocate(&ucs2name, f);
+ if (size == (size_t)-1) {
DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
goto done;
}
@@ -603,11 +604,9 @@ static bool must_mangle(const char *name,
{
smb_ucs2_t *name_ucs2 = NULL;
NTSTATUS status;
- size_t converted_size;
-
magic_char = lp_magicchar(p);
- if (!push_ucs2_allocate(&name_ucs2, name, &converted_size)) {
+ if (push_ucs2_allocate(&name_ucs2, name) == (size_t)-1) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
return False;
}
@@ -638,14 +637,12 @@ static bool hash_name_to_8_3(const char *in,
const struct share_params *p)
{
smb_ucs2_t *in_ucs2 = NULL;
- size_t converted_size;
-
magic_char = lp_magicchar(p);
DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in,
cache83 ? "True" : "False"));
- if (!push_ucs2_allocate(&in_ucs2, in, &converted_size)) {
+ if (push_ucs2_allocate(&in_ucs2, in) == (size_t)-1) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
return False;
}
diff --git a/source/smbd/message.c b/source/smbd/message.c
index 62df5c37eb..a870f03df9 100644
--- a/source/smbd/message.c
+++ b/source/smbd/message.c
@@ -45,7 +45,7 @@ static void msg_deliver(struct msg_state *state)
int i;
int fd;
char *msg;
- size_t len;
+ int len;
ssize_t sz;
fstring alpha_buf;
char *s;
@@ -72,17 +72,18 @@ static void msg_deliver(struct msg_state *state)
* Incoming message is in DOS codepage format. Convert to UNIX.
*/
- if (!convert_string_talloc(talloc_tos(), CH_DOS, CH_UNIX, state->msg,
- talloc_get_size(state->msg), (void *)&msg,
- &len, true)) {
+ len = convert_string_talloc(
+ talloc_tos(), CH_DOS, CH_UNIX, state->msg,
+ talloc_get_size(state->msg), (void *)&msg, true);
+
+ if (len == -1) {
DEBUG(3, ("Conversion failed, delivering message in DOS "
"codepage format\n"));
msg = state->msg;
}
for (i = 0; i < len; i++) {
- if ((msg[i] == '\r') &&
- (i < (len-1)) && (msg[i+1] == '\n')) {
+ if ((msg[i] == '\r') && (i < (len-1)) && (msg[i+1] == '\n')) {
continue;
}
sz = write(fd, &msg[i], 1);
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 32240ff0d5..aef4ff6638 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -215,40 +215,37 @@ static NTSTATUS parse_dfs_path(connection_struct *conn,
Note this CHANGES CWD !!!! JRA.
*********************************************************/
-NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
- connection_struct **pconn,
+static NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
+ connection_struct *conn,
int snum,
- const char *path,
- char **poldcwd)
+ const char *path)
{
- connection_struct *conn;
char *connpath;
- char *oldcwd;
- conn = TALLOC_ZERO_P(ctx, connection_struct);
- if (conn == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ ZERO_STRUCTP(conn);
- connpath = talloc_strdup(conn, path);
+ connpath = talloc_strdup(ctx, path);
if (!connpath) {
- TALLOC_FREE(conn);
return NT_STATUS_NO_MEMORY;
}
- connpath = talloc_string_sub(conn,
+ connpath = talloc_string_sub(ctx,
connpath,
"%S",
lp_servicename(snum));
if (!connpath) {
- TALLOC_FREE(conn);
return NT_STATUS_NO_MEMORY;
}
/* needed for smbd_vfs_init() */
- if (!(conn->params = TALLOC_ZERO_P(conn, struct share_params))) {
+ if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) {
+ DEBUG(0,("talloc_init(connection_struct) failed!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx,
+ struct share_params))) {
DEBUG(0, ("TALLOC failed\n"));
- TALLOC_FREE(conn);
return NT_STATUS_NO_MEMORY;
}
@@ -269,14 +266,6 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
* user we will fail.... WTF ? JRA.
*/
- oldcwd = vfs_GetWd(ctx, conn);
- if (oldcwd == NULL) {
- NTSTATUS status = map_nt_error_from_unix(errno);
- DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno)));
- conn_free_internal(conn);
- return status;
- }
-
if (vfs_ChDir(conn,conn->connectpath) != 0) {
NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. "
@@ -286,9 +275,6 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
return status;
}
- *pconn = conn;
- *poldcwd = oldcwd;
-
return NT_STATUS_OK;
}
@@ -684,17 +670,6 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx,
return NT_STATUS_OK;
}
- if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn)))
- || (strequal(pdp->servicename, HOMES_NAME)
- && strequal(lp_servicename(SNUM(conn)),
- conn->server_info->sanitized_username) )) ) {
-
- /* The given sharename doesn't match this connection. */
- TALLOC_FREE(pdp);
-
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
status = dfs_path_lookup(ctx, conn, path_in, pdp,
search_wcard_flag, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
@@ -765,18 +740,19 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
int *consumedcntp,
bool *self_referralp)
{
- struct connection_struct *conn;
+ struct connection_struct conns;
+ struct connection_struct *conn = &conns;
char *targetpath = NULL;
int snum;
NTSTATUS status = NT_STATUS_NOT_FOUND;
bool dummy;
struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path);
- char *oldpath;
if (!pdp) {
return NT_STATUS_NO_MEMORY;
}
+ ZERO_STRUCT(conns);
*self_referralp = False;
status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy);
@@ -880,8 +856,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
return NT_STATUS_OK;
}
- status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum),
- &oldpath);
+ status = create_conn_struct(ctx, conn, snum, lp_pathname(snum));
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(pdp);
return status;
@@ -896,7 +871,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
DEBUG(3,("get_referred_path: No valid referrals for path %s\n",
dfs_path));
- vfs_ChDir(conn, oldpath);
conn_free_internal(conn);
TALLOC_FREE(pdp);
return status;
@@ -908,13 +882,11 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
&jucn->referral_count)) {
DEBUG(3,("get_referred_path: failed to parse symlink "
"target %s\n", targetpath ));
- vfs_ChDir(conn, oldpath);
conn_free_internal(conn);
TALLOC_FREE(pdp);
return NT_STATUS_NOT_FOUND;
}
- vfs_ChDir(conn, oldpath);
conn_free_internal(conn);
TALLOC_FREE(pdp);
return NT_STATUS_OK;
@@ -1309,30 +1281,26 @@ bool create_junction(TALLOC_CTX *ctx,
**********************************************************************/
static bool junction_to_local_path(const struct junction_map *jucn,
- char **pp_path_out,
- connection_struct **conn_out,
- char **oldpath)
+ char **pp_path_out,
+ connection_struct *conn_out)
{
int snum;
- NTSTATUS status;
snum = lp_servicenumber(jucn->service_name);
if(snum < 0) {
return False;
}
- status = create_conn_struct(talloc_tos(), conn_out, snum,
- lp_pathname(snum), oldpath);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(),
+ conn_out, snum,
+ lp_pathname(snum)))) {
return False;
}
- *pp_path_out = talloc_asprintf(*conn_out,
+ *pp_path_out = talloc_asprintf(conn_out->mem_ctx,
"%s/%s",
lp_pathname(snum),
jucn->volume_name);
if (!*pp_path_out) {
- vfs_ChDir(*conn_out, *oldpath);
- conn_free_internal(*conn_out);
return False;
}
return True;
@@ -1341,19 +1309,21 @@ static bool junction_to_local_path(const struct junction_map *jucn,
bool create_msdfs_link(const struct junction_map *jucn)
{
char *path = NULL;
- char *cwd;
char *msdfs_link = NULL;
- connection_struct *conn;
+ connection_struct conns;
+ connection_struct *conn = &conns;
int i=0;
bool insert_comma = False;
bool ret = False;
- if(!junction_to_local_path(jucn, &path, &conn, &cwd)) {
+ ZERO_STRUCT(conns);
+
+ if(!junction_to_local_path(jucn, &path, conn)) {
return False;
}
/* Form the msdfs_link contents */
- msdfs_link = talloc_strdup(conn, "msdfs:");
+ msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:");
if (!msdfs_link) {
goto out;
}
@@ -1406,7 +1376,7 @@ bool create_msdfs_link(const struct junction_map *jucn)
ret = True;
out:
- vfs_ChDir(conn, cwd);
+
conn_free_internal(conn);
return ret;
}
@@ -1414,19 +1384,18 @@ out:
bool remove_msdfs_link(const struct junction_map *jucn)
{
char *path = NULL;
- char *cwd;
- connection_struct *conn;
+ connection_struct conns;
+ connection_struct *conn = &conns;
bool ret = False;
- if (!junction_to_local_path(jucn, &path, &conn, &cwd)) {
- return false;
- }
+ ZERO_STRUCT(conns);
- if( SMB_VFS_UNLINK(conn, path) == 0 ) {
- ret = True;
+ if( junction_to_local_path(jucn, &path, conn) ) {
+ if( SMB_VFS_UNLINK(conn, path) == 0 ) {
+ ret = True;
+ }
}
- vfs_ChDir(conn, cwd);
conn_free_internal(conn);
return ret;
}
@@ -1442,9 +1411,9 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
char *dname = NULL;
const char *connect_path = lp_pathname(snum);
const char *msdfs_proxy = lp_msdfs_proxy(snum);
- connection_struct *conn;
- NTSTATUS status;
- char *cwd;
+ connection_struct conn;
+
+ ZERO_STRUCT(conn);
if(*connect_path == '\0') {
return 0;
@@ -1454,11 +1423,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
* Fake up a connection struct for the VFS layer.
*/
- status = create_conn_struct(talloc_tos(), &conn, snum, connect_path,
- &cwd);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("create_conn_struct failed: %s\n",
- nt_errstr(status)));
+ if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(),
+ &conn, snum, connect_path))) {
return 0;
}
@@ -1471,24 +1437,24 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
}
/* Now enumerate all dfs links */
- dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0);
+ dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0);
if(!dirp) {
goto out;
}
- while ((dname = vfs_readdirname(conn, dirp)) != NULL) {
- if (is_msdfs_link(conn,
+ while ((dname = vfs_readdirname(&conn, dirp)) != NULL) {
+ if (is_msdfs_link(&conn,
dname,
NULL)) {
cnt++;
}
}
- SMB_VFS_CLOSEDIR(conn,dirp);
+ SMB_VFS_CLOSEDIR(&conn,dirp);
out:
- vfs_ChDir(conn, cwd);
- conn_free_internal(conn);
+
+ conn_free_internal(&conn);
return cnt;
}
@@ -1506,10 +1472,10 @@ static int form_junctions(TALLOC_CTX *ctx,
const char *connect_path = lp_pathname(snum);
char *service_name = lp_servicename(snum);
const char *msdfs_proxy = lp_msdfs_proxy(snum);
- connection_struct *conn;
+ connection_struct conn;
struct referral *ref = NULL;
- char *cwd;
- NTSTATUS status;
+
+ ZERO_STRUCT(conn);
if (jn_remain == 0) {
return 0;
@@ -1523,10 +1489,7 @@ static int form_junctions(TALLOC_CTX *ctx,
* Fake up a connection struct for the VFS layer.
*/
- status = create_conn_struct(ctx, &conn, snum, connect_path, &cwd);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("create_conn_struct failed: %s\n",
- nt_errstr(status)));
+ if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) {
return 0;
}
@@ -1570,12 +1533,12 @@ static int form_junctions(TALLOC_CTX *ctx,
}
/* Now enumerate all dfs links */
- dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0);
+ dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0);
if(!dirp) {
goto out;
}
- while ((dname = vfs_readdirname(conn, dirp)) != NULL) {
+ while ((dname = vfs_readdirname(&conn, dirp)) != NULL) {
char *link_target = NULL;
if (cnt >= jn_remain) {
DEBUG(2, ("form_junctions: ran out of MSDFS "
@@ -1583,7 +1546,7 @@ static int form_junctions(TALLOC_CTX *ctx,
goto out;
}
if (is_msdfs_link_internal(ctx,
- conn,
+ &conn,
dname, &link_target,
NULL)) {
if (parse_msdfs_symlink(ctx,
@@ -1609,11 +1572,10 @@ static int form_junctions(TALLOC_CTX *ctx,
out:
if (dirp) {
- SMB_VFS_CLOSEDIR(conn,dirp);
+ SMB_VFS_CLOSEDIR(&conn,dirp);
}
- vfs_ChDir(conn, cwd);
- conn_free_internal(conn);
+ conn_free_internal(&conn);
return cnt;
}
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 84f111fb02..9f56949eeb 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -516,7 +516,6 @@ void reply_negprot(struct smb_request *req)
int num_cliprotos;
char **cliprotos;
int i;
- size_t converted_size;
static bool done_negprot = False;
@@ -556,8 +555,8 @@ void reply_negprot(struct smb_request *req)
cliprotos = tmp;
- if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
- &converted_size)) {
+ if (pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p)
+ == (size_t)-1) {
DEBUG(0, ("pull_ascii_talloc failed\n"));
TALLOC_FREE(cliprotos);
reply_nterror(req, NT_STATUS_NO_MEMORY);
diff --git a/source/smbd/notify.c b/source/smbd/notify.c
index 139dfe7d5b..eb3384d9a4 100644
--- a/source/smbd/notify.c
+++ b/source/smbd/notify.c
@@ -114,9 +114,6 @@ static bool notify_marshall_changes(int num_changes,
if (prs_offset(ps) > max_offset) {
/* Too much data for client. */
- DEBUG(10, ("Client only wanted %d bytes, trying to "
- "marshall %d bytes\n", (int)max_offset,
- (int)prs_offset(ps)));
return False;
}
}
@@ -259,9 +256,6 @@ NTSTATUS change_notify_add_request(const struct smb_request *req,
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
- DEBUG(10, ("change_notify_add_request: Adding request for %s: "
- "max_param = %d\n", fsp->fsp_name, (int)max_param));
-
if (!(request = SMB_MALLOC_P(struct notify_change_request))
|| !(map = SMB_MALLOC_P(struct notify_mid_map))) {
SAFE_FREE(request);
diff --git a/source/smbd/ntquotas.c b/source/smbd/ntquotas.c
index c616c494dc..fcccf9d9fc 100644
--- a/source/smbd/ntquotas.c
+++ b/source/smbd/ntquotas.c
@@ -222,13 +222,6 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
return 0;
}
-static int quota_handle_destructor(SMB_NTQUOTA_HANDLE *handle)
-{
- if (handle->quota_list)
- free_ntquota_list(&handle->quota_list);
- return 0;
-}
-
void *init_quota_handle(TALLOC_CTX *mem_ctx)
{
SMB_NTQUOTA_HANDLE *qt_handle;
@@ -242,6 +235,24 @@ void *init_quota_handle(TALLOC_CTX *mem_ctx)
return NULL;
}
- talloc_set_destructor(qt_handle, quota_handle_destructor);
- return (void *)qt_handle;
+ return (void *)qt_handle;
+}
+
+void destroy_quota_handle(void **pqt_handle)
+{
+ SMB_NTQUOTA_HANDLE *qt_handle = NULL;
+ if (!pqt_handle||!(*pqt_handle))
+ return;
+
+ qt_handle = (SMB_NTQUOTA_HANDLE *)(*pqt_handle);
+
+
+ if (qt_handle->quota_list)
+ free_ntquota_list(&qt_handle->quota_list);
+
+ qt_handle->quota_list = NULL;
+ qt_handle->tmp_list = NULL;
+ qt_handle = NULL;
+
+ return;
}
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 567c428bb8..13caf77b98 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -22,6 +22,28 @@
extern int max_send;
extern enum protocol_types Protocol;
+extern struct current_user current_user;
+
+static const char *known_nt_pipes[] = {
+ "\\LANMAN",
+ "\\srvsvc",
+ "\\samr",
+ "\\wkssvc",
+ "\\NETLOGON",
+ "\\ntlsa",
+ "\\ntsvcs",
+ "\\lsass",
+ "\\lsarpc",
+ "\\winreg",
+ "\\initshutdown",
+ "\\spoolss",
+ "\\netdfs",
+ "\\rpcecho",
+ "\\svcctl",
+ "\\eventlog",
+ "\\unixinfo",
+ NULL
+};
static char *nttrans_realloc(char **ptr, size_t size)
{
@@ -268,12 +290,25 @@ static void nt_open_pipe(char *fname, connection_struct *conn,
struct smb_request *req, int *ppnum)
{
smb_np_struct *p = NULL;
+ int i;
DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
/* See if it is one we want to handle. */
- if (!is_known_pipename(fname)) {
+ if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) {
+ reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ERRDOS, ERRbadpipe);
+ return;
+ }
+
+ for( i = 0; known_nt_pipes[i]; i++ ) {
+ if( strequal(fname,known_nt_pipes[i])) {
+ break;
+ }
+ }
+
+ if ( known_nt_pipes[i] == NULL ) {
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
ERRDOS, ERRbadpipe);
return;
@@ -739,7 +774,13 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len,
security_info_sent &= ~DACL_SECURITY_INFORMATION;
}
- status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd);
+ if (fsp->fh->fd != -1) {
+ status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd);
+ }
+ else {
+ status = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name,
+ security_info_sent, psd);
+ }
TALLOC_FREE(psd);
@@ -1495,7 +1536,7 @@ static void call_nt_transact_rename(connection_struct *conn,
}
fsp = file_fsp(SVAL(params, 0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
return;
}
srvstr_get_path_wcard(ctx, params, req->flags2, &new_name, params+4,
@@ -1587,8 +1628,14 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
if (!lp_nt_acl_support(SNUM(conn))) {
status = get_null_nt_acl(talloc_tos(), &psd);
} else {
- status = SMB_VFS_FGET_NT_ACL(
- fsp, security_info_wanted, &psd);
+ if (fsp->fh->fd != -1) {
+ status = SMB_VFS_FGET_NT_ACL(
+ fsp, security_info_wanted, &psd);
+ }
+ else {
+ status = SMB_VFS_GET_NT_ACL(
+ conn, fsp->fsp_name, security_info_wanted, &psd);
+ }
}
if (!NT_STATUS_IS_OK(status)) {
@@ -1748,7 +1795,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum));
- if (!fsp_belongs_conn(conn, req, fsp)) {
+ if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
return;
}
@@ -1803,7 +1850,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
uint32 i;
char *cur_pdata;
- if (!fsp_belongs_conn(conn, req, fsp)) {
+ if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
return;
}
@@ -1926,7 +1973,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum));
- if (!fsp_belongs_conn(conn, req, fsp)) {
+ if (!fsp_belongs_conn(conn, req, fsp, &current_user)) {
return;
}
@@ -2011,10 +2058,9 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
ZERO_STRUCT(qt);
/* access check */
- if (conn->server_info->utok.uid != 0) {
- DEBUG(1,("get_user_quota: access_denied service [%s] user "
- "[%s]\n", lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ if (current_user.ut.uid != 0) {
+ DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
+ lp_servicename(SNUM(conn)),conn->user));
reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -2031,7 +2077,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
/* maybe we can check the quota_fnum */
fsp = file_fsp(SVAL(params,0));
- if (!check_fsp_ntquota_handle(conn, req, fsp)) {
+ if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return;
@@ -2040,7 +2086,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
/* the NULL pointer checking for fsp->fake_file_handle->pd
* is done by CHECK_NTQUOTA_HANDLE_OK()
*/
- qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
+ qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd;
level = SVAL(params,2);
@@ -2278,10 +2324,9 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
ZERO_STRUCT(qt);
/* access check */
- if (conn->server_info->utok.uid != 0) {
- DEBUG(1,("set_user_quota: access_denied service [%s] user "
- "[%s]\n", lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ if (current_user.ut.uid != 0) {
+ DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
+ lp_servicename(SNUM(conn)),conn->user));
reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -2298,7 +2343,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
/* maybe we can check the quota_fnum */
fsp = file_fsp(SVAL(params,0));
- if (!check_fsp_ntquota_handle(conn, req, fsp)) {
+ if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return;
@@ -2560,7 +2605,7 @@ void reply_nttrans(struct smb_request *req)
return;
}
- if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
reply_doserror(req, ERRSRV, ERRaccess);
END_PROFILE(SMBnttrans);
return;
diff --git a/source/smbd/open.c b/source/smbd/open.c
index ad024a58ef..afe8d5e9b3 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -22,6 +22,8 @@
#include "includes.h"
extern const struct generic_mapping file_generic_mapping;
+extern struct current_user current_user;
+extern userdom_struct current_user_info;
extern bool global_client_failed_oplock_break;
struct deferred_open_record {
@@ -321,7 +323,7 @@ static NTSTATUS open_file(files_struct *fsp,
/* Inherit the ACL if required */
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir, path,
+ inherit_access_acl(conn, parent_dir, path,
unx_mode);
}
@@ -389,6 +391,7 @@ static NTSTATUS open_file(files_struct *fsp,
fsp->modified = False;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = False;
+ fsp->is_stat = False;
if (conn->aio_write_behind_list &&
is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) {
fsp->aio_write_behind = True;
@@ -398,8 +401,8 @@ static NTSTATUS open_file(files_struct *fsp,
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
- conn->server_info->unix_name,
- fsp->fsp_name,
+ *current_user_info.smb_name ?
+ current_user_info.smb_name : conn->user,fsp->fsp_name,
BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
conn->num_files_open + 1));
@@ -1178,7 +1181,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
- return print_fsp_open(conn, fname, req->vuid, result);
+ return print_fsp_open(conn, fname, result);
}
if (!parent_dirname_talloc(talloc_tos(), fname, &parent_dir,
@@ -1568,7 +1571,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
- !can_access_file_data(conn,fname,psbuf,can_access_mask)) {
+ !can_access_file(conn,fname,psbuf,can_access_mask)) {
can_access = False;
}
@@ -1847,8 +1850,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
new_file_created = True;
}
- set_share_mode(lck, fsp, conn->server_info->utok.uid, 0,
- fsp->oplock_type, new_file_created);
+ set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created);
/* Handle strange delete on close create semantics. */
if ((create_options & FILE_DELETE_ON_CLOSE)
@@ -2057,7 +2059,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
}
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir, name, mode);
+ inherit_access_acl(conn, parent_dir, name, mode);
}
if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
@@ -2224,6 +2226,7 @@ NTSTATUS open_directory(connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True;
+ fsp->is_stat = False;
fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
string_set(&fsp->fsp_name,fname);
@@ -2250,8 +2253,7 @@ NTSTATUS open_directory(connection_struct *conn,
return status;
}
- set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, NO_OPLOCK,
- True);
+ set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True);
/* For directories the delete on close bit at open time seems
always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
@@ -2307,6 +2309,58 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, cons
}
/****************************************************************************
+ Open a pseudo-file (no locking checks - a 'stat' open).
+****************************************************************************/
+
+NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req,
+ const char *fname, SMB_STRUCT_STAT *psbuf,
+ files_struct **result)
+{
+ files_struct *fsp = NULL;
+ NTSTATUS status;
+
+ if (!VALID_STAT(*psbuf)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Can't 'stat' open directories. */
+ if(S_ISDIR(psbuf->st_mode)) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ status = file_new(conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ DEBUG(5,("open_file_stat: 'opening' file %s\n", fname));
+
+ /*
+ * Setup the files_struct for it.
+ */
+
+ fsp->mode = psbuf->st_mode;
+ fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
+ fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
+ fsp->file_pid = req ? req->smbpid : 0;
+ fsp->can_lock = False;
+ fsp->can_read = False;
+ fsp->can_write = False;
+ fsp->print_file = False;
+ fsp->modified = False;
+ fsp->oplock_type = NO_OPLOCK;
+ fsp->sent_oplock_break = NO_BREAK_SENT;
+ fsp->is_directory = False;
+ fsp->is_stat = True;
+ string_set(&fsp->fsp_name,fname);
+
+ conn->num_files_open++;
+
+ *result = fsp;
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Receive notification that one of our open files has been renamed by another
smbd process.
****************************************************************************/
@@ -2608,7 +2662,9 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
&& (create_disposition != FILE_CREATE)
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
- && (!can_delete_file_in_directory(conn, fname))) {
+ && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY)
+ && !lp_delete_readonly(SNUM(conn)))
+ || !can_delete_file_in_directory(conn, fname))) {
status = NT_STATUS_ACCESS_DENIED;
goto fail;
}
@@ -2996,8 +3052,7 @@ NTSTATUS create_file(connection_struct *conn,
* also tries a QUERY_FILE_INFO on the file and then
* close it
*/
- status = open_fake_file(conn, req->vuid,
- fake_file_type, fname,
+ status = open_fake_file(conn, fake_file_type, fname,
access_mask, &fsp);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 1d3514429f..80eba562c5 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -119,6 +119,8 @@ void invalidate_vuid(uint16 vuid)
session_yield(vuser);
+ data_blob_free(&vuser->session_key);
+
if (vuser->auth_ntlmssp_state) {
auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
}
@@ -127,7 +129,7 @@ void invalidate_vuid(uint16 vuid)
/* clear the vuid from the 'cache' on each connection, and
from the vuid 'owner' of connections */
- conn_clear_vuid_caches(vuid);
+ conn_clear_vuid_cache(vuid);
TALLOC_FREE(vuser);
num_validated_vuids--;
@@ -199,37 +201,6 @@ int register_initial_vuid(void)
return vuser->vuid;
}
-static int register_homes_share(const char *username)
-{
- int result;
- struct passwd *pwd;
-
- result = lp_servicenumber(username);
- if (result != -1) {
- DEBUG(3, ("Using static (or previously created) service for "
- "user '%s'; path = '%s'\n", username,
- lp_pathname(result)));
- return result;
- }
-
- pwd = getpwnam_alloc(talloc_tos(), username);
-
- if ((pwd == NULL) || (pwd->pw_dir[0] == '\0')) {
- DEBUG(3, ("No home directory defined for user '%s'\n",
- username));
- TALLOC_FREE(pwd);
- return -1;
- }
-
- DEBUG(3, ("Adding homes service for user '%s' using home directory: "
- "'%s'\n", username, pwd->pw_dir));
-
- result = add_home_service(username, username, pwd->pw_dir);
-
- TALLOC_FREE(pwd);
- return result;
-}
-
/**
* register that a valid login has been performed, establish 'session'.
* @param server_info The token returned from the authentication process.
@@ -250,47 +221,109 @@ static int register_homes_share(const char *username)
int register_existing_vuid(uint16 vuid,
auth_serversupplied_info *server_info,
+ DATA_BLOB session_key,
DATA_BLOB response_blob,
const char *smb_name)
{
- fstring tmp;
- user_struct *vuser;
-
- vuser = get_partial_auth_user_struct(vuid);
+ user_struct *vuser = get_partial_auth_user_struct(vuid);
if (!vuser) {
goto fail;
}
/* Use this to keep tabs on all our info from the authentication */
- vuser->server_info = talloc_move(vuser, &server_info);
+ vuser->server_info = server_info;
+
+ /* Ensure that the server_info will disappear with
+ * the vuser it is now attached to */
+
+ talloc_steal(vuser, vuser->server_info);
+
+ /* the next functions should be done by a SID mapping system (SMS) as
+ * the new real sam db won't have reference to unix uids or gids
+ */
+
+ vuser->uid = server_info->uid;
+ vuser->gid = server_info->gid;
+
+ vuser->n_groups = server_info->n_groups;
+ if (vuser->n_groups) {
+ if (!(vuser->groups = (gid_t *)talloc_memdup(vuser,
+ server_info->groups,
+ sizeof(gid_t)*vuser->n_groups))) {
+ DEBUG(0,("register_existing_vuid: "
+ "failed to talloc_memdup vuser->groups\n"));
+ goto fail;
+ }
+ }
+
+ vuser->guest = server_info->guest;
+ fstrcpy(vuser->user.unix_name, server_info->unix_name);
/* This is a potentially untrusted username */
- alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp));
+ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
+ sizeof(vuser->user.smb_name));
+
+ fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
+ fstrcpy(vuser->user.full_name,
+ pdb_get_fullname(server_info->sam_account));
+
+ {
+ /* Keep the homedir handy */
+ const char *homedir =
+ pdb_get_homedir(server_info->sam_account);
+ const char *logon_script =
+ pdb_get_logon_script(server_info->sam_account);
+
+ if (!IS_SAM_DEFAULT(server_info->sam_account,
+ PDB_UNIXHOMEDIR)) {
+ const char *unix_homedir =
+ pdb_get_unix_homedir(server_info->sam_account);
+ if (unix_homedir) {
+ vuser->unix_homedir = unix_homedir;
+ }
+ } else {
+ struct passwd *passwd =
+ getpwnam_alloc(vuser, vuser->user.unix_name);
+ if (passwd) {
+ vuser->unix_homedir = passwd->pw_dir;
+ /* Ensure that the unix_homedir now
+ * belongs to vuser, so it goes away
+ * with it, not with passwd below: */
+ talloc_steal(vuser, vuser->unix_homedir);
+ TALLOC_FREE(passwd);
+ }
+ }
- vuser->server_info->sanitized_username = talloc_strdup(
- vuser->server_info, tmp);
+ if (homedir) {
+ vuser->homedir = homedir;
+ }
+ if (logon_script) {
+ vuser->logon_script = logon_script;
+ }
+ }
+ vuser->session_key = session_key;
DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n",
- (unsigned int)vuser->server_info->utok.uid,
- (unsigned int)vuser->server_info->utok.gid,
- vuser->server_info->unix_name,
- vuser->server_info->sanitized_username,
- pdb_get_domain(vuser->server_info->sam_account),
- vuser->server_info->guest ));
+ (unsigned int)vuser->uid,
+ (unsigned int)vuser->gid,
+ vuser->user.unix_name, vuser->user.smb_name,
+ vuser->user.domain, vuser->guest ));
DEBUG(3, ("register_existing_vuid: User name: %s\t"
- "Real name: %s\n", vuser->server_info->unix_name,
- pdb_get_fullname(vuser->server_info->sam_account)));
+ "Real name: %s\n", vuser->user.unix_name,
+ vuser->user.full_name));
- if (!vuser->server_info->ptok) {
+ if (server_info->ptok) {
+ vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok);
+ } else {
DEBUG(1, ("register_existing_vuid: server_info does not "
"contain a user_token - cannot continue\n"));
goto fail;
}
DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, "
- "and will be vuid %u\n", (int)vuser->server_info->utok.uid,
- vuser->server_info->unix_name, vuser->vuid));
+ "and will be vuid %u\n",
+ (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
next_vuid++;
num_validated_vuids++;
@@ -309,26 +342,34 @@ int register_existing_vuid(uint16 vuid,
If a share exists by this name (autoloaded or not) reuse it . */
vuser->homes_snum = -1;
-
- if (!vuser->server_info->guest) {
- vuser->homes_snum = register_homes_share(
- vuser->server_info->unix_name);
+ if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) {
+ int servicenumber = lp_servicenumber(vuser->user.unix_name);
+ if ( servicenumber == -1 ) {
+ DEBUG(3, ("Adding homes service for user '%s' using "
+ "home directory: '%s'\n",
+ vuser->user.unix_name, vuser->unix_homedir));
+ vuser->homes_snum =
+ add_home_service(vuser->user.unix_name,
+ vuser->user.unix_name,
+ vuser->unix_homedir);
+ } else {
+ DEBUG(3, ("Using static (or previously created) "
+ "service for user '%s'; path = '%s'\n",
+ vuser->user.unix_name,
+ lp_pathname(servicenumber) ));
+ vuser->homes_snum = servicenumber;
+ }
}
- if (srv_is_signing_negotiated() && !vuser->server_info->guest &&
+ if (srv_is_signing_negotiated() && !vuser->guest &&
!srv_signing_started()) {
/* Try and turn on server signing on the first non-guest
* sessionsetup. */
- srv_set_signing(vuser->server_info->user_session_key, response_blob);
+ srv_set_signing(vuser->session_key, response_blob);
}
/* fill in the current_user_info struct */
- set_current_user_info(
- vuser->server_info->sanitized_username,
- vuser->server_info->unix_name,
- pdb_get_fullname(vuser->server_info->sam_account),
- pdb_get_domain(vuser->server_info->sam_account));
-
+ set_current_user_info( &vuser->user );
return vuser->vuid;
fail:
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 4fdcdcc557..6b4b83d97d 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -44,6 +44,9 @@ struct pipe_dbrec {
fstring user;
};
+
+extern struct pipe_id_info pipe_names[];
+
/****************************************************************************
Reply to an open and X on a named pipe.
This code is basically stolen from reply_open_and_X with some
@@ -56,6 +59,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
char *pipe_name = NULL;
smb_np_struct *p;
int size=0,fmode=0,mtime=0,rmode=0;
+ int i;
TALLOC_CTX *ctx = talloc_tos();
/* XXXX we need to handle passed times, sattr and flags */
@@ -78,7 +82,13 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
DEBUG(4,("Opening pipe %s.\n", pipe_name));
/* See if it is one we want to handle. */
- if (!is_known_pipename(pipe_name)) {
+ for( i = 0; pipe_names[i].client_pipe ; i++ ) {
+ if( strequal(pipe_name,pipe_names[i].client_pipe)) {
+ break;
+ }
+ }
+
+ if (pipe_names[i].client_pipe == NULL) {
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
ERRDOS, ERRbadpipe);
return;
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 7479aea076..d798fa8da4 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -904,7 +904,7 @@ static SEC_ACCESS map_canon_ace_perms(int snum,
if (directory_ace) {
nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
} else {
- nt_mask = (UNIX_ACCESS_RWX & ~DELETE_ACCESS);
+ nt_mask = UNIX_ACCESS_RWX;
}
} else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
/*
@@ -2207,7 +2207,9 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
posix_id unix_ug;
enum ace_owner owner_type;
- entry_id = SMB_ACL_NEXT_ENTRY;
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
/* Is this a MASK entry ? */
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
@@ -3701,7 +3703,9 @@ int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
- entry_id = SMB_ACL_NEXT_ENTRY;
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
break;
@@ -3739,7 +3743,9 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
SMB_ACL_PERMSET_T permset;
mode_t perms;
- entry_id = SMB_ACL_NEXT_ENTRY;
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
return -1;
@@ -3796,7 +3802,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
resulting ACL on TO. Note that name is in UNIX character set.
****************************************************************************/
-static int copy_access_posix_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
+static int copy_access_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
{
SMB_ACL_T posix_acl = NULL;
int ret = -1;
@@ -3823,27 +3829,7 @@ static int copy_access_posix_acl(connection_struct *conn, const char *from, cons
int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
{
- return copy_access_posix_acl(conn, name, name, mode);
-}
-
-/****************************************************************************
- Check for an existing default POSIX ACL on a directory.
-****************************************************************************/
-
-static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname)
-{
- SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
- bool has_acl = False;
- SMB_ACL_ENTRY_T entry;
-
- if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
- has_acl = True;
- }
-
- if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
- }
- return has_acl;
+ return copy_access_acl(conn, name, name, mode);
}
/****************************************************************************
@@ -3851,13 +3837,13 @@ static bool directory_has_default_posix_acl(connection_struct *conn, const char
inherit this Access ACL to file name.
****************************************************************************/
-int inherit_access_posix_acl(connection_struct *conn, const char *inherit_from_dir,
+int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir,
const char *name, mode_t mode)
{
- if (directory_has_default_posix_acl(conn, inherit_from_dir))
+ if (directory_has_default_acl(conn, inherit_from_dir))
return 0;
- return copy_access_posix_acl(conn, inherit_from_dir, name, mode);
+ return copy_access_acl(conn, inherit_from_dir, name, mode);
}
/****************************************************************************
@@ -3886,6 +3872,26 @@ int fchmod_acl(files_struct *fsp, mode_t mode)
}
/****************************************************************************
+ Check for an existing default POSIX ACL on a directory.
+****************************************************************************/
+
+bool directory_has_default_acl(connection_struct *conn, const char *fname)
+{
+ SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
+ bool has_acl = False;
+ SMB_ACL_ENTRY_T entry;
+
+ if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
+ has_acl = True;
+ }
+
+ if (def_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ }
+ return has_acl;
+}
+
+/****************************************************************************
Map from wire type to permset.
****************************************************************************/
@@ -4159,7 +4165,9 @@ static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
- entry_id = SMB_ACL_NEXT_ENTRY;
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n",
@@ -4273,29 +4281,30 @@ bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
{
SEC_DESC *psd, *ret_sd;
- connection_struct *conn;
+ connection_struct conn;
files_struct finfo;
struct fd_handle fh;
- conn = TALLOC_ZERO_P(ctx, connection_struct);
- if (conn == NULL) {
- DEBUG(0, ("talloc failed\n"));
+ ZERO_STRUCT( conn );
+
+ if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
+ DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
return NULL;
}
- if (!(conn->params = TALLOC_P(conn, struct share_params))) {
+ if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) {
DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
- TALLOC_FREE(conn);
+ TALLOC_FREE(conn.mem_ctx);
return NULL;
}
- conn->params->service = -1;
+ conn.params->service = -1;
- set_conn_connectpath(conn, "/");
+ set_conn_connectpath(&conn, "/");
- if (!smbd_vfs_init(conn)) {
+ if (!smbd_vfs_init(&conn)) {
DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
- conn_free_internal( conn );
+ conn_free_internal( &conn );
return NULL;
}
@@ -4303,20 +4312,20 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
ZERO_STRUCT( fh );
finfo.fnum = -1;
- finfo.conn = conn;
+ finfo.conn = &conn;
finfo.fh = &fh;
finfo.fh->fd = -1;
finfo.fsp_name = CONST_DISCARD(char *,fname);
if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) {
DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
- conn_free_internal( conn );
+ conn_free_internal( &conn );
return NULL;
}
ret_sd = dup_sec_desc( ctx, psd );
- conn_free_internal( conn );
+ conn_free_internal( &conn );
return ret_sd;
}
diff --git a/source/smbd/process.c b/source/smbd/process.c
index c7e5c4cde3..cb465aec94 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -152,7 +152,7 @@ static NTSTATUS read_packet_remainder(int fd, char *buffer,
1 /* pad byte */)
static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
- const char *lenbuf,
+ const char lenbuf[4],
int fd, char **buffer,
unsigned int timeout,
size_t *p_unread,
@@ -1245,8 +1245,7 @@ static const struct smb_message_struct {
allocate and initialize a reply packet
********************************************************************/
-bool create_outbuf(TALLOC_CTX *mem_ctx, const char *inbuf, char **outbuf,
- uint8_t num_words, uint32_t num_bytes)
+void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
{
/*
* Protect against integer wrap
@@ -1261,33 +1260,23 @@ bool create_outbuf(TALLOC_CTX *mem_ctx, const char *inbuf, char **outbuf,
smb_panic(msg);
}
- *outbuf = TALLOC_ARRAY(mem_ctx, char,
- smb_size + num_words*2 + num_bytes);
- if (*outbuf == NULL) {
- return false;
+ if (!(req->outbuf = TALLOC_ARRAY(
+ req, uint8,
+ smb_size + num_words*2 + num_bytes))) {
+ smb_panic("could not allocate output buffer\n");
}
- construct_reply_common(inbuf, *outbuf);
- srv_set_message(*outbuf, num_words, num_bytes, false);
+ construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
+ srv_set_message((char *)req->outbuf, num_words, num_bytes, false);
/*
* Zero out the word area, the caller has to take care of the bcc area
* himself
*/
if (num_words != 0) {
- memset(*outbuf + smb_vwv0, 0, num_words*2);
+ memset(req->outbuf + smb_vwv0, 0, num_words*2);
}
- return true;
-}
-
-void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
-{
- char *outbuf;
- if (!create_outbuf(req, (char *)req->inbuf, &outbuf, num_words,
- num_bytes)) {
- smb_panic("could not allocate output buffer\n");
- }
- req->outbuf = (uint8_t *)outbuf;
+ return;
}
@@ -1392,13 +1381,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
if(session_tag != UID_FIELD_INVALID) {
vuser = get_valid_user_struct(session_tag);
if (vuser) {
- set_current_user_info(
- vuser->server_info->sanitized_username,
- vuser->server_info->unix_name,
- pdb_get_fullname(vuser->server_info
- ->sam_account),
- pdb_get_domain(vuser->server_info
- ->sam_account));
+ set_current_user_info(&vuser->user);
}
}
}
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index fbda57db51..466fef960c 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -32,6 +32,7 @@ extern int max_recv;
unsigned int smb_echo_count = 0;
extern uint32 global_client_caps;
+extern struct current_user current_user;
extern bool global_encrypted_passwords_negotiated;
/****************************************************************************
@@ -326,13 +327,13 @@ size_t srvstr_get_path(TALLOC_CTX *ctx,
****************************************************************************/
bool check_fsp_open(connection_struct *conn, struct smb_request *req,
- files_struct *fsp)
+ files_struct *fsp, struct current_user *user)
{
if (!(fsp) || !(conn)) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return False;
}
- if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
+ if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return False;
}
@@ -345,9 +346,9 @@ bool check_fsp_open(connection_struct *conn, struct smb_request *req,
****************************************************************************/
bool check_fsp(connection_struct *conn, struct smb_request *req,
- files_struct *fsp)
+ files_struct *fsp, struct current_user *user)
{
- if (!check_fsp_open(conn, req, fsp)) {
+ if (!check_fsp_open(conn, req, fsp, user)) {
return False;
}
if ((fsp)->is_directory) {
@@ -363,45 +364,14 @@ bool check_fsp(connection_struct *conn, struct smb_request *req,
}
/****************************************************************************
- Check if we have a correct fsp pointing to a quota fake file. Replacement for
- the CHECK_NTQUOTA_HANDLE_OK macro.
-****************************************************************************/
-
-bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
- files_struct *fsp)
-{
- if (!check_fsp_open(conn, req, fsp)) {
- return false;
- }
-
- if (fsp->is_directory) {
- return false;
- }
-
- if (fsp->fake_file_handle == NULL) {
- return false;
- }
-
- if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
- return false;
- }
-
- if (fsp->fake_file_handle->private_data == NULL) {
- return false;
- }
-
- return true;
-}
-
-/****************************************************************************
Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
****************************************************************************/
bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
- files_struct *fsp)
+ files_struct *fsp, struct current_user *user)
{
if ((fsp) && (conn) && ((conn)==(fsp)->conn)
- && (req->vuid == (fsp)->vuid)) {
+ && (current_user.vuid==(fsp)->vuid)) {
return True;
}
@@ -2131,7 +2101,7 @@ void reply_ctemp(struct smb_request *req)
return;
}
- status = check_name(conn, fname);
+ status = check_name(conn, CONST_DISCARD(char *,fname));
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBctemp);
@@ -2358,13 +2328,13 @@ static NTSTATUS do_unlink(connection_struct *conn,
&sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("create_file_unixpath failed: %s\n",
+ DEBUG(10, ("open_file_ntcreate failed: %s\n",
nt_errstr(status)));
return status;
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
+ if (!set_delete_on_close(fsp, True, &current_user.ut)) {
close_file(fsp, NORMAL_CLOSE);
return NT_STATUS_ACCESS_DENIED;
}
@@ -2819,7 +2789,7 @@ void reply_readbraw(struct smb_request *req)
*/
if (!fsp || !conn || conn != fsp->conn ||
- req->vuid != fsp->vuid ||
+ current_user.vuid != fsp->vuid ||
fsp->is_directory || fsp->fh->fd == -1) {
/*
* fsp could be NULL here so use the value from the packet. JRA.
@@ -2954,7 +2924,7 @@ void reply_lockread(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBlockread);
return;
}
@@ -3062,7 +3032,7 @@ void reply_read(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBread);
return;
}
@@ -3318,7 +3288,7 @@ void reply_read_and_X(struct smb_request *req)
return;
}
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBreadX);
return;
}
@@ -3456,7 +3426,7 @@ void reply_writebraw(struct smb_request *req)
}
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
return;
@@ -3662,7 +3632,7 @@ void reply_writeunlock(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBwriteunlock);
return;
}
@@ -3769,7 +3739,7 @@ void reply_write(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBwrite);
return;
}
@@ -4001,7 +3971,7 @@ void reply_write_and_X(struct smb_request *req)
startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
write_through = BITSETW(req->inbuf+smb_vwv7,0);
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBwriteX);
return;
}
@@ -4120,7 +4090,7 @@ void reply_lseek(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
return;
}
@@ -4206,7 +4176,7 @@ void reply_flush(struct smb_request *req)
fnum = SVAL(req->inbuf,smb_vwv0);
fsp = file_fsp(fnum);
- if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
+ if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
return;
}
@@ -4279,7 +4249,7 @@ void reply_close(struct smb_request *req)
* We can only use CHECK_FSP if we know it's not a directory.
*/
- if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
+ if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBclose);
return;
@@ -4353,7 +4323,7 @@ void reply_writeclose(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBwriteclose);
return;
}
@@ -4440,7 +4410,7 @@ void reply_lock(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBlock);
return;
}
@@ -4499,7 +4469,7 @@ void reply_unlock(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBunlock);
return;
}
@@ -4645,7 +4615,7 @@ void reply_printopen(struct smb_request *req)
}
/* Open for exclusive use, write only. */
- status = print_fsp_open(conn, NULL, req->vuid, &fsp);
+ status = print_fsp_open(conn, NULL, &fsp);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -4683,7 +4653,7 @@ void reply_printclose(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBsplclose);
return;
}
@@ -4825,7 +4795,7 @@ void reply_printwrite(struct smb_request *req)
fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBsplwr);
return;
}
@@ -5586,10 +5556,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
- notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
-
rename_open_files(conn, lck, newname);
+ notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
+
/*
* A rename acts as a new file create w.r.t. allowing an initial delete
* on close, probably because in Windows there is a new handle to the
@@ -6659,7 +6629,7 @@ void reply_lockingX(struct smb_request *req)
lock_timeout = IVAL(req->inbuf,smb_vwv4);
large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
END_PROFILE(SMBlockingX);
return;
}
diff --git a/source/smbd/sec_ctx.c b/source/smbd/sec_ctx.c
index a618f06e6b..0f307f6a64 100644
--- a/source/smbd/sec_ctx.c
+++ b/source/smbd/sec_ctx.c
@@ -145,7 +145,7 @@ static void gain_root(void)
Get the list of current groups.
****************************************************************************/
-static int get_current_groups(gid_t gid, size_t *p_ngroups, gid_t **p_groups)
+static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
{
int i;
gid_t grp;
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 53116f3d98..176cd5f973 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -90,12 +90,9 @@ struct messaging_context *smbd_messaging_context(void)
{
static struct messaging_context *ctx;
- if (ctx == NULL) {
- ctx = messaging_init(NULL, server_id_self(),
- smbd_event_context());
- }
- if (ctx == NULL) {
- DEBUG(0, ("Could not init smbd messaging context.\n"));
+ if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
+ smbd_event_context()))) {
+ smb_panic("Could not init smbd messaging context");
}
return ctx;
}
@@ -296,7 +293,6 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown)
/* a child terminated uncleanly so tickle all processes to see
if they can grab any of the pending locks
*/
- DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", pid));
messaging_send_buf(smbd_messaging_context(), procid_self(),
MSG_SMB_BRL_VALIDATE, NULL, 0);
message_send_all(smbd_messaging_context(),
@@ -575,12 +571,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_
MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete);
brl_register_msgs(smbd_messaging_context());
-#ifdef CLUSTER_SUPPORT
- if (lp_clustering()) {
- ctdbd_register_reconfigure(messaging_ctdbd_connection());
- }
-#endif
-
#ifdef DEVELOPER
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_INJECT_FAULT, msg_inject_fault);
@@ -894,7 +884,6 @@ static void exit_server_common(enum server_exit_reason how,
const char *const reason)
{
static int firsttime=1;
- bool had_open_conn;
if (!firsttime)
exit(0);
@@ -906,7 +895,7 @@ static void exit_server_common(enum server_exit_reason how,
(negprot_global_auth_context->free)(&negprot_global_auth_context);
}
- had_open_conn = conn_close_all();
+ conn_close_all();
invalidate_all_vuids();
@@ -956,15 +945,7 @@ static void exit_server_common(enum server_exit_reason how,
(reason ? reason : "normal exit")));
}
- /* if we had any open SMB connections when we exited then we
- need to tell the parent smbd so that it can trigger a retry
- of any locks we may have been holding or open files we were
- blocking */
- if (had_open_conn) {
- exit(1);
- } else {
- exit(0);
- }
+ exit(0);
}
void exit_server(const char *const explanation)
@@ -998,9 +979,7 @@ static void release_ip(const char *ip, void *priv)
away */
DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
ip));
- /* note we must exit with non-zero status so the unclean handler gets
- called in the parent, so that the brl database is tickled */
- _exit(1);
+ _exit(0);
}
}
@@ -1116,6 +1095,8 @@ extern void build_options(bool screen);
TimeInit();
+ db_tdb2_setup_messaging(NULL, false);
+
#ifdef HAVE_SET_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
#endif
@@ -1247,6 +1228,11 @@ extern void build_options(bool screen);
if (smbd_messaging_context() == NULL)
exit(1);
+ /*
+ * Do this before reload_services.
+ */
+ db_tdb2_setup_messaging(smbd_messaging_context(), true);
+
if (!reload_services(False))
return(-1);
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 0b851f1e48..491a67a2eb 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -523,6 +523,31 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev)
return NT_STATUS_OK;
}
+static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
+{
+ int snum = conn->params->service;
+ char *fuser, *found_username;
+ NTSTATUS result;
+
+ if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
+ lp_servicename(snum)))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
+ &conn->uid, &conn->gid, &found_username,
+ &conn->nt_user_token);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ fstrcpy(username, found_username);
+
+ TALLOC_FREE(fuser);
+ TALLOC_FREE(found_username);
+ return NT_STATUS_OK;
+}
+
/*
* Go through lookup_name etc to find the force'd group.
*
@@ -536,14 +561,23 @@ static NTSTATUS find_forced_group(bool force_user,
gid_t *pgid)
{
NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
- TALLOC_CTX *frame = talloc_stackframe();
+ TALLOC_CTX *mem_ctx;
DOM_SID group_sid;
enum lsa_SidType type;
char *groupname;
bool user_must_be_member = False;
gid_t gid;
- groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
+ ZERO_STRUCTP(pgroup_sid);
+ *pgid = (gid_t)-1;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
if (groupname == NULL) {
DEBUG(1, ("talloc_strdup failed\n"));
result = NT_STATUS_NO_MEMORY;
@@ -555,15 +589,10 @@ static NTSTATUS find_forced_group(bool force_user,
groupname += 1;
}
- groupname = talloc_string_sub(talloc_tos(), groupname,
+ groupname = talloc_string_sub(mem_ctx, groupname,
"%S", lp_servicename(snum));
- if (groupname == NULL) {
- DEBUG(1, ("talloc_string_sub failed\n"));
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
- if (!lookup_name_smbconf(talloc_tos(), groupname,
+ if (!lookup_name_smbconf(mem_ctx, groupname,
LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
NULL, NULL, &group_sid, &type)) {
DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
@@ -612,88 +641,11 @@ static NTSTATUS find_forced_group(bool force_user,
result = NT_STATUS_OK;
done:
- TALLOC_FREE(frame);
+ TALLOC_FREE(mem_ctx);
return result;
}
/****************************************************************************
- Create an auth_serversupplied_info structure for a connection_struct
-****************************************************************************/
-
-static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
- struct auth_serversupplied_info *vuid_serverinfo,
- DATA_BLOB password,
- struct auth_serversupplied_info **presult)
-{
- if (lp_guest_only(snum)) {
- return make_server_info_guest(mem_ctx, presult);
- }
-
- if (vuid_serverinfo != NULL) {
-
- struct auth_serversupplied_info *result;
-
- /*
- * This is the normal security != share case where we have a
- * valid vuid from the session setup. */
-
- if (vuid_serverinfo->guest) {
- if (!lp_guest_ok(snum)) {
- DEBUG(2, ("guest user (from session setup) "
- "not permitted to access this share "
- "(%s)\n", lp_servicename(snum)));
- return NT_STATUS_ACCESS_DENIED;
- }
- } else {
- if (!user_ok_token(vuid_serverinfo->unix_name,
- pdb_get_domain(vuid_serverinfo->sam_account),
- vuid_serverinfo->ptok, snum)) {
- DEBUG(2, ("user '%s' (from session setup) not "
- "permitted to access this share "
- "(%s)\n",
- vuid_serverinfo->unix_name,
- lp_servicename(snum)));
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
- result = copy_serverinfo(mem_ctx, vuid_serverinfo);
- if (result == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- *presult = result;
- return NT_STATUS_OK;
- }
-
- if (lp_security() == SEC_SHARE) {
-
- fstring user;
- bool guest;
-
- /* add the sharename as a possible user name if we
- are in share mode security */
-
- add_session_user(lp_servicename(snum));
-
- /* shall we let them in? */
-
- if (!authorise_login(snum,user,password,&guest)) {
- DEBUG( 2, ( "Invalid username/password for [%s]\n",
- lp_servicename(snum)) );
- return NT_STATUS_WRONG_PASSWORD;
- }
-
- return make_serverinfo_from_username(mem_ctx, user, guest,
- presult);
- }
-
- DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
- return NT_STATUS_ACCESS_DENIED;
-}
-
-
-/****************************************************************************
Make a connection, given the snum to connect to, and the vuser of the
connecting user if appropriate.
****************************************************************************/
@@ -701,49 +653,132 @@ static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
static connection_struct *make_connection_snum(int snum, user_struct *vuser,
DATA_BLOB password,
const char *pdev,
- NTSTATUS *pstatus)
+ NTSTATUS *status)
{
+ struct passwd *pass = NULL;
+ bool guest = False;
connection_struct *conn;
SMB_STRUCT_STAT st;
+ fstring user;
fstring dev;
int ret;
char addr[INET6_ADDRSTRLEN];
bool on_err_call_dis_hook = false;
- NTSTATUS status;
+ *user = 0;
fstrcpy(dev, pdev);
SET_STAT_INVALID(st);
- if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
+ if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
return NULL;
}
conn = conn_new();
if (!conn) {
DEBUG(0,("Couldn't find free connection.\n"));
- *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
+ *status = NT_STATUS_INSUFFICIENT_RESOURCES;
return NULL;
}
conn->params->service = snum;
-
- status = create_connection_server_info(
- conn, snum, vuser ? vuser->server_info : NULL, password,
- &conn->server_info);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("create_connection_server_info failed: %s\n",
- nt_errstr(status)));
- *pstatus = status;
+ conn->nt_user_token = NULL;
+
+ if (lp_guest_only(snum)) {
+ const char *guestname = lp_guestaccount();
+ NTSTATUS status2;
+ char *found_username = NULL;
+
+ guest = True;
+ pass = getpwnam_alloc(NULL, guestname);
+ if (!pass) {
+ DEBUG(0,("make_connection_snum: Invalid guest "
+ "account %s??\n",guestname));
+ conn_free(conn);
+ *status = NT_STATUS_NO_SUCH_USER;
+ return NULL;
+ }
+ status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
+ &conn->uid, &conn->gid,
+ &found_username,
+ &conn->nt_user_token);
+ if (!NT_STATUS_IS_OK(status2)) {
+ TALLOC_FREE(pass);
+ conn_free(conn);
+ *status = status2;
+ return NULL;
+ }
+ fstrcpy(user, found_username);
+ string_set(&conn->user,user);
+ conn->force_user = True;
+ TALLOC_FREE(found_username);
+ TALLOC_FREE(pass);
+ DEBUG(3,("Guest only user %s\n",user));
+ } else if (vuser) {
+ if (vuser->guest) {
+ if (!lp_guest_ok(snum)) {
+ DEBUG(2, ("guest user (from session setup) "
+ "not permitted to access this share "
+ "(%s)\n", lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
+ } else {
+ if (!user_ok_token(vuser->user.unix_name,
+ vuser->nt_user_token, snum)) {
+ DEBUG(2, ("user '%s' (from session setup) not "
+ "permitted to access this share "
+ "(%s)\n", vuser->user.unix_name,
+ lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
+ }
+ conn->vuid = vuser->vuid;
+ conn->uid = vuser->uid;
+ conn->gid = vuser->gid;
+ string_set(&conn->user,vuser->user.unix_name);
+ fstrcpy(user,vuser->user.unix_name);
+ guest = vuser->guest;
+ } else if (lp_security() == SEC_SHARE) {
+ NTSTATUS status2;
+ char *found_username = NULL;
+
+ /* add it as a possible user name if we
+ are in share mode security */
+ add_session_user(lp_servicename(snum));
+ /* shall we let them in? */
+ if (!authorise_login(snum,user,password,&guest)) {
+ DEBUG( 2, ( "Invalid username/password for [%s]\n",
+ lp_servicename(snum)) );
+ conn_free(conn);
+ *status = NT_STATUS_WRONG_PASSWORD;
+ return NULL;
+ }
+ pass = Get_Pwnam_alloc(talloc_tos(), user);
+ status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
+ &conn->uid, &conn->gid,
+ &found_username,
+ &conn->nt_user_token);
+ TALLOC_FREE(pass);
+ if (!NT_STATUS_IS_OK(status2)) {
+ conn_free(conn);
+ *status = status2;
+ return NULL;
+ }
+ fstrcpy(user, found_username);
+ string_set(&conn->user,user);
+ TALLOC_FREE(found_username);
+ conn->force_user = True;
+ } else {
+ DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
return NULL;
}
- if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
- conn->force_user = true;
- }
-
- add_session_user(conn->server_info->unix_name);
+ add_session_user(user);
safe_strcpy(conn->client_address,
client_addr(get_client_fd(),addr,sizeof(addr)),
@@ -775,84 +810,126 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->veto_oplock_list = NULL;
conn->aio_write_behind_list = NULL;
string_set(&conn->dirpath,"");
+ string_set(&conn->user,user);
conn->read_only = lp_readonly(SNUM(conn));
conn->admin_user = False;
+ /*
+ * If force user is true, then store the given userid and the gid of
+ * the user we're forcing.
+ * For auxiliary groups see below.
+ */
+
if (*lp_force_user(snum)) {
+ NTSTATUS status2;
- /*
- * Replace conn->server_info with a completely faked up one
- * from the username we are forced into :-)
- */
-
- char *fuser;
- struct auth_serversupplied_info *forced_serverinfo;
-
- fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
- lp_servicename(snum));
- if (fuser == NULL) {
- conn_free(conn);
- *pstatus = NT_STATUS_NO_MEMORY;
- return NULL;
- }
-
- status = make_serverinfo_from_username(
- conn, fuser, conn->server_info->guest,
- &forced_serverinfo);
- if (!NT_STATUS_IS_OK(status)) {
+ status2 = find_forced_user(conn,
+ (vuser != NULL) && vuser->guest,
+ user);
+ if (!NT_STATUS_IS_OK(status2)) {
conn_free(conn);
- *pstatus = status;
+ *status = status2;
return NULL;
}
-
- TALLOC_FREE(conn->server_info);
- conn->server_info = forced_serverinfo;
-
+ string_set(&conn->user,user);
conn->force_user = True;
- DEBUG(3,("Forced user %s\n", fuser));
+ DEBUG(3,("Forced user %s\n",user));
}
/*
* If force group is true, then override
* any groupid stored for the connecting user.
*/
-
+
if (*lp_force_group(snum)) {
+ NTSTATUS status2;
+ DOM_SID group_sid;
- status = find_forced_group(
- conn->force_user, snum, conn->server_info->unix_name,
- &conn->server_info->ptok->user_sids[1],
- &conn->server_info->utok.gid);
-
- if (!NT_STATUS_IS_OK(status)) {
+ status2 = find_forced_group(conn->force_user,
+ snum, user,
+ &group_sid, &conn->gid);
+ if (!NT_STATUS_IS_OK(status2)) {
conn_free(conn);
- *pstatus = status;
+ *status = status2;
return NULL;
}
+
+ if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
+
+ /* Not force user and not security=share, but force
+ * group. vuser has a token to copy */
+
+ conn->nt_user_token = dup_nt_token(
+ NULL, vuser->nt_user_token);
+ if (conn->nt_user_token == NULL) {
+ DEBUG(0, ("dup_nt_token failed\n"));
+ conn_free(conn);
+ *status = NT_STATUS_NO_MEMORY;
+ return NULL;
+ }
+ }
+
+ /* If conn->nt_user_token is still NULL, we have
+ * security=share. This means ignore the SID, as we had no
+ * vuser to copy from */
+
+ if (conn->nt_user_token != NULL) {
+ /* Overwrite the primary group sid */
+ sid_copy(&conn->nt_user_token->user_sids[1],
+ &group_sid);
+
+ }
+ conn->force_group = True;
}
- conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
+ if (conn->nt_user_token != NULL) {
+ size_t i;
+
+ /* We have a share-specific token from force [user|group].
+ * This means we have to create the list of unix groups from
+ * the list of sids. */
+
+ conn->ngroups = 0;
+ conn->groups = NULL;
+
+ for (i=0; i<conn->nt_user_token->num_sids; i++) {
+ gid_t gid;
+ DOM_SID *sid = &conn->nt_user_token->user_sids[i];
+
+ if (!sid_to_gid(sid, &gid)) {
+ DEBUG(10, ("Could not convert SID %s to gid, "
+ "ignoring it\n",
+ sid_string_dbg(sid)));
+ continue;
+ }
+ if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
+ &conn->ngroups)) {
+ DEBUG(0, ("add_gid_to_array_unique failed\n"));
+ conn_free(conn);
+ *status = NT_STATUS_NO_MEMORY;
+ return NULL;
+ }
+ }
+ }
{
char *s = talloc_sub_advanced(talloc_tos(),
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
lp_pathname(snum));
if (!s) {
conn_free(conn);
- *pstatus = NT_STATUS_NO_MEMORY;
+ *status = NT_STATUS_NO_MEMORY;
return NULL;
}
if (!set_conn_connectpath(conn,s)) {
TALLOC_FREE(s);
conn_free(conn);
- *pstatus = NT_STATUS_NO_MEMORY;
+ *status = NT_STATUS_NO_MEMORY;
return NULL;
}
DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
@@ -869,13 +946,32 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
{
bool can_write = False;
+ NT_USER_TOKEN *token = conn->nt_user_token ?
+ conn->nt_user_token :
+ (vuser ? vuser->nt_user_token : NULL);
+
+ /*
+ * I don't believe this can happen. But the
+ * logic above is convoluted enough to confuse
+ * automated checkers, so be sure. JRA.
+ */
+
+ if (token == NULL) {
+ DEBUG(0,("make_connection: connection to %s "
+ "denied due to missing "
+ "NT token.\n",
+ lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
- can_write = share_access_check(conn->server_info->ptok,
- lp_servicename(snum),
- FILE_WRITE_DATA);
+ can_write = share_access_check(token,
+ lp_servicename(snum),
+ FILE_WRITE_DATA);
if (!can_write) {
- if (!share_access_check(conn->server_info->ptok,
+ if (!share_access_check(token,
lp_servicename(snum),
FILE_READ_DATA)) {
/* No access, read or write. */
@@ -884,7 +980,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
"descriptor.\n",
lp_servicename(snum)));
conn_free(conn);
- *pstatus = NT_STATUS_ACCESS_DENIED;
+ *status = NT_STATUS_ACCESS_DENIED;
return NULL;
} else {
conn->read_only = True;
@@ -897,7 +993,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
DEBUG(0, ("vfs_init failed for service %s\n",
lp_servicename(snum)));
conn_free(conn);
- *pstatus = NT_STATUS_BAD_NETWORK_NAME;
+ *status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
@@ -915,13 +1011,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
lp_servicename(snum),
conn->connectpath));
conn_free(conn);
- *pstatus = NT_STATUS_BAD_NETWORK_NAME;
+ *status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
}
if ((!conn->printer) && (!conn->ipc)) {
- conn->notify_ctx = notify_init(conn, server_id_self(),
+ conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
smbd_messaging_context(),
smbd_event_context(),
conn);
@@ -939,7 +1035,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
DEBUG(1, ("Max connections (%d) exceeded for %s\n",
lp_max_connections(snum), lp_servicename(snum)));
conn_free(conn);
- *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
+ *status = NT_STATUS_INSUFFICIENT_RESOURCES;
return NULL;
}
@@ -949,7 +1045,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if (!claim_connection(conn, lp_servicename(snum), 0)) {
DEBUG(1, ("Could not store connections entry\n"));
conn_free(conn);
- *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
+ *status = NT_STATUS_INTERNAL_DB_ERROR;
return NULL;
}
@@ -958,12 +1054,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
/* execute any "root preexec = " line */
if (*lp_rootpreexec(snum)) {
char *cmd = talloc_sub_advanced(talloc_tos(),
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
lp_rootpreexec(snum));
DEBUG(5,("cmd=%s\n",cmd));
ret = smbrun(cmd,NULL);
@@ -973,7 +1067,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
"connection\n", ret));
yield_connection(conn, lp_servicename(snum));
conn_free(conn);
- *pstatus = NT_STATUS_ACCESS_DENIED;
+ *status = NT_STATUS_ACCESS_DENIED;
return NULL;
}
}
@@ -984,7 +1078,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
DEBUG(0,("Can't become connected user!\n"));
yield_connection(conn, lp_servicename(snum));
conn_free(conn);
- *pstatus = NT_STATUS_LOGON_FAILURE;
+ *status = NT_STATUS_LOGON_FAILURE;
return NULL;
}
@@ -997,19 +1091,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
/* execute any "preexec = " line */
if (*lp_preexec(snum)) {
char *cmd = talloc_sub_advanced(talloc_tos(),
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
lp_preexec(snum));
ret = smbrun(cmd,NULL);
TALLOC_FREE(cmd);
if (ret != 0 && lp_preexec_close(snum)) {
DEBUG(1,("preexec gave %d - failing connection\n",
ret));
- *pstatus = NT_STATUS_ACCESS_DENIED;
+ *status = NT_STATUS_ACCESS_DENIED;
goto err_root_exit;
}
}
@@ -1033,10 +1125,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
to allow any filesystems needing user credentials to initialize
themselves. */
- if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
- conn->server_info->unix_name) < 0) {
+ if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
DEBUG(0,("make_connection: VFS make connection failed!\n"));
- *pstatus = NT_STATUS_UNSUCCESSFUL;
+ *status = NT_STATUS_UNSUCCESSFUL;
goto err_root_exit;
}
@@ -1060,7 +1151,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->connectpath, lp_servicename(snum),
strerror(errno) ));
}
- *pstatus = NT_STATUS_BAD_NETWORK_NAME;
+ *status = NT_STATUS_BAD_NETWORK_NAME;
goto err_root_exit;
}
@@ -1101,8 +1192,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->client_address );
dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
dbgtext( "connect to service %s ", lp_servicename(snum) );
- dbgtext( "initially as user %s ",
- conn->server_info->unix_name );
+ dbgtext( "initially as user %s ", user );
dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
dbgtext( "(pid %d)\n", (int)sys_getpid() );
}
@@ -1143,7 +1233,7 @@ connection_struct *make_connection_with_chdir(const char *service_in,
*/
if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
- DEBUG(0,("make_connection_with_chdir: Can't change "
+ DEBUG(0,("move_driver_to_download_area: Can't change "
"directory to %s for [print$] (%s)\n",
conn->connectpath,strerror(errno)));
yield_connection(conn, lp_servicename(SNUM(conn)));
@@ -1322,12 +1412,10 @@ void close_cnum(connection_struct *conn, uint16 vuid)
if (*lp_postexec(SNUM(conn)) &&
change_to_user(conn, vuid)) {
char *cmd = talloc_sub_advanced(talloc_tos(),
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
lp_postexec(SNUM(conn)));
smbrun(cmd,NULL);
TALLOC_FREE(cmd);
@@ -1338,12 +1426,10 @@ void close_cnum(connection_struct *conn, uint16 vuid)
/* execute any "root postexec = " line */
if (*lp_rootpostexec(SNUM(conn))) {
char *cmd = talloc_sub_advanced(talloc_tos(),
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name,
- conn->connectpath,
- conn->server_info->utok.gid,
- conn->server_info->sanitized_username,
- pdb_get_domain(conn->server_info->sam_account),
+ lp_servicename(SNUM(conn)), conn->user,
+ conn->connectpath, conn->gid,
+ get_current_username(),
+ current_user_info.domain,
lp_rootpostexec(SNUM(conn)));
smbrun(cmd,NULL);
TALLOC_FREE(cmd);
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 3b431a19be..000b2f5d9c 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -75,7 +75,7 @@ bool session_claim(user_struct *vuser)
/* don't register sessions for the guest user - its just too
expensive to go through pam session code for browsing etc */
- if (vuser->server_info->guest) {
+ if (vuser->guest) {
return True;
}
@@ -164,12 +164,12 @@ bool session_claim(user_struct *vuser)
hostname = client_addr(get_client_fd(),addr,sizeof(addr));
}
- fstrcpy(sessionid.username, vuser->server_info->unix_name);
+ fstrcpy(sessionid.username, vuser->user.unix_name);
fstrcpy(sessionid.hostname, hostname);
sessionid.id_num = i; /* Only valid for utmp sessions */
sessionid.pid = pid;
- sessionid.uid = vuser->server_info->utok.uid;
- sessionid.gid = vuser->server_info->utok.gid;
+ sessionid.uid = vuser->uid;
+ sessionid.gid = vuser->gid;
fstrcpy(sessionid.remote_machine, get_remote_machine_name());
fstrcpy(sessionid.ip_addr_str,
client_addr(get_client_fd(),addr,sizeof(addr)));
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 9c9d0a97bc..98594b0769 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -45,7 +45,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status,
(lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
DEBUG(3,("No such user %s [%s] - using guest account\n",
user, domain));
- status = make_server_info_guest(NULL, server_info);
+ status = make_server_info_guest(server_info);
}
}
@@ -53,7 +53,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status,
if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
DEBUG(3,("Registered username %s for guest access\n",
user));
- status = make_server_info_guest(NULL, server_info);
+ status = make_server_info_guest(server_info);
}
}
@@ -442,7 +442,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
if (pw) {
/* if a real user check pam account restrictions */
/* only really perfomed if "obey pam restriction" is true */
- /* do this before an eventual mapping to guest occurs */
+ /* do this before an eventual mappign to guest occurs */
ret = smb_pam_accountcheck(pw->pw_name);
if ( !NT_STATUS_IS_OK(ret)) {
DEBUG(1,("PAM account restriction "
@@ -488,7 +488,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
reload_services(True);
if ( map_domainuser_to_guest ) {
- make_server_info_guest(NULL, &server_info);
+ make_server_info_guest(&server_info);
} else if (logon_info) {
/* pass the unmapped username here since map_username()
will be called again from inside make_server_info_info3() */
@@ -530,7 +530,9 @@ static void reply_spnego_kerberos(struct smb_request *req,
}
}
- server_info->nss_token |= username_was_mapped;
+ if (username_was_mapped) {
+ server_info->was_mapped = username_was_mapped;
+ }
/* we need to build the token for the user. make_server_info_guest()
already does this */
@@ -558,13 +560,9 @@ static void reply_spnego_kerberos(struct smb_request *req,
if (!is_partial_auth_vuid(sess_vuid)) {
sess_vuid = register_initial_vuid();
}
-
- data_blob_free(&server_info->user_session_key);
- server_info->user_session_key = session_key;
- session_key = data_blob_null;
-
sess_vuid = register_existing_vuid(sess_vuid,
server_info,
+ session_key,
nullblob,
client);
@@ -575,6 +573,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
if (sess_vuid == UID_FIELD_INVALID ) {
ret = NT_STATUS_LOGON_FAILURE;
+ data_blob_free(&session_key);
} else {
/* current_user_info is changed on new vuid */
reload_services( True );
@@ -644,24 +643,23 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
if (NT_STATUS_IS_OK(nt_status)) {
DATA_BLOB nullblob = data_blob_null;
+ DATA_BLOB session_key =
+ data_blob(
+ (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
+ (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
if (!is_partial_auth_vuid(vuid)) {
+ data_blob_free(&session_key);
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
-
- data_blob_free(&server_info->user_session_key);
- server_info->user_session_key =
- data_blob_talloc(
- server_info,
- (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
- (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
-
/* register_existing_vuid keeps the server info */
if (register_existing_vuid(vuid,
- server_info, nullblob,
+ server_info,
+ session_key, nullblob,
(*auth_ntlmssp_state)->ntlmssp_state->user) !=
vuid) {
+ data_blob_free(&session_key);
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
@@ -1352,9 +1350,6 @@ static int shutdown_other_smbds(struct db_record *rec,
return 0;
}
- DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
- "(IP %s)\n", procid_to_pid(&crec->pid), ip));
-
messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
&data_blob_null);
return 0;
@@ -1403,6 +1398,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
bool doencrypt = global_encrypted_passwords_negotiated;
+ DATA_BLOB session_key;
+
START_PROFILE(SMBsesssetupX);
ZERO_STRUCT(lm_resp);
@@ -1753,6 +1750,13 @@ void reply_sesssetup_and_X(struct smb_request *req)
}
}
+ if (server_info->user_session_key.data) {
+ session_key = data_blob(server_info->user_session_key.data,
+ server_info->user_session_key.length);
+ } else {
+ session_key = data_blob_null;
+ }
+
data_blob_clear_free(&plaintext_password);
/* it's ok - setup a reply */
@@ -1771,6 +1775,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
if (lp_security() == SEC_SHARE) {
sess_vuid = UID_FIELD_INVALID;
+ data_blob_free(&session_key);
TALLOC_FREE(server_info);
} else {
/* Ignore the initial vuid. */
@@ -1778,6 +1783,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
+ data_blob_free(&session_key);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
END_PROFILE(SMBsesssetupX);
@@ -1786,11 +1792,13 @@ void reply_sesssetup_and_X(struct smb_request *req)
/* register_existing_vuid keeps the server info */
sess_vuid = register_existing_vuid(sess_vuid,
server_info,
+ session_key,
nt_resp.data ? nt_resp : lm_resp,
sub_user);
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
+ data_blob_free(&session_key);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
END_PROFILE(SMBsesssetupX);
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
index f5f79c86e5..512126254a 100644
--- a/source/smbd/share_access.c
+++ b/source/smbd/share_access.c
@@ -27,6 +27,8 @@
* + and & may be combined
*/
+extern userdom_struct current_user_info;
+
static bool do_group_checks(const char **name, const char **pattern)
{
if ((*name)[0] == '@') {
@@ -64,7 +66,6 @@ static bool do_group_checks(const char **name, const char **pattern)
static bool token_contains_name(TALLOC_CTX *mem_ctx,
const char *username,
- const char *domain,
const char *sharename,
const struct nt_user_token *token,
const char *name)
@@ -74,7 +75,8 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
enum lsa_SidType type;
if (username != NULL) {
- name = talloc_sub_basic(mem_ctx, username, domain, name);
+ name = talloc_sub_basic(mem_ctx, username,
+ current_user_info.domain, name);
}
if (sharename != NULL) {
name = talloc_string_sub(mem_ctx, name, "%S", sharename);
@@ -150,7 +152,6 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
*/
bool token_contains_name_in_list(const char *username,
- const char *domain,
const char *sharename,
const struct nt_user_token *token,
const char **list)
@@ -166,8 +167,7 @@ bool token_contains_name_in_list(const char *username,
}
while (*list != NULL) {
- if (token_contains_name(mem_ctx, username, domain, sharename,
- token, *list)) {
+ if (token_contains_name(mem_ctx, username, sharename,token, *list)) {
TALLOC_FREE(mem_ctx);
return True;
}
@@ -191,12 +191,10 @@ bool token_contains_name_in_list(const char *username,
* The other use is the netgroup check when using @group or &group.
*/
-bool user_ok_token(const char *username, const char *domain,
- struct nt_user_token *token, int snum)
+bool user_ok_token(const char *username, struct nt_user_token *token, int snum)
{
if (lp_invalid_users(snum) != NULL) {
- if (token_contains_name_in_list(username, domain,
- lp_servicename(snum),
+ if (token_contains_name_in_list(username, lp_servicename(snum),
token,
lp_invalid_users(snum))) {
DEBUG(10, ("User %s in 'invalid users'\n", username));
@@ -205,7 +203,7 @@ bool user_ok_token(const char *username, const char *domain,
}
if (lp_valid_users(snum) != NULL) {
- if (!token_contains_name_in_list(username, domain,
+ if (!token_contains_name_in_list(username,
lp_servicename(snum), token,
lp_valid_users(snum))) {
DEBUG(10, ("User %s not in 'valid users'\n",
@@ -222,8 +220,7 @@ bool user_ok_token(const char *username, const char *domain,
DEBUG(0, ("'only user = yes' and no 'username ='\n"));
return False;
}
- if (!token_contains_name_in_list(NULL, domain,
- lp_servicename(snum),
+ if (!token_contains_name_in_list(NULL, lp_servicename(snum),
token, list)) {
DEBUG(10, ("%s != 'username'\n", username));
return False;
@@ -251,13 +248,12 @@ bool user_ok_token(const char *username, const char *domain,
*/
bool is_share_read_only_for_token(const char *username,
- const char *domain,
struct nt_user_token *token, int snum)
{
bool result = lp_readonly(snum);
if (lp_readlist(snum) != NULL) {
- if (token_contains_name_in_list(username, domain,
+ if (token_contains_name_in_list(username,
lp_servicename(snum), token,
lp_readlist(snum))) {
result = True;
@@ -265,7 +261,7 @@ bool is_share_read_only_for_token(const char *username,
}
if (lp_writelist(snum) != NULL) {
- if (token_contains_name_in_list(username, domain,
+ if (token_contains_name_in_list(username,
lp_servicename(snum), token,
lp_writelist(snum))) {
result = False;
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 1e2095a3ea..13105dce0f 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -28,6 +28,7 @@
extern int max_send;
extern enum protocol_types Protocol;
extern uint32 global_client_caps;
+extern struct current_user current_user;
#define get_file_size(sbuf) ((sbuf).st_size)
#define DIR_ENTRY_SAFETY_MARGIN 4096
@@ -177,7 +178,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
char *p;
char **names, **tmp;
size_t num_names;
- ssize_t sizeret = -1;
+ ssize_t sizeret;
if (!lp_ea_support(SNUM(conn))) {
*pnames = NULL;
@@ -503,7 +504,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s
static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
{
struct ea_list *ea_list_head = NULL;
- size_t converted_size, offset = 0;
+ size_t offset = 0;
while (offset + 2 < data_size) {
struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
@@ -521,11 +522,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
if (pdata[offset + namelen] != '\0') {
return NULL;
}
- if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
- &converted_size)) {
- DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
- "failed: %s", strerror(errno)));
- }
+ pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
if (!eal->ea.name) {
return NULL;
}
@@ -547,7 +544,6 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
uint16 val_len;
unsigned int namelen;
- size_t converted_size;
if (!eal) {
return NULL;
@@ -569,10 +565,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
if (pdata[namelen + 4] != '\0') {
return NULL;
}
- if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
- DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
- strerror(errno)));
- }
+ pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
if (!eal->ea.name) {
return NULL;
}
@@ -1892,7 +1885,7 @@ static void call_trans2findfirst(connection_struct *conn,
bool requires_resume_key;
int info_level;
char *directory = NULL;
- char *mask = NULL;
+ const char *mask = NULL;
char *p;
int last_entry_off=0;
int dptr_num = -1;
@@ -1980,7 +1973,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return;
}
- ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
+ ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
return;
@@ -1996,12 +1989,10 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
if(p == NULL) {
/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
if((directory[0] == '.') && (directory[1] == '\0')) {
- mask = talloc_strdup(ctx,"*");
- if (!mask) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
+ mask = "*";
mask_contains_wcard = True;
+ } else {
+ mask = directory;
}
directory = talloc_strdup(talloc_tos(), "./");
if (!directory) {
@@ -2009,6 +2000,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return;
}
} else {
+ mask = p+1;
*p = 0;
}
@@ -2840,11 +2832,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
fsp.fnum = -1;
/* access check */
- if (conn->server_info->utok.uid != 0) {
- DEBUG(0,("set_user_quota: access_denied "
- "service [%s] user [%s]\n",
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ if (current_user.ut.uid != 0) {
+ DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
+ lp_servicename(SNUM(conn)),conn->user));
reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -3004,7 +2994,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
* in our list of SIDs.
*/
if (nt_token_check_sid(&global_sid_Builtin_Guests,
- conn->server_info->ptok)) {
+ current_user.nt_user_token)) {
flags |= SMB_WHOAMI_GUEST;
}
@@ -3012,7 +3002,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
* is in our list of SIDs.
*/
if (nt_token_check_sid(&global_sid_Authenticated_Users,
- conn->server_info->ptok)) {
+ current_user.nt_user_token)) {
flags &= ~SMB_WHOAMI_GUEST;
}
@@ -3028,18 +3018,16 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
+ 4 /* num_sids */
+ 4 /* SID bytes */
+ 4 /* pad/reserved */
- + (conn->server_info->utok.ngroups * 8)
+ + (current_user.ut.ngroups * 8)
/* groups list */
- + (conn->server_info->ptok->num_sids *
+ + (current_user.nt_user_token->num_sids *
SID_MAX_SIZE)
/* SID list */;
SIVAL(pdata, 0, flags);
SIVAL(pdata, 4, SMB_WHOAMI_MASK);
- SBIG_UINT(pdata, 8,
- (SMB_BIG_UINT)conn->server_info->utok.uid);
- SBIG_UINT(pdata, 16,
- (SMB_BIG_UINT)conn->server_info->utok.gid);
+ SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
+ SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
if (data_len >= max_data_bytes) {
@@ -3054,18 +3042,18 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
break;
}
- SIVAL(pdata, 24, conn->server_info->utok.ngroups);
- SIVAL(pdata, 28, conn->server_info->num_sids);
+ SIVAL(pdata, 24, current_user.ut.ngroups);
+ SIVAL(pdata, 28,
+ current_user.nt_user_token->num_sids);
/* We walk the SID list twice, but this call is fairly
* infrequent, and I don't expect that it's performance
* sensitive -- jpeach
*/
for (i = 0, sid_bytes = 0;
- i < conn->server_info->ptok->num_sids; ++i) {
+ i < current_user.nt_user_token->num_sids; ++i) {
sid_bytes += ndr_size_dom_sid(
- &conn->server_info->ptok->user_sids[i],
- 0);
+ &current_user.nt_user_token->user_sids[i], 0);
}
/* SID list byte count */
@@ -3076,21 +3064,20 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
data_len = 40;
/* GID list */
- for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
+ for (i = 0; i < current_user.ut.ngroups; ++i) {
SBIG_UINT(pdata, data_len,
- (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
+ (SMB_BIG_UINT)current_user.ut.groups[i]);
data_len += 8;
}
/* SID list */
for (i = 0;
- i < conn->server_info->ptok->num_sids; ++i) {
+ i < current_user.nt_user_token->num_sids; ++i) {
int sid_len = ndr_size_dom_sid(
- &conn->server_info->ptok->user_sids[i],
- 0);
+ &current_user.nt_user_token->user_sids[i], 0);
sid_linearize(pdata + data_len, sid_len,
- &conn->server_info->ptok->user_sids[i]);
+ &current_user.nt_user_token->user_sids[i]);
data_len += sid_len;
}
@@ -3285,11 +3272,9 @@ cap_low = 0x%x, cap_high = 0x%x\n",
ZERO_STRUCT(quotas);
/* access check */
- if ((conn->server_info->utok.uid != 0)
- ||!CAN_WRITE(conn)) {
+ if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
- lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ lp_servicename(SNUM(conn)),conn->user));
reply_doserror(req, ERRSRV, ERRaccess);
return;
}
@@ -3299,9 +3284,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
* --metze
*/
fsp = file_fsp(SVAL(params,0));
-
- if (!check_fsp_ntquota_handle(conn, req,
- fsp)) {
+ if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(
req, NT_STATUS_INVALID_HANDLE);
@@ -3686,10 +3669,10 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams,
size_t namelen;
smb_ucs2_t *namebuf;
- if (!push_ucs2_talloc(talloc_tos(), &namebuf,
- streams[i].name, &namelen) ||
- namelen <= 2)
- {
+ namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
+ streams[i].name);
+
+ if ((namelen == (size_t)-1) || (namelen <= 2)) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -3884,7 +3867,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
}
/* Initial check for valid fsp ptr. */
- if (!check_fsp_open(conn, req, fsp)) {
+ if (!check_fsp_open(conn, req, fsp, &current_user)) {
return;
}
@@ -3927,7 +3910,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
/*
* Original code - this is an open file.
*/
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
return;
}
@@ -5107,8 +5090,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, delete_on_close,
- &conn->server_info->utok)) {
+ if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
return NT_STATUS_ACCESS_DENIED;
}
return NT_STATUS_OK;
@@ -5895,7 +5877,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
*/
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(
+ inherit_access_acl(
conn, parent_dirname(fname),
fname, unixmode);
}
@@ -6584,7 +6566,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
fsp = file_fsp(SVAL(params,0));
/* Basic check for non-null fsp. */
- if (!check_fsp_open(conn, req, fsp)) {
+ if (!check_fsp_open(conn, req, fsp, &current_user)) {
return;
}
info_level = SVAL(params,2);
@@ -6637,7 +6619,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
/*
* Original code - this is an open file.
*/
- if (!check_fsp(conn, req, fsp)) {
+ if (!check_fsp(conn, req, fsp, &current_user)) {
return;
}
@@ -7569,7 +7551,7 @@ void reply_trans2(struct smb_request *req)
}
}
- if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
+ if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
DEBUG(0, ("talloc failed\n"));
reply_nterror(req, NT_STATUS_NO_MEMORY);
END_PROFILE(SMBtrans2);
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index 8998f6a371..ffa643a8f5 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -2,17 +2,17 @@
Unix SMB/CIFS implementation.
uid/user handling
Copyright (C) Andrew Tridgell 1992-1998
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -23,6 +23,29 @@
extern struct current_user current_user;
/****************************************************************************
+ Iterator functions for getting all gid's from current_user.
+****************************************************************************/
+
+gid_t get_current_user_gid_first(int *piterator)
+{
+ *piterator = 0;
+ return current_user.ut.gid;
+}
+
+gid_t get_current_user_gid_next(int *piterator)
+{
+ gid_t ret;
+
+ if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) {
+ return (gid_t)-1;
+ }
+
+ ret = current_user.ut.groups[*piterator];
+ (*piterator) += 1;
+ return ret;
+}
+
+/****************************************************************************
Become the guest user without changing the security context stack.
****************************************************************************/
@@ -36,62 +59,56 @@ bool change_to_guest(void)
if (!pass)
return(False);
}
-
+
#ifdef AIX
/* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before
setting IDs */
initgroups(pass->pw_name, pass->pw_gid);
#endif
-
+
set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
-
+
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
TALLOC_FREE(pass);
pass = NULL;
-
+
return True;
}
/*******************************************************************
Check if a username is OK.
-
- This sets up conn->server_info with a copy related to this vuser that
- later code can then mess with.
********************************************************************/
-static bool check_user_ok(connection_struct *conn, uint16_t vuid,
- struct auth_serversupplied_info *server_info,
- int snum)
+static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
{
unsigned int i;
struct vuid_cache_entry *ent = NULL;
bool readonly_share;
- bool admin_user;
+ NT_USER_TOKEN *token;
- for (i=0; i<VUID_CACHE_SIZE; i++) {
- ent = &conn->vuid_cache.array[i];
- if (ent->vuid == vuid) {
- conn->server_info = ent->server_info;
+ for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
+ if (conn->vuid_cache.array[i].vuid == vuser->vuid) {
+ ent = &conn->vuid_cache.array[i];
conn->read_only = ent->read_only;
conn->admin_user = ent->admin_user;
return(True);
}
}
- if (!user_ok_token(server_info->unix_name,
- pdb_get_domain(server_info->sam_account),
- server_info->ptok, snum))
+ if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum))
return(False);
- readonly_share = is_share_read_only_for_token(
- server_info->unix_name,
- pdb_get_domain(server_info->sam_account),
- server_info->ptok, snum);
+ readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
+ vuser->nt_user_token,
+ SNUM(conn));
+
+ token = conn->nt_user_token ?
+ conn->nt_user_token : vuser->nt_user_token;
if (!readonly_share &&
- !share_access_check(server_info->ptok, lp_servicename(snum),
+ !share_access_check(token, lp_servicename(snum),
FILE_WRITE_DATA)) {
/* smb.conf allows r/w, but the security descriptor denies
* write. Fall back to looking at readonly. */
@@ -100,71 +117,31 @@ static bool check_user_ok(connection_struct *conn, uint16_t vuid,
"security descriptor\n"));
}
- if (!share_access_check(server_info->ptok, lp_servicename(snum),
+ if (!share_access_check(token, lp_servicename(snum),
readonly_share ?
FILE_READ_DATA : FILE_WRITE_DATA)) {
return False;
}
- admin_user = token_contains_name_in_list(
- server_info->unix_name,
- pdb_get_domain(server_info->sam_account),
- NULL, server_info->ptok, lp_admin_users(snum));
-
- ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry];
-
- conn->vuid_cache.next_entry =
- (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
-
- TALLOC_FREE(ent->server_info);
+ i = conn->vuid_cache.entries % VUID_CACHE_SIZE;
+ if (conn->vuid_cache.entries < VUID_CACHE_SIZE)
+ conn->vuid_cache.entries++;
- /*
- * If force_user was set, all server_info's are based on the same
- * username-based faked one.
- */
-
- ent->server_info = copy_serverinfo(
- conn, conn->force_user ? conn->server_info : server_info);
-
- if (ent->server_info == NULL) {
- ent->vuid = UID_FIELD_INVALID;
- return false;
- }
-
- ent->vuid = vuid;
+ ent = &conn->vuid_cache.array[i];
+ ent->vuid = vuser->vuid;
ent->read_only = readonly_share;
- ent->admin_user = admin_user;
+
+ ent->admin_user = token_contains_name_in_list(
+ vuser->user.unix_name, NULL, vuser->nt_user_token,
+ lp_admin_users(SNUM(conn)));
conn->read_only = ent->read_only;
conn->admin_user = ent->admin_user;
- conn->server_info = ent->server_info;
return(True);
}
/****************************************************************************
- Clear a vuid out of the connection's vuid cache
-****************************************************************************/
-
-void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
-{
- int i;
-
- for (i=0; i<VUID_CACHE_SIZE; i++) {
- struct vuid_cache_entry *ent;
-
- ent = &conn->vuid_cache.array[i];
-
- if (ent->vuid == vuid) {
- ent->vuid = UID_FIELD_INVALID;
- TALLOC_FREE(ent->server_info);
- ent->read_only = False;
- ent->admin_user = False;
- }
- }
-}
-
-/****************************************************************************
Become the user of a connection number without changing the security context
stack, but modify the current_user entries.
****************************************************************************/
@@ -176,9 +153,11 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
gid_t gid;
uid_t uid;
char group_c;
+ bool must_free_token = False;
+ NT_USER_TOKEN *token = NULL;
int num_groups = 0;
gid_t *group_list = NULL;
-
+
if (!conn) {
DEBUG(2,("change_to_user: Connection not open\n"));
return(False);
@@ -192,13 +171,13 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
*/
if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
- (current_user.ut.uid == conn->server_info->utok.uid)) {
+ (current_user.ut.uid == conn->uid)) {
DEBUG(4,("change_to_user: Skipping user change - already "
"user\n"));
return(True);
} else if ((current_user.conn == conn) &&
- (vuser != NULL) && (current_user.vuid == vuid) &&
- (current_user.ut.uid == vuser->server_info->utok.uid)) {
+ (vuser != 0) && (current_user.vuid == vuid) &&
+ (current_user.ut.uid == vuser->uid)) {
DEBUG(4,("change_to_user: Skipping user change - already "
"user\n"));
return(True);
@@ -206,30 +185,26 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
snum = SNUM(conn);
- if ((vuser) && !check_user_ok(conn, vuid, vuser->server_info, snum)) {
+ if ((vuser) && !check_user_ok(conn, vuser, snum)) {
DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
"not permitted access to share %s.\n",
- vuser->server_info->sanitized_username,
- vuser->server_info->unix_name, vuid,
+ vuser->user.smb_name, vuser->user.unix_name, vuid,
lp_servicename(snum)));
return False;
}
- /*
- * conn->server_info is now correctly set up with a copy we can mess
- * with for force_group etc.
- */
-
if (conn->force_user) /* security = share sets this too */ {
- uid = conn->server_info->utok.uid;
- gid = conn->server_info->utok.gid;
- group_list = conn->server_info->utok.groups;
- num_groups = conn->server_info->utok.ngroups;
+ uid = conn->uid;
+ gid = conn->gid;
+ group_list = conn->groups;
+ num_groups = conn->ngroups;
+ token = conn->nt_user_token;
} else if (vuser) {
- uid = conn->admin_user ? 0 : vuser->server_info->utok.uid;
- gid = conn->server_info->utok.gid;
- num_groups = conn->server_info->utok.ngroups;
- group_list = conn->server_info->utok.groups;
+ uid = conn->admin_user ? 0 : vuser->uid;
+ gid = vuser->gid;
+ num_groups = vuser->n_groups;
+ group_list = vuser->groups;
+ token = vuser->nt_user_token;
} else {
DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
"share %s.\n",vuid, lp_servicename(snum) ));
@@ -244,6 +219,13 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
if((group_c = *lp_force_group(snum))) {
+ token = dup_nt_token(NULL, token);
+ if (token == NULL) {
+ DEBUG(0, ("dup_nt_token failed\n"));
+ return False;
+ }
+ must_free_token = True;
+
if(group_c == '+') {
/*
@@ -255,21 +237,18 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
int i;
for (i = 0; i < num_groups; i++) {
- if (group_list[i]
- == conn->server_info->utok.gid) {
- gid = conn->server_info->utok.gid;
- gid_to_sid(&conn->server_info->ptok
- ->user_sids[1], gid);
+ if (group_list[i] == conn->gid) {
+ gid = conn->gid;
+ gid_to_sid(&token->user_sids[1], gid);
break;
}
}
} else {
- gid = conn->server_info->utok.gid;
- gid_to_sid(&conn->server_info->ptok->user_sids[1],
- gid);
+ gid = conn->gid;
+ gid_to_sid(&token->user_sids[1], gid);
}
}
-
+
/* Now set current_user since we will immediately also call
set_sec_ctx() */
@@ -277,14 +256,21 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
current_user.ut.groups = group_list;
set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
- conn->server_info->ptok);
+ token);
+
+ /*
+ * Free the new token (as set_sec_ctx copies it).
+ */
+
+ if (must_free_token)
+ TALLOC_FREE(token);
current_user.conn = conn;
current_user.vuid = vuid;
DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
(int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
-
+
return(True);
}
@@ -344,29 +330,29 @@ struct conn_ctx {
connection_struct *conn;
uint16 vuid;
};
-
+
/* A stack of current_user connection contexts. */
-
+
static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH];
static int conn_ctx_stack_ndx;
static void push_conn_ctx(void)
{
struct conn_ctx *ctx_p;
-
+
/* Check we don't overflow our stack */
-
+
if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
DEBUG(0, ("Connection context stack overflow!\n"));
smb_panic("Connection context stack overflow!\n");
}
-
+
/* Store previous user context */
ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
-
+
ctx_p->conn = current_user.conn;
ctx_p->vuid = current_user.vuid;
-
+
DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
(unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
@@ -376,7 +362,7 @@ static void push_conn_ctx(void)
static void pop_conn_ctx(void)
{
struct conn_ctx *ctx_p;
-
+
/* Check for stack underflow. */
if (conn_ctx_stack_ndx == 0) {
diff --git a/source/smbd/utmp.c b/source/smbd/utmp.c
index af947ef462..de6d707eaf 100644
--- a/source/smbd/utmp.c
+++ b/source/smbd/utmp.c
@@ -189,7 +189,7 @@ static const char *wt_pathname =
# endif
/* BSD-like systems might want "lastlog" support. */
-#if 0 /* *** Not yet implemented */
+/* *** Not yet implemented */
#ifndef HAVE_PUTUTLINE /* see "pututline_my()" */
static const char *ll_pathname =
# if defined (_PATH_LASTLOG) /* what other names (if any?) */
@@ -198,7 +198,6 @@ static const char *ll_pathname =
"" ;
# endif /* _PATH_LASTLOG */
#endif /* HAVE_PUTUTLINE */
-#endif
/*
* Get name of {u,w}tmp{,x} file.
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 1e137dd908..33a3a43aa4 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -177,7 +177,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
goto fail;
}
- handle = TALLOC_ZERO_P(conn, vfs_handle_struct);
+ handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct);
if (!handle) {
DEBUG(0,("TALLOC_ZERO() failed!\n"));
goto fail;
@@ -185,7 +185,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops));
handle->conn = conn;
if (module_param) {
- handle->param = talloc_strdup(conn, module_param);
+ handle->param = talloc_strdup(conn->mem_ctx, module_param);
}
DLIST_ADD(conn->vfs_handles, handle);
@@ -232,7 +232,7 @@ void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle, files_struct *fsp,
}
ext = (struct vfs_fsp_data *)TALLOC_ZERO(
- handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
+ handle->conn->mem_ctx, sizeof(struct vfs_fsp_data) + ext_size);
if (ext == NULL) {
return NULL;
}