summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c22
-rw-r--r--source3/smbd/fileio.c3
-rw-r--r--source3/smbd/files.c43
-rw-r--r--source3/smbd/globals.c3
-rw-r--r--source3/smbd/negprot.c5
-rw-r--r--source3/smbd/notify.c17
-rw-r--r--source3/smbd/nttrans.c2
-rw-r--r--source3/smbd/open.c37
-rw-r--r--source3/smbd/oplock.c28
-rw-r--r--source3/smbd/oplock_irix.c18
-rw-r--r--source3/smbd/oplock_onefs.c5
-rw-r--r--source3/smbd/posix_acls.c52
-rw-r--r--source3/smbd/reply.c36
-rw-r--r--source3/smbd/server.c12
-rw-r--r--source3/smbd/sesssetup.c11
-rw-r--r--source3/smbd/trans2.c14
-rw-r--r--source3/smbd/vfs.c15
17 files changed, 235 insertions, 88 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 78b8123680..d23b509af2 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -471,6 +471,7 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
SMB_STRUCT_STAT sbuf;
struct smb_file_time ft;
NTSTATUS status;
+ int ret = -1;
ZERO_STRUCT(sbuf);
ZERO_STRUCT(ft);
@@ -485,15 +486,19 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
/* Ensure we have a valid stat struct for the source. */
if (fsp->fh->fd != -1) {
- if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
- return map_nt_error_from_unix(errno);
- }
+ ret = SMB_VFS_FSTAT(fsp, &sbuf);
} else {
- if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) {
- return map_nt_error_from_unix(errno);
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
}
}
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+
if (!VALID_STAT(sbuf)) {
/* if it doesn't seem to be a real file */
return NT_STATUS_OK;
@@ -581,6 +586,13 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
*/
saved_status4 = update_write_time_on_close(fsp);
+ if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ /* Someone renamed the file or a parent directory containing
+ * this file. We can't do anything about this, we don't have
+ * an "update timestamp by fd" call in POSIX. Eat the error. */
+
+ saved_status4 = NT_STATUS_OK;
+ }
if (NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_IS_OK(saved_status1)) {
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index a9a97a2d14..adf664b396 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -256,10 +256,9 @@ ssize_t write_file(struct smb_request *req,
int write_path = -1;
if (fsp->print_file) {
- fstring sharename;
uint32 jobid;
- if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) {
+ if (!rap_to_pjobid(fsp->rap_print_jobid, NULL, &jobid)) {
DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n",
(unsigned int)fsp->rap_print_jobid ));
errno = EBADF;
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index efaadffc06..36e80a086a 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -356,6 +356,49 @@ files_struct *file_find_print(void)
}
/****************************************************************************
+ Find any fsp open with a pathname below that of an already open path.
+****************************************************************************/
+
+bool file_find_subpath(files_struct *dir_fsp)
+{
+ files_struct *fsp;
+ size_t dlen;
+ char *d_fullname = talloc_asprintf(talloc_tos(),
+ "%s/%s",
+ dir_fsp->conn->connectpath,
+ dir_fsp->fsp_name);
+
+ if (!d_fullname) {
+ return false;
+ }
+
+ dlen = strlen(d_fullname);
+
+ for (fsp=Files;fsp;fsp=fsp->next) {
+ char *d1_fullname;
+
+ if (fsp == dir_fsp) {
+ continue;
+ }
+
+ d1_fullname = talloc_asprintf(talloc_tos(),
+ "%s/%s",
+ fsp->conn->connectpath,
+ fsp->fsp_name);
+
+ if (strnequal(d_fullname, d1_fullname, dlen)) {
+ TALLOC_FREE(d_fullname);
+ TALLOC_FREE(d1_fullname);
+ return true;
+ }
+ TALLOC_FREE(d1_fullname);
+ }
+
+ TALLOC_FREE(d_fullname);
+ return false;
+}
+
+/****************************************************************************
Sync open files on a connection.
****************************************************************************/
diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c
index 3f8cb411e5..9e7d103562 100644
--- a/source3/smbd/globals.c
+++ b/source3/smbd/globals.c
@@ -66,7 +66,8 @@ struct fsp_singleton_cache fsp_fi_cache = {
.fsp = NULL,
.id = {
.devid = 0,
- .inode = 0
+ .inode = 0,
+ .extid = 0
}
};
unsigned long file_gen_counter = 0;
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 57608a9b40..a921954c49 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -27,7 +27,6 @@ extern enum protocol_types Protocol;
static void get_challenge(uint8 buff[8])
{
NTSTATUS nt_status;
- const uint8 *cryptkey;
/* We might be called more than once, multiple negprots are
* permitted */
@@ -42,8 +41,8 @@ static void get_challenge(uint8 buff[8])
smb_panic("cannot make_negprot_global_auth_context!");
}
DEBUG(10, ("get challenge: getting challenge\n"));
- cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
- memcpy(buff, cryptkey, 8);
+ negprot_global_auth_context->get_ntlm_challenge(
+ negprot_global_auth_context, buff);
}
/****************************************************************************
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 1d4f5e8c5b..8ceeaf5f55 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -214,6 +214,8 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
ZERO_STRUCT(e);
e.path = fullpath;
+ e.dir_fd = fsp->fh->fd;
+ e.dir_id = fsp->file_id;
e.filter = filter;
e.subdir_filter = 0;
if (recursive) {
@@ -370,13 +372,26 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
if ((fsp->notify->num_changes > 1000) || (name == NULL)) {
/*
* The real number depends on the client buf, just provide a
- * guard against a DoS here.
+ * guard against a DoS here. If name == NULL the CN backend is
+ * alerting us to a problem. Possibly dropped events. Clear
+ * queued changes and send the catch-all response to the client
+ * if a request is pending.
*/
TALLOC_FREE(fsp->notify->changes);
fsp->notify->num_changes = -1;
+ if (fsp->notify->requests != NULL) {
+ change_notify_reply(fsp->conn,
+ fsp->notify->requests->req,
+ fsp->notify->requests->max_param,
+ fsp->notify);
+ change_notify_remove_request(fsp->notify->requests);
+ }
return;
}
+ /* If we've exceeded the server side queue or received a NULL name
+ * from the underlying CN implementation, don't queue up any more
+ * requests until we can send a catch-all response to the client */
if (fsp->notify->num_changes == -1) {
return;
}
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index ad2366efae..86a46505a2 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1856,6 +1856,8 @@ static void call_nt_transact_ioctl(connection_struct *conn,
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
+
+ /* For backwards compatibility only store the dev/inode. */
push_file_id_16(pdata, &fsp->file_id);
memcpy(pdata+16,create_volume_objectid(conn,objid),16);
push_file_id_16(pdata+32, &fsp->file_id);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 9971ffa679..569c260319 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -132,6 +132,18 @@ static NTSTATUS fd_open(struct connection_struct *conn,
fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
if (fsp->fh->fd == -1) {
status = map_nt_error_from_unix(errno);
+ if (errno == EMFILE) {
+ static time_t last_warned = 0L;
+
+ if (time((time_t *) NULL) > last_warned) {
+ DEBUG(0,("Too many open files, unable "
+ "to open more! smbd's max "
+ "open files = %d\n",
+ lp_max_open_files()));
+ last_warned = time((time_t *) NULL);
+ }
+ }
+
}
DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
@@ -1428,7 +1440,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
"create_disposition = 0x%x create_options=0x%x "
"unix mode=0%o oplock_request=%d\n",
fname, new_dos_attributes, access_mask, share_access,
- create_disposition, create_options, unx_mode,
+ create_disposition, create_options, (unsigned int)unx_mode,
oplock_request));
if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
@@ -2445,6 +2457,25 @@ static NTSTATUS open_directory(connection_struct *conn,
fname,
access_mask,
&access_granted);
+
+ /* Were we trying to do a directory open
+ * for delete and didn't get DELETE
+ * access (only) ? Check if the
+ * directory allows DELETE_CHILD.
+ * See here:
+ * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
+ * for details. */
+
+ if ((NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
+ (access_mask & DELETE_ACCESS) &&
+ (access_granted == DELETE_ACCESS) &&
+ can_delete_file_in_directory(conn, fname))) {
+ DEBUG(10,("open_directory: overrode ACCESS_DENIED "
+ "on directory %s\n",
+ fname ));
+ status = NT_STATUS_OK;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_directory: check_open_rights on "
"file %s failed with %s\n",
@@ -2597,8 +2628,8 @@ void msg_file_was_renamed(struct messaging_context *msg,
}
/* Unpack the message. */
- pull_file_id_16(frm, &id);
- sharepath = &frm[16];
+ pull_file_id_24(frm, &id);
+ sharepath = &frm[24];
newname = sharepath + strlen(sharepath) + 1;
sp_len = strlen(sharepath);
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index b39e5bf634..22870283fa 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -40,8 +40,8 @@ void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
/* Put the kernel break info into the message. */
- push_file_id_16((char *)msg, &fsp->file_id);
- SIVAL(msg,16,fsp->fh->gen_id);
+ push_file_id_24((char *)msg, &fsp->file_id);
+ SIVAL(msg,24,fsp->fh->gen_id);
/* Don't need to be root here as we're only ever
sending to ourselves. */
@@ -583,8 +583,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
}
/* Pull the data from the message. */
- pull_file_id_16((char *)data->data, &id);
- file_id = (unsigned long)IVAL(data->data, 16);
+ pull_file_id_24((char *)data->data, &id);
+ file_id = (unsigned long)IVAL(data->data, 24);
DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n",
(int)procid_to_pid(&src), file_id_string_tos(&id),
@@ -865,12 +865,12 @@ void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e)
SIVAL(msg,16,e->private_options);
SIVAL(msg,20,(uint32)e->time.tv_sec);
SIVAL(msg,24,(uint32)e->time.tv_usec);
- push_file_id_16(msg+28, &e->id);
- SIVAL(msg,44,e->share_file_id);
- SIVAL(msg,48,e->uid);
- SSVAL(msg,52,e->flags);
+ push_file_id_24(msg+28, &e->id);
+ SIVAL(msg,52,e->share_file_id);
+ SIVAL(msg,56,e->uid);
+ SSVAL(msg,60,e->flags);
#ifdef CLUSTER_SUPPORT
- SIVAL(msg,54,e->pid.vnn);
+ SIVAL(msg,62,e->pid.vnn);
#endif
}
@@ -888,12 +888,12 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
e->private_options = IVAL(msg,16);
e->time.tv_sec = (time_t)IVAL(msg,20);
e->time.tv_usec = (int)IVAL(msg,24);
- pull_file_id_16(msg+28, &e->id);
- e->share_file_id = (unsigned long)IVAL(msg,44);
- e->uid = (uint32)IVAL(msg,48);
- e->flags = (uint16)SVAL(msg,52);
+ pull_file_id_24(msg+28, &e->id);
+ e->share_file_id = (unsigned long)IVAL(msg,52);
+ e->uid = (uint32)IVAL(msg,56);
+ e->flags = (uint16)SVAL(msg,60);
#ifdef CLUSTER_SUPPORT
- e->pid.vnn = IVAL(msg,54);
+ e->pid.vnn = IVAL(msg,62);
#endif
}
diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c
index bbc9132a08..89b8e0f7b5 100644
--- a/source3/smbd/oplock_irix.c
+++ b/source3/smbd/oplock_irix.c
@@ -103,6 +103,24 @@ static bool irix_oplocks_available(void)
return True;
}
+/*
+ * This is bad because the file_id should always be created through the vfs
+ * layer! Unfortunately, a conn struct isn't available here.
+ */
+static struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ struct file_id key;
+
+ /* the ZERO_STRUCT ensures padding doesn't break using the key as a
+ * blob */
+ ZERO_STRUCT(key);
+
+ key.devid = dev;
+ key.inode = inode;
+
+ return key;
+}
+
/****************************************************************************
* Deal with the IRIX kernel <--> smbd
* oplock break protocol.
diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c
index 0908ce4386..d4f181fc47 100644
--- a/source3/smbd/oplock_onefs.c
+++ b/source3/smbd/oplock_onefs.c
@@ -744,13 +744,13 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
po.po_flags_on |= P_NON_BLOCKING_SEMLOCK;
if (setprocoptions(&po) != 0) {
DEBUG(0, ("setprocoptions failed: %s.\n", strerror(errno)));
- goto err_out;
+ return NULL;
}
/* Setup the oplock contexts */
_ctx = talloc_zero(mem_ctx, struct kernel_oplocks);
if (!_ctx) {
- goto err_out;
+ return NULL;
}
ctx = talloc_zero(_ctx, struct onefs_oplocks_context);
@@ -788,7 +788,6 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
err_out:
talloc_free(_ctx);
- talloc_free(ctx);
return NULL;
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index e9b581efe8..2f84a831c6 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -719,12 +719,12 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn,
Count a linked list of canonical ACE entries.
****************************************************************************/
-static size_t count_canon_ace_list( canon_ace *list_head )
+static size_t count_canon_ace_list( canon_ace *l_head )
{
size_t count = 0;
canon_ace *ace;
- for (ace = list_head; ace; ace = ace->next)
+ for (ace = l_head; ace; ace = ace->next)
count++;
return count;
@@ -734,13 +734,13 @@ static size_t count_canon_ace_list( canon_ace *list_head )
Free a linked list of canonical ACE entries.
****************************************************************************/
-static void free_canon_ace_list( canon_ace *list_head )
+static void free_canon_ace_list( canon_ace *l_head )
{
canon_ace *list, *next;
- for (list = list_head; list; list = next) {
+ for (list = l_head; list; list = next) {
next = list->next;
- DLIST_REMOVE(list_head, list);
+ DLIST_REMOVE(l_head, list);
SAFE_FREE(list);
}
}
@@ -916,7 +916,7 @@ static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
static void merge_aces( canon_ace **pp_list_head )
{
- canon_ace *list_head = *pp_list_head;
+ canon_ace *l_head = *pp_list_head;
canon_ace *curr_ace_outer;
canon_ace *curr_ace_outer_next;
@@ -925,7 +925,7 @@ static void merge_aces( canon_ace **pp_list_head )
* with identical SIDs.
*/
- for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
+ for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
canon_ace *curr_ace;
canon_ace *curr_ace_next;
@@ -947,7 +947,7 @@ static void merge_aces( canon_ace **pp_list_head )
/* Merge two allow or two deny ACE's. */
curr_ace_outer->perms |= curr_ace->perms;
- DLIST_REMOVE(list_head, curr_ace);
+ DLIST_REMOVE(l_head, curr_ace);
SAFE_FREE(curr_ace);
curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
}
@@ -960,7 +960,7 @@ static void merge_aces( canon_ace **pp_list_head )
* appears only once in the list.
*/
- for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
+ for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
canon_ace *curr_ace;
canon_ace *curr_ace_next;
@@ -992,7 +992,7 @@ static void merge_aces( canon_ace **pp_list_head )
* The deny overrides the allow. Remove the allow.
*/
- DLIST_REMOVE(list_head, curr_ace);
+ DLIST_REMOVE(l_head, curr_ace);
SAFE_FREE(curr_ace);
curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
@@ -1008,7 +1008,7 @@ static void merge_aces( canon_ace **pp_list_head )
* before we can get to an allow ace.
*/
- DLIST_REMOVE(list_head, curr_ace_outer);
+ DLIST_REMOVE(l_head, curr_ace_outer);
SAFE_FREE(curr_ace_outer);
break;
}
@@ -1019,7 +1019,7 @@ static void merge_aces( canon_ace **pp_list_head )
/* We may have modified the list. */
- *pp_list_head = list_head;
+ *pp_list_head = l_head;
}
/****************************************************************************
@@ -2305,12 +2305,12 @@ static bool unpack_canon_ace(files_struct *fsp,
static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
{
- canon_ace *list_head = *pp_list_head;
+ canon_ace *l_head = *pp_list_head;
canon_ace *owner_ace = NULL;
canon_ace *other_ace = NULL;
canon_ace *ace = NULL;
- for (ace = list_head; ace; ace = ace->next) {
+ for (ace = l_head; ace; ace = ace->next) {
if (ace->type == SMB_ACL_USER_OBJ)
owner_ace = ace;
else if (ace->type == SMB_ACL_OTHER) {
@@ -2331,16 +2331,16 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
*/
if (owner_ace) {
- DLIST_PROMOTE(list_head, owner_ace);
+ DLIST_PROMOTE(l_head, owner_ace);
}
if (other_ace) {
- DLIST_DEMOTE(list_head, other_ace, canon_ace *);
+ DLIST_DEMOTE(l_head, other_ace, canon_ace *);
}
/* We have probably changed the head of the list. */
- *pp_list_head = list_head;
+ *pp_list_head = l_head;
}
/****************************************************************************
@@ -2353,7 +2353,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
{
mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
- canon_ace *list_head = NULL;
+ canon_ace *l_head = NULL;
canon_ace *ace = NULL;
canon_ace *next_ace = NULL;
int entry_id = SMB_ACL_FIRST_ENTRY;
@@ -2457,14 +2457,14 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
ace->owner_type = owner_type;
ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
- DLIST_ADD(list_head, ace);
+ DLIST_ADD(l_head, ace);
}
/*
* This next call will ensure we have at least a user/group/world set.
*/
- if (!ensure_canon_entry_valid(&list_head, conn->params,
+ if (!ensure_canon_entry_valid(&l_head, conn->params,
S_ISDIR(psbuf->st_mode), powner, pgroup,
psbuf, False))
goto fail;
@@ -2476,7 +2476,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
- for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
+ for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
next_ace = ace->next;
/* Masks are only applied to entries other than USER_OBJ and OTHER. */
@@ -2484,7 +2484,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
ace->perms &= acl_mask;
if (ace->perms == 0) {
- DLIST_PROMOTE(list_head, ace);
+ DLIST_PROMOTE(l_head, ace);
}
if( DEBUGLVL( 10 ) ) {
@@ -2492,15 +2492,15 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
}
}
- arrange_posix_perms(fname,&list_head );
+ arrange_posix_perms(fname,&l_head );
- print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head );
+ print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head );
- return list_head;
+ return l_head;
fail:
- free_canon_ace_list(list_head);
+ free_canon_ace_list(l_head);
return NULL;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 457f9412a9..22e4c1aad7 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2214,6 +2214,16 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
}
if (S_ISDIR(pst->st_mode)) {
+ if (fsp->posix_open) {
+ return NT_STATUS_OK;
+ }
+
+ /* If no pathnames are open below this
+ directory, allow the rename. */
+
+ if (file_find_subpath(fsp)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
return NT_STATUS_OK;
}
@@ -2788,6 +2798,18 @@ static void send_file_readbraw(connection_struct *conn,
DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readbraw sendfile failed");
+ } else if (sendfile_read == 0) {
+ /*
+ * Some sendfile implementations return 0 to indicate
+ * that there was a short read, but nothing was
+ * actually written to the socket. In this case,
+ * fallback to the normal read path so the header gets
+ * the correct byte count.
+ */
+ DEBUG(3, ("send_file_readbraw: sendfile sent zero "
+ "bytes falling back to the normal read: "
+ "%s\n", fsp->fsp_name));
+ goto normal_readbraw;
}
/* Deal with possible short send. */
@@ -2796,9 +2818,9 @@ static void send_file_readbraw(connection_struct *conn,
}
return;
}
-#endif
normal_readbraw:
+#endif
outbuf = TALLOC_ARRAY(NULL, char, nread+4);
if (!outbuf) {
@@ -3284,6 +3306,18 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX sendfile failed");
+ } else if (nread == 0) {
+ /*
+ * Some sendfile implementations return 0 to indicate
+ * that there was a short read, but nothing was
+ * actually written to the socket. In this case,
+ * fallback to the normal read path so the header gets
+ * the correct byte count.
+ */
+ DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
+ "falling back to the normal read: %s\n",
+ fsp->fsp_name));
+ goto normal_read;
}
DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index e8ccba0873..538e04938e 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -212,7 +212,7 @@ 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));
+ DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", (unsigned int)pid));
messaging_send_buf(smbd_messaging_context(), procid_self(),
MSG_SMB_BRL_VALIDATE, NULL, 0);
message_send_all(smbd_messaging_context(),
@@ -359,10 +359,6 @@ static void smbd_accept_connection(struct tevent_context *ev,
/* Child code ... */
am_parent = 0;
-#ifdef WITH_MADVISE_PROTECTED
- madvise(NULL,0,MADV_PROTECT);
-#endif
-
/* Stop zombies, the parent explicitly handles
* them, counting worker smbds. */
CatchChild();
@@ -451,7 +447,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent,
if (s->fd == -1) {
DEBUG(0,("smbd_open_once_socket: open_socket_in: "
"%s\n", strerror(errno)));
- close(s->fd);
TALLOC_FREE(s);
/*
* We ignore an error here, as we've done before
@@ -735,7 +730,7 @@ void reload_printers(void)
DEBUG(3, ("removing stale printer %s\n", pname));
if (is_printer_published(NULL, snum, NULL))
- nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH);
+ nt_printer_publish(NULL, snum, DSPRINT_UNPUBLISH);
del_a_printer(pname);
lp_killservice(snum);
}
@@ -1135,9 +1130,6 @@ extern void build_options(bool screen);
if (is_daemon && !interactive) {
DEBUG( 3, ( "Becoming a daemon.\n" ) );
become_daemon(Fork, no_process_group);
-#ifdef WITH_MADVISE_PROTECTED
- madvise(NULL,0,MADV_PROTECT);
-#endif
}
#if HAVE_SETPGID
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 7a03ef7f3c..2c29192220 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -1352,8 +1352,8 @@ 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));
+ DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
+ "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
&data_blob_null);
@@ -1691,14 +1691,15 @@ void reply_sesssetup_and_X(struct smb_request *req)
}
} else {
struct auth_context *plaintext_auth_context = NULL;
- const uint8 *chal;
nt_status = make_auth_context_subsystem(
&plaintext_auth_context);
if (NT_STATUS_IS_OK(nt_status)) {
- chal = plaintext_auth_context->get_ntlm_challenge(
- plaintext_auth_context);
+ uint8_t chal[8];
+
+ plaintext_auth_context->get_ntlm_challenge(
+ plaintext_auth_context, chal);
if (!make_user_info_for_reply(&user_info,
user, domain, chal,
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 759e520866..ee1dda98b2 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -4972,6 +4972,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
+ files_struct *fsp,
const char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 dosmode)
@@ -4980,6 +4981,14 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if (fsp) {
+ if (fsp->base_fsp) {
+ fname = fsp->base_fsp->fsp_name;
+ } else {
+ fname = fsp->fsp_name;
+ }
+ }
+
if (dosmode) {
if (S_ISDIR(psbuf->st_mode)) {
dosmode |= aDIR;
@@ -5723,12 +5732,11 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
/* Set the attributes */
dosmode = IVAL(pdata,32);
- status = smb_set_file_dosmode(conn, fname, psbuf, dosmode);
+ status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-
/* access time */
ft.atime = interpret_long_date(pdata+8);
@@ -6415,6 +6423,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
create_disp = FILE_OVERWRITE_IF;
} else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
create_disp = FILE_OPEN_IF;
+ } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
+ create_disp = FILE_OPEN;
} else {
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
(unsigned int)wire_open_mode ));
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 9580247368..426772889c 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -766,18 +766,13 @@ int vfs_ChDir(connection_struct *conn, const char *path)
format. Note this can be called with conn == NULL.
********************************************************************/
-struct getwd_cache_key {
- SMB_DEV_T dev;
- SMB_INO_T ino;
-};
-
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
char s[PATH_MAX+1];
SMB_STRUCT_STAT st, st2;
char *result;
DATA_BLOB cache_value;
- struct getwd_cache_key key;
+ struct file_id key;
*s = 0;
@@ -797,9 +792,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto nocache;
}
- ZERO_STRUCT(key); /* unlikely, but possible padding */
- key.dev = st.st_dev;
- key.ino = st.st_ino;
+ key = vfs_file_id_from_sbuf(conn, &st);
if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
@@ -838,9 +831,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
}
if (lp_getwd_cache() && VALID_STAT(st)) {
- ZERO_STRUCT(key); /* unlikely, but possible padding */
- key.dev = st.st_dev;
- key.ino = st.st_ino;
+ key = vfs_file_id_from_sbuf(conn, &st);
memcache_add(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),