diff options
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/libsmb/smb_share_modes.c | 1 | ||||
-rw-r--r-- | source3/locking/locking.c | 39 | ||||
-rw-r--r-- | source3/smbd/close.c | 39 | ||||
-rw-r--r-- | source3/smbd/open.c | 12 |
5 files changed, 59 insertions, 35 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index cf754b5c1f..df4f47f12c 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -506,6 +506,7 @@ typedef struct files_struct { BOOL is_stat; BOOL aio_write_behind; BOOL lockdb_clean; + BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ char *fsp_name; struct vfs_fsp_data *vfs_extension; @@ -773,7 +774,6 @@ struct share_mode_lock { struct share_mode_entry *share_modes; UNIX_USER_TOKEN *delete_token; BOOL delete_on_close; - BOOL initial_delete_on_close; BOOL fresh; BOOL modified; }; @@ -788,7 +788,6 @@ struct locking_data { struct { int num_share_mode_entries; BOOL delete_on_close; - BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ uint32 delete_token_size; /* Only valid if either of the two previous fields are True. */ diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index b62240ce50..b8c7a7e66b 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -274,7 +274,6 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, memset(ld, '\0', sizeof(struct locking_data)); ld->u.s.num_share_mode_entries = 1; ld->u.s.delete_on_close = 0; - ld->u.s.initial_delete_on_close = 0; ld->u.s.delete_token_size = 0; shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); create_share_mode_entry(shares, new_entry); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 111fc98bbe..56d18a63ef 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -473,14 +473,11 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) data = (struct locking_data *)dbuf.dptr; lck->delete_on_close = data->u.s.delete_on_close; - lck->initial_delete_on_close = data->u.s.initial_delete_on_close; lck->num_share_modes = data->u.s.num_share_mode_entries; DEBUG(10, ("parse_share_modes: delete_on_close: %d, " - "initial_delete_on_close: %d, " "num_share_modes: %d\n", lck->delete_on_close, - lck->initial_delete_on_close, lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { @@ -635,11 +632,9 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; - data->u.s.initial_delete_on_close = lck->initial_delete_on_close; data->u.s.delete_token_size = delete_token_size; - DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n", + DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n", data->u.s.delete_on_close, - data->u.s.initial_delete_on_close, (unsigned int)data->u.s.delete_token_size, data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, @@ -734,7 +729,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, lck->share_modes = NULL; lck->delete_token = NULL; lck->delete_on_close = False; - lck->initial_delete_on_close = False; lck->fresh = False; lck->modified = False; @@ -1251,11 +1245,22 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok changed the delete on close flag. This will be noticed in the close code, the last closer will delete the file if flag is set. - Note that setting this to any value clears the initial_delete_on_close flag. - If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the - lck entry. + This makes a copy of any UNIX_USER_TOKEN into the + lck entry. This function is used when the lock is already granted. ****************************************************************************/ +void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, UNIX_USER_TOKEN *tok) +{ + if (lck->delete_on_close != delete_on_close) { + set_delete_on_close_token(lck, tok); + lck->delete_on_close = delete_on_close; + if (delete_on_close) { + SMB_ASSERT(lck->delete_token != NULL); + } + lck->modified = True; + } +} + BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok) { struct share_mode_lock *lck; @@ -1274,19 +1279,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return False; } - if (lck->delete_on_close != delete_on_close) { - set_delete_on_close_token(lck, tok); - lck->delete_on_close = delete_on_close; - if (delete_on_close) { - SMB_ASSERT(lck->delete_token != NULL); - } - lck->modified = True; - } - - if (lck->initial_delete_on_close) { - lck->initial_delete_on_close = False; - lck->modified = True; - } + set_delete_on_close_lck(lck, delete_on_close, tok); TALLOC_FREE(lck); return True; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index fe5e5eccf2..8958878433 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -22,6 +22,8 @@ #include "includes.h" +extern struct current_user current_user; + /**************************************************************************** Run a file if it is a magic script. ****************************************************************************/ @@ -172,7 +174,23 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, "entry for file %s\n", fsp->fsp_name)); } - delete_file = (lck->delete_on_close | lck->initial_delete_on_close); + if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) { + BOOL became_user = False; + + /* Initial delete on close was set and no one else + * wrote a real delete on close. */ + + if (current_user.vuid != fsp->vuid) { + become_user(conn, fsp->vuid); + became_user = True; + } + set_delete_on_close_lck(lck, True, ¤t_user.ut); + if (became_user) { + unbecome_user(); + } + } + + delete_file = lck->delete_on_close; if (delete_file) { int i; @@ -402,7 +420,24 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type) DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); } - delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); + if (fsp->initial_delete_on_close) { + BOOL became_user = False; + + /* Initial delete on close was set - for + * directories we don't care if anyone else + * wrote a real delete on close. */ + + if (current_user.vuid != fsp->vuid) { + become_user(fsp->conn, fsp->vuid); + became_user = True; + } + set_delete_on_close_lck(lck, True, ¤t_user.ut); + if (became_user) { + unbecome_user(); + } + } + + delete_dir = lck->delete_on_close; if (delete_dir) { int i; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index c0638c0039..a5a8eacda0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1761,10 +1761,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } /* Note that here we set the *inital* delete on close flag, - not the regular one. */ - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } /* Files should be initially set as archive */ @@ -2117,9 +2115,9 @@ NTSTATUS open_directory(connection_struct *conn, } if (NT_STATUS_IS_OK(status)) { - set_delete_on_close_token(lck, ¤t_user.ut); - lck->initial_delete_on_close = True; - lck->modified = True; + /* Note that here we set the *inital* delete on close flag, + not the regular one. The magic gets handled in close. */ + fsp->initial_delete_on_close = True; } } |