summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-01-25 05:35:21 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-01-25 05:35:21 +0100
commit5baac15781779a3ebfa3807299e5329809835370 (patch)
tree0ea19612d064f02a8bd9fc62df1bef63da276e67 /source3/smbd
parentc9d193eb08b036c5196d63c22790f3cd3583ba82 (diff)
parent8b804077128cd981bf238b2506c589dff3bf8ff4 (diff)
downloadsamba-5baac15781779a3ebfa3807299e5329809835370.tar.gz
samba-5baac15781779a3ebfa3807299e5329809835370.tar.bz2
samba-5baac15781779a3ebfa3807299e5329809835370.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c8
-rw-r--r--source3/smbd/dosmode.c13
-rw-r--r--source3/smbd/posix_acls.c290
-rw-r--r--source3/smbd/reply.c46
-rw-r--r--source3/smbd/trans2.c99
5 files changed, 250 insertions, 206 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index abcd651d93..2fb8ec2bb5 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -465,11 +465,11 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts)
static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
{
SMB_STRUCT_STAT sbuf;
- struct timespec ts[2];
+ struct smb_file_time ft;
NTSTATUS status;
ZERO_STRUCT(sbuf);
- ZERO_STRUCT(ts);
+ ZERO_STRUCT(ft);
if (!fsp->update_write_time_on_close) {
return NT_STATUS_OK;
@@ -495,9 +495,9 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
return NT_STATUS_OK;
}
- ts[1] = fsp->close_write_time;
+ ft.mtime = fsp->close_write_time;
status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
- &sbuf, ts, true);
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index ade5e66e86..555718bd83 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -704,7 +704,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
than POSIX.
*******************************************************************/
-int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
+int file_ntimes(connection_struct *conn, const char *fname,
+ struct smb_file_time *ft)
{
SMB_STRUCT_STAT sbuf;
int ret = -1;
@@ -713,9 +714,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
ZERO_STRUCT(sbuf);
DEBUG(6, ("file_ntime: actime: %s",
- time_to_asc(convert_timespec_to_time_t(ts[0]))));
+ time_to_asc(convert_timespec_to_time_t(ft->atime))));
DEBUG(6, ("file_ntime: modtime: %s",
- time_to_asc(convert_timespec_to_time_t(ts[1]))));
+ time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+ DEBUG(6, ("file_ntime: createtime: %s",
+ time_to_asc(convert_timespec_to_time_t(ft->create_time))));
/* Don't update the time on read-only shares */
/* We need this as set_filetime (which can be called on
@@ -728,7 +731,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
return 0;
}
- if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
+ if(SMB_VFS_NTIMES(conn, fname, ft) == 0) {
return 0;
}
@@ -750,7 +753,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
if (can_write_to_file(conn, fname, &sbuf)) {
/* We are allowed to become root and change the filetime. */
become_root();
- ret = SMB_VFS_NTIMES(conn, fname, ts);
+ ret = SMB_VFS_NTIMES(conn, fname, ft);
unbecome_root();
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 951046c562..72f5c94bc5 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3187,6 +3187,15 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
return -1;
}
+ /* only allow chown to the current user. This is more secure,
+ and also copes with the case where the SID in a take ownership ACL is
+ a local SID on the users workstation
+ */
+ if (uid != current_user.ut.uid) {
+ errno = EPERM;
+ return -1;
+ }
+
if (SMB_VFS_STAT(conn,fname,&st)) {
return -1;
}
@@ -3195,12 +3204,6 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
return -1;
}
- /* only allow chown to the current user. This is more secure,
- and also copes with the case where the SID in a take ownership ACL is
- a local SID on the users workstation
- */
- uid = current_user.ut.uid;
-
become_root();
/* Keep the current file gid the same. */
ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
@@ -3426,8 +3429,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
bool acl_perms = False;
mode_t orig_mode = (mode_t)0;
NTSTATUS status;
- uid_t orig_uid;
- gid_t orig_gid;
+ bool set_acl_as_root = false;
+ bool acl_set_support = false;
+ bool ret = false;
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
@@ -3448,10 +3452,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
return map_nt_error_from_unix(errno);
}
- /* Save the original elements we check against. */
+ /* Save the original element we check against. */
orig_mode = sbuf.st_mode;
- orig_uid = sbuf.st_uid;
- orig_gid = sbuf.st_gid;
/*
* Unpack the user/group/world id's.
@@ -3468,7 +3470,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
* Noticed by Simo.
*/
- if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) {
+ if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
@@ -3493,174 +3495,188 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
}
} else {
- int ret;
+ int sret;
if(fsp->fh->fd == -1)
- ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
+ sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
else
- ret = SMB_VFS_FSTAT(fsp, &sbuf);
+ sret = SMB_VFS_FSTAT(fsp, &sbuf);
- if(ret != 0)
+ if(sret != 0)
return map_nt_error_from_unix(errno);
}
- /* Save the original elements we check against. */
+ /* Save the original element we check against. */
orig_mode = sbuf.st_mode;
- orig_uid = sbuf.st_uid;
- orig_gid = sbuf.st_gid;
+
+ /* If we successfully chowned, we know we must
+ * be able to set the acl, so do it as root.
+ */
+ set_acl_as_root = true;
}
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
-#if 0
- /* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
-
- /* See here: http://www.codeproject.com/KB/winsdk/accessctrl2.aspx
- * for details and also the log trace in bug #4308. JRA.
- */
-
- if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
- psd->dacl != NULL &&
- (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
- SE_DESC_DACL_AUTO_INHERIT_REQ))==
- (SE_DESC_DACL_AUTO_INHERITED|
- SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
- SEC_DESC *new_sd = NULL;
- status = append_parent_acl(fsp, psd, &new_sd);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- psd = new_sd;
- }
-#endif
-
acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
&file_ace_list, &dir_ace_list, security_info_sent, psd);
/* Ignore W2K traverse DACL set. */
- if (file_ace_list || dir_ace_list) {
+ if (!file_ace_list && !dir_ace_list) {
+ return NT_STATUS_OK;
+ }
- if (!acl_perms) {
- DEBUG(3,("set_nt_acl: cannot set permissions\n"));
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
- return NT_STATUS_ACCESS_DENIED;
- }
+ if (!acl_perms) {
+ DEBUG(3,("set_nt_acl: cannot set permissions\n"));
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ return NT_STATUS_ACCESS_DENIED;
+ }
- /*
- * Only change security if we got a DACL.
- */
+ /*
+ * Only change security if we got a DACL.
+ */
- if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) {
+ if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * Try using the POSIX ACL set first. Fall back to chmod if
+ * we have no ACL support on this filesystem.
+ */
- bool acl_set_support = False;
- bool ret = False;
+ if (acl_perms && file_ace_list) {
+ if (set_acl_as_root) {
+ become_root();
+ }
+ ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support);
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ if (acl_set_support && ret == false) {
+ DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ return map_nt_error_from_unix(errno);
+ }
+ }
+
+ if (acl_perms && acl_set_support && fsp->is_directory) {
+ if (dir_ace_list) {
+ if (set_acl_as_root) {
+ become_root();
+ }
+ ret = set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support);
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ if (ret == false) {
+ DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ int sret = -1;
/*
- * Try using the POSIX ACL set first. Fall back to chmod if
- * we have no ACL support on this filesystem.
+ * No default ACL - delete one if it exists.
*/
- if (acl_perms && file_ace_list) {
- ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support);
- if (acl_set_support && ret == False) {
- DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
+ if (set_acl_as_root) {
+ become_root();
+ }
+ sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ if (sret == -1) {
+ if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
+ DEBUG(5,("set_nt_acl: acl group control on and "
+ "current user in file %s primary group. Override delete_def_acl\n",
+ fsp->fsp_name ));
+
+ become_root();
+ sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
+ unbecome_root();
+ }
+
+ if (sret == -1) {
+ DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
+ free_canon_ace_list(dir_ace_list);
return map_nt_error_from_unix(errno);
}
}
+ }
+ }
- if (acl_perms && acl_set_support && fsp->is_directory) {
- if (dir_ace_list) {
- if (!set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support)) {
- DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
- }
- } else {
+ if (acl_set_support) {
+ if (set_acl_as_root) {
+ become_root();
+ }
+ store_inheritance_attributes(fsp, file_ace_list, dir_ace_list,
+ (psd->type & SE_DESC_DACL_PROTECTED) ? True : False);
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ }
- /*
- * No default ACL - delete one if it exists.
- */
+ /*
+ * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod.
+ */
- if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) {
- int sret = -1;
-
- if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group control on and "
- "current user in file %s primary group. Override delete_def_acl\n",
- fsp->fsp_name ));
-
- become_root();
- sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
- unbecome_root();
- }
-
- if (sret == -1) {
- DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
- }
- }
- }
- }
+ if(!acl_set_support && acl_perms) {
+ mode_t posix_perms;
- if (acl_set_support) {
- store_inheritance_attributes(fsp, file_ace_list, dir_ace_list,
- (psd->type & SE_DESC_DACL_PROTECTED) ? True : False);
- }
+ if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
- /*
- * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod.
- */
+ if (orig_mode != posix_perms) {
+ int sret = -1;
- if(!acl_set_support && acl_perms) {
- mode_t posix_perms;
+ DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
+ fsp->fsp_name, (unsigned int)posix_perms ));
- if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
- DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
+ if (set_acl_as_root) {
+ become_root();
+ }
+ sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ if(sret == -1) {
+ if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
+ DEBUG(5,("set_nt_acl: acl group control on and "
+ "current user in file %s primary group. Override chmod\n",
fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
+
+ become_root();
+ sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
+ unbecome_root();
}
- if (orig_mode != posix_perms) {
-
- DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
- fsp->fsp_name, (unsigned int)posix_perms ));
-
- if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) {
- int sret = -1;
- if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group control on and "
- "current user in file %s primary group. Override chmod\n",
- fsp->fsp_name ));
-
- become_root();
- sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
- unbecome_root();
- }
-
- if (sret == -1) {
- DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
- fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
- }
- }
+ if (sret == -1) {
+ DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+ return map_nt_error_from_unix(errno);
}
}
}
-
- free_canon_ace_list(file_ace_list);
- free_canon_ace_list(dir_ace_list);
}
+ free_canon_ace_list(file_ace_list);
+ free_canon_ace_list(dir_ace_list);
+
return NT_STATUS_OK;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 28836144c2..52dab0a013 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1063,7 +1063,7 @@ void reply_getatr(struct smb_request *req)
void reply_setatr(struct smb_request *req)
{
- struct timespec ts[2];
+ struct smb_file_time ft;
connection_struct *conn = req->conn;
char *fname = NULL;
int mode;
@@ -1075,7 +1075,7 @@ void reply_setatr(struct smb_request *req)
START_PROFILE(SMBsetatr);
- ZERO_STRUCT(ts);
+ ZERO_STRUCT(ft);
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -1133,9 +1133,9 @@ void reply_setatr(struct smb_request *req)
mode = SVAL(req->vwv+0, 0);
mtime = srv_make_unix_date3(req->vwv+1);
- ts[1] = convert_time_t_to_timespec(mtime);
+ ft.mtime = convert_time_t_to_timespec(mtime);
status = smb_set_file_time(conn, NULL, fname,
- &sbuf, ts, true);
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsetatr);
@@ -1924,7 +1924,7 @@ void reply_mknew(struct smb_request *req)
connection_struct *conn = req->conn;
char *fname = NULL;
uint32 fattr = 0;
- struct timespec ts[2];
+ struct smb_file_time ft;
files_struct *fsp;
int oplock_request = 0;
SMB_STRUCT_STAT sbuf;
@@ -1936,6 +1936,7 @@ void reply_mknew(struct smb_request *req)
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBcreate);
+ ZERO_STRUCT(ft);
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -1946,8 +1947,8 @@ void reply_mknew(struct smb_request *req)
fattr = SVAL(req->vwv+0, 0);
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
- /* mtime. */
+ /* mtime. */
+ ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
STR_TERMINATE, &status);
@@ -1999,8 +2000,8 @@ void reply_mknew(struct smb_request *req)
return;
}
- ts[0] = get_atimespec(&sbuf); /* atime. */
- status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
+ ft.atime = get_atimespec(&sbuf); /* atime. */
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
reply_openerror(req, status);
@@ -7115,12 +7116,13 @@ void reply_readbs(struct smb_request *req)
void reply_setattrE(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct timespec ts[2];
+ struct smb_file_time ft;
files_struct *fsp;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBsetattrE);
+ ZERO_STRUCT(ft);
if (req->wct < 7) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -7138,14 +7140,15 @@ void reply_setattrE(struct smb_request *req)
/*
- * Convert the DOS times into unix times. Ignore create
- * time as UNIX can't set this.
+ * Convert the DOS times into unix times.
*/
- ts[0] = convert_time_t_to_timespec(
- srv_make_unix_date2(req->vwv+3)); /* atime. */
- ts[1] = convert_time_t_to_timespec(
- srv_make_unix_date2(req->vwv+5)); /* mtime. */
+ ft.atime = convert_time_t_to_timespec(
+ srv_make_unix_date2(req->vwv+3));
+ ft.mtime = convert_time_t_to_timespec(
+ srv_make_unix_date2(req->vwv+5));
+ ft.create_time = convert_time_t_to_timespec(
+ srv_make_unix_date2(req->vwv+1));
reply_outbuf(req, 0, 0);
@@ -7172,17 +7175,20 @@ void reply_setattrE(struct smb_request *req)
}
status = smb_set_file_time(conn, fsp, fsp->fsp_name,
- &sbuf, ts, true);
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsetattrE);
return;
}
- DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
+ DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
+ " createtime=%u\n",
fsp->fnum,
- (unsigned int)ts[0].tv_sec,
- (unsigned int)ts[1].tv_sec));
+ (unsigned int)ft.atime.tv_sec,
+ (unsigned int)ft.mtime.tv_sec,
+ (unsigned int)ft.create_time.tv_sec
+ ));
END_PROFILE(SMBsetattrE);
return;
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 52340d5370..1b161d5338 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1430,7 +1430,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
mdate_ts = get_mtimespec(&sbuf);
adate_ts = get_atimespec(&sbuf);
- create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ create_date_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
if (ask_sharemode) {
struct timespec write_time_ts;
@@ -1453,7 +1454,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
mdate = convert_timespec_to_time_t(mdate_ts);
adate = convert_timespec_to_time_t(adate_ts);
- DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
+ DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
+ pathreal,fname));
found = True;
@@ -4892,7 +4894,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
files_struct *fsp,
const char *fname,
const SMB_STRUCT_STAT *psbuf,
- struct timespec ts[2],
+ struct smb_file_time *ft,
bool setting_write_time)
{
uint32 action =
@@ -4904,23 +4906,29 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_timespec(ts[0])) {
- ts[0] = get_atimespec(psbuf);
+ if (null_timespec(ft->atime)) {
+ ft->atime= get_atimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_timespec(ts[1])) {
- ts[1] = get_mtimespec(psbuf);
+ if (null_timespec(ft->mtime)) {
+ ft->mtime = get_mtimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
if (!setting_write_time) {
- /* ts[1] comes from change time, not write time. */
+ /* ft->mtime comes from change time, not write time. */
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
- DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ DEBUG(5,("smb_set_filetime: actime: %s\n ",
+ time_to_asc(convert_timespec_to_time_t(ft->atime))));
+ DEBUG(5,("smb_set_filetime: modtime: %s\n ",
+ time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+ if (!null_timespec(ft->create_time)) {
+ DEBUG(5,("smb_set_file_time: createtime: %s\n ",
+ time_to_asc(convert_timespec_to_time_t(ft->create_time))));
+ }
/*
* Try and set the times of this file if
@@ -4930,7 +4938,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
{
struct timespec mts = get_mtimespec(psbuf);
struct timespec ats = get_atimespec(psbuf);
- if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+ if ((timespec_compare(&ft->atime, &ats) == 0) &&
+ (timespec_compare(&ft->mtime, &mts) == 0)) {
return NT_STATUS_OK;
}
}
@@ -4947,18 +4956,19 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
*/
DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
- time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ time_to_asc(convert_timespec_to_time_t(ft->mtime))));
if (fsp != NULL) {
if (fsp->base_fsp) {
- set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
+ set_sticky_write_time_fsp(fsp->base_fsp,
+ ft->mtime);
} else {
- set_sticky_write_time_fsp(fsp, ts[1]);
+ set_sticky_write_time_fsp(fsp, ft->mtime);
}
} else {
set_sticky_write_time_path(conn, fname,
vfs_file_id_from_sbuf(conn, psbuf),
- ts[1]);
+ ft->mtime);
}
}
@@ -4968,7 +4978,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
fname = fsp->base_fsp->fsp_name;
}
- if(file_ntimes(conn, fname, ts)!=0) {
+ if(file_ntimes(conn, fname, ft)!=0) {
return map_nt_error_from_unix(errno);
}
notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
@@ -5677,16 +5687,21 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
const char *fname,
const SMB_STRUCT_STAT *psbuf)
{
- struct timespec ts[2];
+ struct smb_file_time ft;
+ ZERO_STRUCT(ft);
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
+
/* access time */
- ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
+ ft.atime = interpret_long_date(pdata + 8);
+
/* write time */
- ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+ ft.mtime = interpret_long_date(pdata + 16);
DEBUG(10,("smb_set_info_standard: file %s\n",
fname ? fname : fsp->fsp_name ));
@@ -5695,7 +5710,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
fsp,
fname,
psbuf,
- ts,
+ &ft,
true);
}
@@ -5713,47 +5728,49 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
struct timespec write_time;
struct timespec changed_time;
+ struct smb_file_time ft;
uint32 dosmode = 0;
- struct timespec ts[2];
NTSTATUS status = NT_STATUS_OK;
bool setting_write_time = true;
+ ZERO_STRUCT(ft);
+
if (total_data < 36) {
return NT_STATUS_INVALID_PARAMETER;
}
/* Set the attributes */
dosmode = IVAL(pdata,32);
- status = smb_set_file_dosmode(conn,
- fname,
- psbuf,
- dosmode);
+ status = smb_set_file_dosmode(conn, fname, psbuf, dosmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- /* Ignore create time at offset pdata. */
/* access time */
- ts[0] = interpret_long_date(pdata+8);
+ ft.atime = interpret_long_date(pdata+8);
write_time = interpret_long_date(pdata+16);
changed_time = interpret_long_date(pdata+24);
/* mtime */
- ts[1] = timespec_min(&write_time, &changed_time);
+ ft.mtime = timespec_min(&write_time, &changed_time);
- if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
- ts[1] = write_time;
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
+
+ if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
+ !null_timespec(write_time)) {
+ ft.mtime = write_time;
}
/* Prefer a defined time to an undefined one. */
- if (null_timespec(ts[1])) {
+ if (null_timespec(ft.mtime)) {
if (null_timespec(write_time)) {
- ts[1] = changed_time;
+ ft.mtime = changed_time;
setting_write_time = false;
} else {
- ts[1] = write_time;
+ ft.mtime = write_time;
}
}
@@ -5764,7 +5781,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
fsp,
fname,
psbuf,
- ts,
+ &ft,
setting_write_time);
}
@@ -6012,7 +6029,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct timespec ts[2];
+ struct smb_file_time ft;
uint32 raw_unixmode;
mode_t unixmode;
SMB_OFF_T size = 0;
@@ -6022,6 +6039,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
bool delete_on_fail = False;
enum perm_type ptype;
+ ZERO_STRUCT(ft);
+
if (total_data < 100) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -6039,8 +6058,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
#endif /* LARGE_SMB_OFF_T */
}
- ts[0] = interpret_long_date(pdata+24); /* access_time */
- ts[1] = interpret_long_date(pdata+32); /* modification_time */
+ ft.atime = interpret_long_date(pdata+24); /* access_time */
+ ft.mtime = interpret_long_date(pdata+32); /* modification_time */
set_owner = (uid_t)IVAL(pdata,40);
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
@@ -6083,8 +6102,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
/* Ensure we don't try and change anything else. */
raw_unixmode = SMB_MODE_NO_CHANGE;
size = get_file_size(*psbuf);
- ts[0] = get_atimespec(psbuf);
- ts[1] = get_mtimespec(psbuf);
+ ft.atime = get_atimespec(psbuf);
+ ft.mtime = get_mtimespec(psbuf);
/*
* We continue here as we might want to change the
* owner uid/gid.
@@ -6172,7 +6191,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
fsp,
fname,
psbuf,
- ts,
+ &ft,
true);
}