summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/reply.c8
-rw-r--r--source3/smbd/server.c72
-rw-r--r--source3/smbd/trans2.c2
3 files changed, 69 insertions, 13 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 7576ee323b..424c7d8183 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -789,7 +789,7 @@ int reply_setatr(char *inbuf,char *outbuf)
if (check_name(fname,cnum))
ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
if (ok)
- ok = set_filetime(fname,mtime);
+ ok = set_filetime(cnum,fname,mtime);
if (!ok)
{
@@ -2270,7 +2270,7 @@ int reply_close(char *inbuf,char *outbuf)
mtime = make_unix_date3(inbuf+smb_vwv1);
/* try and set the date */
- set_filetime(Files[fnum].name,mtime);
+ set_filetime(cnum, Files[fnum].name,mtime);
close_file(fnum,True);
@@ -2317,7 +2317,7 @@ int reply_writeclose(char *inbuf,char *outbuf)
nwritten = write_file(fnum,data,numtowrite);
- set_filetime(Files[fnum].name,mtime);
+ set_filetime(cnum, Files[fnum].name,mtime);
close_file(fnum,True);
@@ -3787,7 +3787,7 @@ not setting timestamps of 0\n",
}
/* Set the date on this file */
- if(sys_utime(Files[fnum].name, &unix_times))
+ if(file_utime(cnum, Files[fnum].name, &unix_times))
return(ERROR(ERRDOS,ERRnoaccess));
DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 7d9638f01e..7639c5940b 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -254,7 +254,6 @@ int dos_mode(int cnum,char *path,struct stat *sbuf)
return(result);
}
-
/*******************************************************************
chmod a file - but preserve some bits
********************************************************************/
@@ -308,6 +307,70 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
return(sys_chmod(fname,unixmode));
}
+/*******************************************************************
+Wrapper around sys_utime that possibly allows DOS semantics rather
+than POSIX.
+*******************************************************************/
+
+int file_utime(int cnum, char *fname, struct utimbuf *times)
+{
+ extern struct current_user current_user;
+ struct stat sb;
+ int ret = -1;
+
+ if(sys_utime(fname, times) == 0)
+ return 0;
+
+ if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum)))
+ return -1;
+
+ /* We have permission (given by the Samba admin) to
+ break POSIX semantics and allow a user to change
+ the time on a file they don't own but can write to
+ (as DOS does).
+ */
+
+ if(sys_stat(fname,&sb) != 0)
+ return -1;
+
+ /* Check if we have write access. */
+ if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum)))
+ {
+ if (((sb.st_mode & S_IWOTH) ||
+ Connections[cnum].admin_user ||
+ ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
+ ((sb.st_mode & S_IWGRP) &&
+ in_group(sb.st_gid,current_user.gid,
+ current_user.ngroups,current_user.igroups))))
+ {
+ /* We are allowed to become root and change the filetime. */
+ become_root(False);
+ ret = sys_utime(fname, times);
+ unbecome_root(False);
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+Change a filetime - possibly allowing DOS semantics.
+*******************************************************************/
+
+BOOL set_filetime(int cnum, char *fname, time_t mtime)
+{
+ struct utimbuf times;
+
+ if (null_mtime(mtime)) return(True);
+
+ times.modtime = times.actime = mtime;
+
+ if (file_utime(cnum, fname, &times)) {
+ DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
+ }
+
+ return(True);
+}
/****************************************************************************
check if two filenames are equal
@@ -1099,13 +1162,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
*/
-#if UTIME_WORKAROUND
- /* XXXX - is this OK?? */
- /* this works around a utime bug but can cause other problems */
- if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
- sys_unlink(fname);
-#endif
-
/*
* Ensure we have a valid struct stat so we can search the
* open fd table.
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index e484b3b2e1..6a7fc292fa 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1433,7 +1433,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
*/
if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
{
- if(sys_utime(fname, &tvs)!=0)
+ if(file_utime(cnum, fname, &tvs)!=0)
{
return(ERROR(ERRDOS,ERRnoaccess));
}