s3:smbd: check for allow_wcard_last_component early in unix_convert()
[metze/samba/wip.git] / source3 / smbd / filename.c
index dcee5a76cfd6d9960911ee9dadc3a476764888b0..81532a06dac8c819e66f168886ac71dc04763d29 100644 (file)
@@ -268,6 +268,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
+       name_has_wildcard = ms_has_wild(name);
+
+       /* Wildcard not valid anywhere. */
+       if (name_has_wildcard && !allow_wcard_last_component) {
+               result = NT_STATUS_OBJECT_NAME_INVALID;
+               goto fail;
+       }
+
        /*
         * stat the name - if it exists then we are all done!
         */
@@ -374,12 +382,6 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
 
                name_has_wildcard = ms_has_wild(start);
 
-               /* Wildcard not valid anywhere. */
-               if (name_has_wildcard && !allow_wcard_last_component) {
-                       result = NT_STATUS_OBJECT_NAME_INVALID;
-                       goto fail;
-               }
-
                /* Wildcards never valid within a pathname. */
                if (name_has_wildcard && end) {
                        result = NT_STATUS_OBJECT_NAME_INVALID;
@@ -401,7 +403,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                         * It exists. it must either be a directory or this must
                         * be the last part of the path for it to be OK.
                         */
-                       if (end && !(st.st_mode & S_IFDIR)) {
+                       if (end && !S_ISDIR(st.st_ex_mode)) {
                                /*
                                 * An intermediate part of the name isn't
                                 * a directory.
@@ -490,8 +492,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                                        goto fail;
                                }
 
-                               /* ENOENT is the only valid error here. */
-                               if ((errno != 0) && (errno != ENOENT)) {
+                               /*
+                                * ENOENT/EACCESS are the only valid errors
+                                * here. EACCESS needs handling here for
+                                * "dropboxes", i.e. directories where users
+                                * can only put stuff with permission -wx.
+                                */
+                               if ((errno != 0) && (errno != ENOENT)
+                                   && (errno != EACCES)) {
                                        /*
                                         * ENOTDIR and ELOOP both map to
                                         * NT_STATUS_OBJECT_PATH_NOT_FOUND
@@ -501,12 +509,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                                                        errno == ELOOP) {
                                                result =
                                                NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                                               goto fail;
-                                       } else if (errno != EACCES) {
+                                       } else {
                                                result =
                                                map_nt_error_from_unix(errno);
-                                               goto fail;
                                        }
+                                       goto fail;
                                }
 
                                /*