summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2005-03-15 01:19:58 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:56:01 -0500
commitcc5ba986bf4c7b704ae5c3787f2f3881145e719c (patch)
treed7d83dee305d4d62a6f763bafc28bf4b07e24cf1 /source3/smbd/reply.c
parent00a62a7f6d880c3788e7211cbbcc95dc6e2aa90e (diff)
downloadsamba-cc5ba986bf4c7b704ae5c3787f2f3881145e719c.tar.gz
samba-cc5ba986bf4c7b704ae5c3787f2f3881145e719c.tar.bz2
samba-cc5ba986bf4c7b704ae5c3787f2f3881145e719c.zip
r5792: Added new parameter "inherit owner". If set on a share, the created file/directory
will be owned by the same uid as the containing directory. Doing this for directories in a race-free mannor has only been tested on Linux (it depends on being able to open a directory and then do a fchown on that file descriptor). If this functionality is not available then the code silently downgrades to not changing the ownership of a new directory. This new parameter (docs to follow) finally makes it possible to create "drop boxes" on Samba, which requires all files within a directory to be commonly owned. A HOWTO on how to use this will follow. Jeremy. (This used to be commit 2e1f727184b9d025d2e3413bdd3d01d5ca803a41)
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c63
1 files changed, 52 insertions, 11 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index f149b79f79..376b42e5fd 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3303,29 +3303,47 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
code.
****************************************************************************/
-NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
+NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
{
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
int ret= -1;
- unix_convert(directory,conn,0,&bad_path,&sbuf);
-
- if( strchr_m(directory, ':')) {
- return NT_STATUS_NOT_A_DIRECTORY;
+ if(!CAN_WRITE(conn)) {
+ DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
+ errno = EACCES;
+ return map_nt_error_from_unix(errno);
}
+ /* The following 2 clauses set explicit DOS error codes. JRA. */
if (ms_has_wild(directory)) {
+ DEBUG(5,("mkdir_internal: failing create on filename %s with wildcards\n", directory));
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRinvalidname;
return NT_STATUS_OBJECT_NAME_INVALID;
}
+ if( strchr_m(directory, ':')) {
+ DEBUG(5,("mkdir_internal: failing create on filename %s with colon in name\n", directory));
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRinvalidname;
+ return NT_STATUS_NOT_A_DIRECTORY;
+ }
+
if (bad_path) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- if (check_name(directory, conn))
- ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
-
+ if (!check_name(directory, conn)) {
+ if(errno == ENOENT) {
+ if (bad_path) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ }
+ return map_nt_error_from_unix(errno);
+ }
+
+ ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
if (ret == -1) {
if(errno == ENOENT) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -3345,6 +3363,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring directory;
int outsize;
NTSTATUS status;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+
START_PROFILE(SMBmkdir);
srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
@@ -3355,12 +3376,32 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
- status = mkdir_internal(conn, directory);
+ unix_convert(directory,conn,0,&bad_path,&sbuf);
+
+ status = mkdir_internal(conn, directory,bad_path);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
return ERROR_NT(status);
}
+ if (lp_inherit_owner(SNUM(conn))) {
+ /* Ensure we're checking for a symlink here.... */
+ /* We don't want to get caught by a symlink racer. */
+
+ if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
+ END_PROFILE(SMBmkdir);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ if(!S_ISDIR(sbuf.st_mode)) {
+ DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
+ END_PROFILE(SMBmkdir);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ change_owner_to_parent(conn, NULL, directory, &sbuf);
+ }
+
outsize = set_message(outbuf,0,0,True);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );