diff options
Diffstat (limited to 'source/smbd/dir.c')
-rw-r--r-- | source/smbd/dir.c | 189 |
1 files changed, 38 insertions, 151 deletions
diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 396ecd98c49..cce62870715 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. Directory handling routines Copyright (C) Andrew Tridgell 1992-1998 @@ -57,7 +58,7 @@ void init_dptrs(void) dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); if (!dptr_bmap) - exit_server("out of memory in init_dptrs"); + exit_server("out of memory in init_dptrs\n"); dptrs_init = True; } @@ -553,24 +554,9 @@ void *dptr_fetch_lanman2(int dptr_num) BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) { - int mask; - - /* Check the "may have" search bits. */ - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - return False; - - /* Check the "must have" bits, which are the may have bits shifted eight */ - /* If must have bit is set, the file/dir can not be returned in search unless the matching - file attribute is set */ - mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */ - if(mask) { - if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */ - return True; - else - return False; - } - - return True; + if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) + return False; + return True; } static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask) @@ -641,7 +627,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) + if (conn->vfs_ops.stat(conn,dos_to_unix_static(pathreal), &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; @@ -678,69 +664,18 @@ typedef struct char *current; } 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, char *name, SMB_STRUCT_STAT *pst) -{ - extern struct current_user current_user; - SEC_DESC *psd = NULL; - size_t sd_size; - files_struct *fsp; - int smb_action; - int access_mode; - NTSTATUS status; - uint32 access_granted; - - /* - * If user is a member of the Admin group - * we never hide files from them. - */ - - if (conn->admin_user) - return True; - - /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) - return False; - - /* Pseudo-open the file (note - no fd's created). */ - - if(S_ISDIR(pst->st_mode)) - fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), - unix_mode(conn,aRONLY|aDIR, name), &smb_action); - else - fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); - - if (!fsp) - return False; - - /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); - close_file(fsp, False); - - /* No access if SD get failed. */ - if (!sd_size) - return False; - - return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, - &access_granted, &status); -} /******************************************************************* - Check to see if a user can write a file (and only files, we do not - check dirs on this one). This is only approximate, - it is used as part of the "hide unwriteable" option. Don't - use it for anything security sensitive. +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_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) +static BOOL user_can_read_file(connection_struct *conn, char *name) { extern struct current_user current_user; + SMB_STRUCT_STAT ste; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; @@ -749,6 +684,8 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ NTSTATUS status; uint32 access_granted; + ZERO_STRUCT(ste); + /* * If user is a member of the Admin group * we never hide files from them. @@ -758,16 +695,17 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (vfs_stat(conn, name, &ste) != 0) return False; /* Pseudo-open the file (note - no fd's created). */ - if(S_ISDIR(pst->st_mode)) - return True; + if(S_ISDIR(ste.st_mode)) + fsp = open_directory(conn, name, &ste, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), + unix_mode(conn,aRONLY|aDIR, name), &smb_action); else - fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), - (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); + fsp = open_file_shared1(conn, name, &ste, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), + (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action); if (!fsp) return False; @@ -780,35 +718,11 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ if (!sd_size) return False; - return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, + return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, &access_granted, &status); } /******************************************************************* - Is a file a "special" type ? -********************************************************************/ - -static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) -{ - /* - * If user is a member of the Admin group - * we never hide files from them. - */ - - if (conn->admin_user) - return True; - - /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) - return True; - - if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) - return False; - - return True; -} - -/******************************************************************* Open a directory. ********************************************************************/ @@ -816,9 +730,9 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; char *n; - DIR *p = conn->vfs_ops.opendir(conn,name); + DIR *p = conn->vfs_ops.opendir(conn,dos_to_unix_static(name)); int used=0; - + if (!p) return(NULL); dirp = (Dir *)malloc(sizeof(Dir)); @@ -827,14 +741,13 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) conn->vfs_ops.closedir(conn,p); return(NULL); } + dirp->pos = dirp->numentries = dirp->mallocsize = 0; dirp->data = dirp->current = NULL; while (True) { int l; BOOL normal_entry = True; - SMB_STRUCT_STAT st; - char *entry = NULL; if (used == 0) { n = "."; @@ -849,69 +762,42 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0)) continue; normal_entry = True; - } + } - ZERO_STRUCT(st); l = strlen(n)+1; + /* Return value of vfs_readdirname has already gone through + unix_to_dos() */ + /* If it's a vetoed file, pretend it doesn't even exist */ if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n)) continue; /* Honour _hide unreadable_ option */ if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) { + char *entry; int ret=0; - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_read_file(conn, entry, &st); - } - if (!ret) { - SAFE_FREE(entry); - continue; - } - } - - /* Honour _hide unwriteable_ option */ - if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) { - int ret=0; - - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = user_can_write_file(conn, entry, &st); - } - if (!ret) { + if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { + ret = user_can_read_file(conn, entry); SAFE_FREE(entry); - continue; } - } - - /* Honour _hide_special_ option */ - if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) { - int ret=0; - - if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) { - ret = file_is_special(conn, entry, &st); - } - if (ret) { - SAFE_FREE(entry); + if (!ret) continue; - } } - SAFE_FREE(entry); - if (used + l > dirp->mallocsize) { int s = MAX(used+l,used+2000); char *r; r = (char *)Realloc(dirp->data,s); if (!r) { DEBUG(0,("Out of memory in OpenDir\n")); - break; - } + break; + } dirp->data = r; dirp->mallocsize = s; dirp->current = dirp->data; } - pstrcpy(dirp->data+used,n); used += l; dirp->numentries++; @@ -928,9 +814,10 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) void CloseDir(void *p) { - if (!p) return; - SAFE_FREE(((Dir *)p)->data); - SAFE_FREE(p); + Dir *dirp = (Dir *)p; + if (!dirp) return; + SAFE_FREE(dirp->data); + SAFE_FREE(dirp); } /******************************************************************* |