Olf fashioned 'anonynous' FTP 'incoming' directory

Dirk-Willem van Gulik Dirk-Willem.van.Gulik at BBC.co.uk
Thu Jan 6 08:12:40 MST 2011


Below is a stab at the same issue for samba4. Or is this 'wrong' - i.e. this is not a POSIX thing - but should be done higher up ?

Thanks,

Dw.

diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index 0da64a7..4fb9ba4 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -142,10 +142,31 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs,
                }
                
                dir = opendir(partial_name);
+                /* now opendir will fail on a non rw directory - but if it is
+                 * still 'x' then access of something deeper (with  r or w)
+                 * will in fact succeed provided there is a 'x' for the user,
+                 * group or world. This is akin to the dead-drop use of an
+                 * old fashioned anonymous ftp incoming directory (Posix 4.8.3)
+                 */
                if (!dir) {
-                       return pvfs_map_errno(pvfs, errno);
+                        /* if there is nothing deeper - give up now. */
+                        if (i == num_components-1)
+                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+
+                        /* check for the special 'x' with no r or w case on 
+                         * a directory (i.e. not a symlink, mntpnt, etc).
+                         *
+                         * We're not further checking uid/gid - as a ENOTDIR 
+                         * will be returned in the next iteration by the stat.
+                         */
+                        if (((name->st.st_mode) & (S_IXUSR|S_IXGRP|S_IXOTH)) && (S_ISDIR(name->st.st_mode))  {
+                               test_name = talloc_asprintf(name, "%s/%s", partial_name, components[i]);
+                               talloc_free(partial_name);
+                               partial_name = test_name;
+                                continue;
+                        }
+                       return pvfs_map_errno(pvfs, errno);
                }
-
                while ((de = readdir(dir))) {
                        if (component_compare(pvfs, components[i], de->d_name) == 0) {
                                break;

> Was looking for FTP style incoming directory functionality in CIFS (windows or unix).
> 
> I.e. where you have a dir "incoming" with x--x--x--  - in which you can put stuff; And you can even get it out if you know the exact name. But directory listings are dis-allowed. I.e. like:
> 
> 	$ mkdir -p foo/bar
>  	$ echo Hi > foo/bar/test
>  	$ chmod a-rw foo
>  	$ ls foo
> 	ls: foo: Permission denied 
> 	$ cat foo/bar/test
> 	Hi
> 	$ ls -la foo/bar
> 	total 6 
> 	drwxr-xr-x 2 dirkx dirkx 512 Jan 5 20:51 . 
> 	d--x--x--x 3 dirkx dirkx 512 Jan 5 20:51 .. 
> 	-rw-r--r-- 1 dirkx dirkx   3 Jan 5 20:51 test 
> 	$ ls foo 
> 	ls: foo: Permission denied 
> 	$
> 
> And found that I could not really do this cleanly/neatly with veto/hidden or permissions - as OpenDir is called from filename.c/dir.c for every path element - rather than evaluating it 'unix style'.
> 
> Is that correct ? Or is there a clean/rock-solid way (in the light of caching) which works ?
> 
> So I ended up hacking below into the 'opendir' -- as a special case. Which works well... but am guessing that this is not the right approach.
> 
> Any advice ?
> 
> Dw.
> 
> 
> 
> static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
> {
> 	SMB_STRUCT_DIR *result;
> 
> 	START_PROFILE(syscall_opendir);
> 	result = sys_opendir(fname);
> #ifDEF FTP_HIDDENDIR
> 	if (!result) {
> 		/* Rather than return an error right away - make an exception for a FTP incoming style (no R, no R but X on all)
> 		 * and if that is indeed the leaf - show an empty dir - but allow pass through.
> 		 */
>                struct stat dirstat;
>                if ((stat(fname, &dirstat) != 0) || ((dirstat.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != (S_IXUSR|S_IXGRP|S_IXOTH))) {
>                        return NULL;
>                }
> 		result = sys_opendir(FTP_HIDDENDIR);
> 		DEBUG(3,("Cont. with a empty dir struct - as we detected a rwXrwXrwX 'hidden' dir.\n"));
>        }
> #endif
> 	END_PROFILE(syscall_opendir);
> 	return result;
> }


More information about the samba-technical mailing list