diff options
Diffstat (limited to 'source3/smbd/dir.c')
-rw-r--r-- | source3/smbd/dir.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5bf0dec944..46078b8d06 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -663,6 +663,36 @@ typedef struct } Dir; + +/******************************************************************* +check to see if a user can read a file. This is only approximate, +it is used as part of the "hide unreadable" option. Don't +use it for anything security sensitive +********************************************************************/ +static BOOL user_can_read_file(connection_struct *conn, const char *name) +{ + struct stat ste; + + /* if we can't stat it does not show it */ + if (stat(name, &ste) != 0) return False; + + if (ste.st_uid == conn->uid) { + return (ste.st_mode & S_IRUSR) == S_IRUSR; + } else { + int i; + if (ste.st_gid == conn->gid) { + return (ste.st_mode & S_IRGRP) == S_IRGRP; + } + for (i=0; i<conn->ngroups; i++) { + if (conn->groups[i] == ste.st_gid) { + return (ste.st_mode & S_IRGRP) == S_IRGRP; + } + } + } + + return (ste.st_mode & S_IROTH) == S_IROTH; +} + /******************************************************************* Open a directory. ********************************************************************/ @@ -677,6 +707,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { + DEBUG(0,("Out of memory in OpenDir\n")); conn->vfs_ops.closedir(conn,p); return(NULL); } @@ -695,6 +726,24 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) /* If it's a vetoed file, pretend it doesn't even exist */ if (use_veto && conn && IS_VETO_PATH(conn, n)) continue; + /* Honour _hide unreadable_ option */ + if (conn && lp_hideunreadable(SNUM(conn))) + { + char *entry; + int ret; + + entry = (char *)malloc(PATH_MAX); + if (!entry) { + DEBUG(0,("Out of memory in OpenDir\n")); + conn->vfs_ops.closedir(conn,p); + return(NULL); + } + slprintf(entry, PATH_MAX, "%s/%s/%s", conn->origpath, name, n); + ret = user_can_read_file(conn, entry); + free(entry); + if (!ret) continue; + } + if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; |