summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-04-14 00:19:12 +0000
committerJeremy Allison <jra@samba.org>2001-04-14 00:19:12 +0000
commit53850c51caf1c4d53ff285b2e5505e0615beeeee (patch)
tree03e7d594efd340da6909e0efa2cf3dd05b6a610b
parent9444e9d9f350961b594a1acbe7a7652d97faec0a (diff)
downloadsamba-53850c51caf1c4d53ff285b2e5505e0615beeeee.tar.gz
samba-53850c51caf1c4d53ff285b2e5505e0615beeeee.tar.bz2
samba-53850c51caf1c4d53ff285b2e5505e0615beeeee.zip
configure:
configure.in: include/config.h.in: include/profile.h: smbd/vfs-wrap.c: smbd/vfs.c: Added fchmod and fchown to VFS (sorry Gerald - but we needed them anyway). smbd/dosmode.c: smbd/files.c: printing/printfsp.c: smbd/close.c: smbd/open.c: Fixed "dos filemode" correctly so there are no race conditions. Forces test of open of file O_WRONLY before allowing fchmod as root. Afterwards, calls standard close function that preserves POSIX locks due to POSIX-me-harder braindamage. :-). Andrew please review this code. Also - in removing the tmpdir param in smbrun an extra NULL parameter was missed in each print_run_command() call (which is a varargs fn.). Now fixed. Jeremy. (This used to be commit 32397e5bc6d995ce7ca37c82d6aedc1e5b1b6fbd)
-rwxr-xr-xsource3/configure2
-rw-r--r--source3/configure.in2
-rw-r--r--source3/include/config.h.in6
-rw-r--r--source3/include/profile.h6
-rw-r--r--source3/include/proto.h6
-rw-r--r--source3/include/vfs.h2
-rw-r--r--source3/printing/print_generic.c22
-rw-r--r--source3/printing/printfsp.c2
-rw-r--r--source3/smbd/close.c2
-rw-r--r--source3/smbd/dosmode.c26
-rw-r--r--source3/smbd/files.c5
-rw-r--r--source3/smbd/open.c54
-rw-r--r--source3/smbd/vfs-wrap.c41
-rw-r--r--source3/smbd/vfs.c10
14 files changed, 144 insertions, 42 deletions
diff --git a/source3/configure b/source3/configure
index 1288634fe6..7cf0e29407 100755
--- a/source3/configure
+++ b/source3/configure
@@ -5100,7 +5100,7 @@ else
RUNPROG=""
fi
-for ac_func in waitpid getcwd strdup strtoul strerror chown chmod chroot
+for ac_func in waitpid getcwd strdup strtoul strerror chown fchown chmod fchmod chroot
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5107: checking for $ac_func" >&5
diff --git a/source3/configure.in b/source3/configure.in
index a201823295..c8270d2d5c 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -471,7 +471,7 @@ else
RUNPROG=""
fi
-AC_CHECK_FUNCS(waitpid getcwd strdup strtoul strerror chown chmod chroot)
+AC_CHECK_FUNCS(waitpid getcwd strdup strtoul strerror chown fchown chmod fchmod chroot)
AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync bzero memset)
AC_CHECK_FUNCS(memmove vsnprintf snprintf setsid glob strpbrk pipe crypt16 getauthuid)
AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction innetgr setnetgrent getnetgrent endnetgrent)
diff --git a/source3/include/config.h.in b/source3/include/config.h.in
index a60d927976..b13f465691 100644
--- a/source3/include/config.h.in
+++ b/source3/include/config.h.in
@@ -466,6 +466,12 @@
/* Define if you have the execl function. */
#undef HAVE_EXECL
+/* Define if you have the fchmod function. */
+#undef HAVE_FCHMOD
+
+/* Define if you have the fchown function. */
+#undef HAVE_FCHOWN
+
/* Define if you have the fcvt function. */
#undef HAVE_FCVT
diff --git a/source3/include/profile.h b/source3/include/profile.h
index b05e1fd9bb..5916614fb7 100644
--- a/source3/include/profile.h
+++ b/source3/include/profile.h
@@ -35,7 +35,7 @@ enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH,
#define PROF_SHMEM_KEY ((key_t)0x07021999)
#define PROF_SHM_MAGIC 0x6349985
-#define PROF_SHM_VERSION 3
+#define PROF_SHM_VERSION 4
/* time values in the following structure are in microseconds */
@@ -80,8 +80,12 @@ struct profile_stats {
unsigned syscall_unlink_time;
unsigned syscall_chmod_count;
unsigned syscall_chmod_time;
+ unsigned syscall_fchmod_count;
+ unsigned syscall_fchmod_time;
unsigned syscall_chown_count;
unsigned syscall_chown_time;
+ unsigned syscall_fchown_count;
+ unsigned syscall_fchown_time;
unsigned syscall_chdir_count;
unsigned syscall_chdir_time;
unsigned syscall_getwd_count;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 890c2dcf60..5d7398b23f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3951,7 +3951,7 @@ BOOL check_name(char *name,connection_struct *conn);
/*The following definitions come from smbd/files.c */
-files_struct *file_new(void );
+files_struct *file_new(connection_struct *conn);
void file_close_conn(connection_struct *conn);
void file_init(void);
void file_close_user(int vuid);
@@ -4048,6 +4048,8 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action);
files_struct *open_file_stat(connection_struct *conn, char *fname,
SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action);
+files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf);
+int close_file_fchmod(files_struct *fsp);
files_struct *open_directory(connection_struct *conn, char *fname,
SMB_STRUCT_STAT *psbuf, int smb_ofun, mode_t unixmode, int *action);
BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op);
@@ -4311,7 +4313,9 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf);
int vfswrap_lstat(connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf);
int vfswrap_unlink(connection_struct *conn, char *path);
int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode);
+int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode);
int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid);
+int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid);
int vfswrap_chdir(connection_struct *conn, char *path);
char *vfswrap_getwd(connection_struct *conn, char *path);
int vfswrap_utime(connection_struct *conn, char *path, struct utimbuf *times);
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 9ca4bde0c5..51f3df1ec9 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -78,7 +78,9 @@ struct vfs_ops {
int (*lstat)(struct connection_struct *conn, char *path, SMB_STRUCT_STAT *sbuf);
int (*unlink)(struct connection_struct *conn, char *path);
int (*chmod)(struct connection_struct *conn, char *path, mode_t mode);
+ int (*fchmod)(struct files_struct *fsp, int fd, mode_t mode);
int (*chown)(struct connection_struct *conn, char *path, uid_t uid, gid_t gid);
+ int (*fchown)(struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
int (*chdir)(struct connection_struct *conn, char *path);
char *(*getwd)(struct connection_struct *conn, char *buf);
int (*utime)(struct connection_struct *conn, char *path, struct utimbuf *times);
diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c
index eff394593c..ef38d26493 100644
--- a/source3/printing/print_generic.c
+++ b/source3/printing/print_generic.c
@@ -104,7 +104,7 @@ static int generic_job_delete(int snum, struct printjob *pjob)
slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
return print_run_command(
snum,
- lp_lprmcommand(snum), NULL, NULL,
+ lp_lprmcommand(snum), NULL,
"%j", jobstr,
"%T", http_timestring(pjob->starttime),
NULL);
@@ -120,7 +120,7 @@ static int generic_job_pause(int snum, struct printjob *pjob)
/* need to pause the spooled entry */
slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
return print_run_command(snum,
- lp_lppausecommand(snum), NULL, NULL,
+ lp_lppausecommand(snum), NULL,
"%j", jobstr,
NULL);
}
@@ -135,7 +135,7 @@ static int generic_job_resume(int snum, struct printjob *pjob)
/* need to pause the spooled entry */
slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
return print_run_command(snum,
- lp_lpresumecommand(snum), NULL, NULL,
+ lp_lpresumecommand(snum), NULL,
"%j", jobstr,
NULL);
}
@@ -172,7 +172,7 @@ static int generic_job_submit(int snum, struct printjob *pjob)
/* send it to the system spooler */
ret = print_run_command(snum,
- lp_printcommand(snum), NULL, NULL,
+ lp_printcommand(snum), NULL,
"%s", p,
"%J", jobname,
"%f", p,
@@ -189,11 +189,8 @@ get the current list of queued jobs
****************************************************************************/
static int generic_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
{
- char *path = lp_pathname(snum);
- char *cmd = lp_lpqcommand(snum);
char **qlines;
int fd;
- pstring tmp_file;
int numlines, i, qcount;
print_queue_struct *queue = NULL;
fstring printer_name;
@@ -202,10 +199,7 @@ static int generic_queue_get(int snum, print_queue_struct **q, print_status_stru
fstrcpy(printer_name, lp_servicename(snum));
dos_to_unix(printer_name, True);
- slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smblpq.%d", path, sys_getpid());
-
- unlink(tmp_file);
- print_run_command(snum, cmd, &fd, tmp_file, NULL);
+ print_run_command(snum, lp_lpqcommand(snum), &fd, NULL);
if (fd == -1) {
DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
@@ -243,8 +237,7 @@ static int generic_queue_get(int snum, print_queue_struct **q, print_status_stru
****************************************************************************/
static int generic_queue_pause(int snum)
{
- return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL,
- NULL);
+ return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL);
}
/****************************************************************************
@@ -252,6 +245,5 @@ static int generic_queue_pause(int snum)
****************************************************************************/
static int generic_queue_resume(int snum)
{
- return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL,
- NULL);
+ return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL);
}
diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c
index efb97be919..6a8e4bea45 100644
--- a/source3/printing/printfsp.c
+++ b/source3/printing/printfsp.c
@@ -34,7 +34,7 @@ files_struct *print_fsp_open(connection_struct *conn,char *jobname)
int jobid;
SMB_STRUCT_STAT sbuf;
extern struct current_user current_user;
- files_struct *fsp = file_new();
+ files_struct *fsp = file_new(conn);
if(!fsp)
return NULL;
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 45df9b2e0d..217c81228f 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -111,7 +111,7 @@ static int close_filestruct(files_struct *fsp)
}
/****************************************************************************
- Close a file - possibly invalidating the read prediction.
+ Close a file.
If normal_close is 1 then this came from a normal SMBclose (or equivalent)
operation otherwise it came as the result of some other operation such as
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 8b2c482b0a..9ec1fa2606 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -184,7 +184,6 @@ chmod a file - but preserve some bits
********************************************************************/
int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st)
{
- extern struct current_user current_user;
SMB_STRUCT_STAT st1;
int mask=0;
mode_t tmp;
@@ -250,16 +249,21 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *
/* Check if we have write access. */
if (CAN_WRITE(conn)) {
- if (((st->st_mode & S_IWOTH) ||
- conn->admin_user ||
- ((st->st_mode & S_IWUSR) && current_user.uid==st->st_uid) ||
- ((st->st_mode & S_IWGRP) &&
- in_group(st->st_gid,current_user.gid, current_user.ngroups,current_user.groups)))) {
- /* We are allowed to become root and change the file mode. */
- become_root();
- ret = vfs_chmod(conn,fname,unixmode);
- unbecome_root();
- }
+ /*
+ * We need to open the file with write access whilst
+ * still in our current user context. This ensures we
+ * are not violating security in doing the fchmod.
+ * This file open does *not* break any oplocks we are
+ * holding. We need to review this.... may need to
+ * break batch oplocks open by others. JRA.
+ */
+ files_struct *fsp = open_file_fchmod(conn,fname,st);
+ if (!fsp)
+ return -1;
+ become_root();
+ ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode);
+ unbecome_root();
+ close_file_fchmod(fsp);
}
return( ret );
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 33243e1e94..27dfad7c48 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -43,7 +43,7 @@ static int files_used;
/****************************************************************************
find first available file slot
****************************************************************************/
-files_struct *file_new(void )
+files_struct *file_new(connection_struct *conn)
{
int i;
static int first_file;
@@ -72,7 +72,7 @@ files_struct *file_new(void )
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (attempt_close_oplocked_file(fsp)) {
- return file_new();
+ return file_new(conn);
}
}
@@ -91,6 +91,7 @@ files_struct *file_new(void )
ZERO_STRUCTP(fsp);
fsp->fd = -1;
+ fsp->conn = conn;
first_file = (i+1) % real_max_open_files;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 007a169f9e..f450e74e58 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -583,13 +583,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
return print_fsp_open(conn, fname);
}
- fsp = file_new();
+ fsp = file_new(conn);
if(!fsp)
return NULL;
- fsp->fd = -1;
- fsp->conn = conn; /* The vfs_fXXX() macros need this. */
-
DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
fname, share_mode, ofun, (int)mode, oplock_request ));
@@ -870,7 +867,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
return NULL;
}
- fsp = file_new();
+ fsp = file_new(conn);
if(!fsp)
return NULL;
@@ -919,6 +916,49 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
}
/****************************************************************************
+ Open a file for for write to ensure that we can fchmod it.
+****************************************************************************/
+
+files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf)
+{
+ files_struct *fsp = NULL;
+ BOOL fsp_open;
+
+ if (!VALID_STAT(*psbuf))
+ return NULL;
+
+ fsp = file_new(conn);
+ if(!fsp)
+ return NULL;
+
+ fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0);
+
+ /*
+ * This is not a user visible file open.
+ * Don't set a share mode and don't increment
+ * the conn->num_files_open.
+ */
+
+ if (!fsp_open) {
+ file_free(fsp);
+ return NULL;
+ }
+
+ return fsp;
+}
+
+/****************************************************************************
+ Close the fchmod file fd - ensure no locks are lost.
+****************************************************************************/
+
+int close_file_fchmod(files_struct *fsp)
+{
+ int ret = fd_close(fsp->conn, fsp);
+ file_free(fsp);
+ return ret;
+}
+
+/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
@@ -927,12 +967,12 @@ files_struct *open_directory(connection_struct *conn, char *fname,
{
extern struct current_user current_user;
BOOL got_stat = False;
- files_struct *fsp = file_new();
+ files_struct *fsp = file_new(conn);
if(!fsp)
return NULL;
- fsp->conn = conn; /* THe vfs_fXXX() macros need this. */
+ fsp->conn = conn; /* The vfs_fXXX() macros need this. */
if (VALID_STAT(*psbuf))
got_stat = True;
diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c
index a4057eb7ce..da8484e14e 100644
--- a/source3/smbd/vfs-wrap.c
+++ b/source3/smbd/vfs-wrap.c
@@ -369,6 +369,34 @@ int vfswrap_chmod(connection_struct *conn, char *path, mode_t mode)
return result;
}
+int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
+{
+ int result;
+ struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
+
+ START_PROFILE(syscall_fchmod);
+
+ /*
+ * We need to do this due to the fact that the default POSIX ACL
+ * chmod modifies the ACL *mask* for the group owner, not the
+ * group owner bits directly. JRA.
+ */
+
+ if (vfs_ops->fchmod_acl != NULL) {
+ int saved_errno = errno; /* We might get ENOSYS */
+ if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
+ END_PROFILE(syscall_chmod);
+ return result;
+ }
+ /* Error - return the old errno. */
+ errno = saved_errno;
+ }
+
+ result = fchmod(fd, mode);
+ END_PROFILE(syscall_fchmod);
+ return result;
+}
+
int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid)
{
int result;
@@ -386,6 +414,17 @@ int vfswrap_chown(connection_struct *conn, char *path, uid_t uid, gid_t gid)
return result;
}
+int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
+{
+ int result;
+
+ START_PROFILE(syscall_fchown);
+
+ result = fchown(fd, uid, gid);
+ END_PROFILE(syscall_fchown);
+ return result;
+}
+
int vfswrap_chdir(connection_struct *conn, char *path)
{
int result;
@@ -452,7 +491,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
extend a file with ftruncate. Provide alternate implementation
for this */
- struct vfs_ops *vfs_ops = fsp->conn->vfs_ops;
+ struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
SMB_STRUCT_STAT st;
char c = 0;
SMB_OFF_T currpos;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index f5bd057ca6..713d58cdc8 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -64,7 +64,9 @@ struct vfs_ops default_vfs_ops = {
vfswrap_lstat,
vfswrap_unlink,
vfswrap_chmod,
+ vfswrap_fchmod,
vfswrap_chown,
+ vfswrap_fchown,
vfswrap_chdir,
vfswrap_getwd,
vfswrap_utime,
@@ -224,10 +226,18 @@ BOOL vfs_init_custom(connection_struct *conn)
conn->vfs_ops.chmod = default_vfs_ops.chmod;
}
+ if (conn->vfs_ops.fchmod == NULL) {
+ conn->vfs_ops.fchmod = default_vfs_ops.fchmod;
+ }
+
if (conn->vfs_ops.chown == NULL) {
conn->vfs_ops.chown = default_vfs_ops.chown;
}
+ if (conn->vfs_ops.fchown == NULL) {
+ conn->vfs_ops.fchown = default_vfs_ops.fchown;
+ }
+
if (conn->vfs_ops.chdir == NULL) {
conn->vfs_ops.chdir = default_vfs_ops.chdir;
}