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