diff options
-rw-r--r-- | source3/smbd/open.c | 99 |
1 files changed, 59 insertions, 40 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7558954ec6..d0a48ced4b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -623,15 +623,49 @@ reproduce the share mode access table static int access_table(int new_deny,int old_deny,int old_mode, pid_t share_pid,char *fname) { - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (old_deny == DENY_DOS || new_deny == DENY_DOS || - old_deny == DENY_FCB || new_deny == DENY_FCB) { + pid_t pid = getpid(); + BOOL isexe = False; + if ((fname = strrchr(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) { + isexe = True; + } + } + + if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); + + if (share_pid == pid) { + if (isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_READ) { + return AFAIL; + } + if (!isexe && old_mode == O_RDONLY && + old_deny == DENY_DOS && new_deny == DENY_DOS) { + return AREAD; + } + if (new_deny == DENY_FCB && old_deny == DENY_DOS) { + if (isexe) return AFAIL; + if (old_mode == DOS_OPEN_RDONLY) return AFAIL; + return AALL; + } + if (old_mode == O_RDONLY && old_deny == DENY_DOS) { + if (new_deny == DENY_FCB || new_deny == DENY_READ) { + if (isexe) return AREAD; + return AFAIL; + } + } + if (old_deny == DENY_FCB) { + if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL; + return AFAIL; + } + } + + if (old_deny == DENY_DOS || new_deny == DENY_DOS || + old_deny == DENY_FCB || new_deny == DENY_FCB) { + if (isexe) { if (old_deny == DENY_FCB || new_deny == DENY_FCB) { return AFAIL; } @@ -652,10 +686,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (old_deny == DENY_READ) return AWRITE; if (old_deny == DENY_WRITE) return AREAD; } - } - /* it isn't a exe, dll, sym or com file */ - { - pid_t pid = getpid(); + /* it isn't a exe, dll, sym or com file */ if (old_deny == new_deny && share_pid == pid) return(AALL); @@ -664,27 +695,26 @@ static int access_table(int new_deny,int old_deny,int old_mode, return(AFAIL); } - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); - if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); + + switch (new_deny) + { + case DENY_WRITE: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL); + return(AFAIL); + case DENY_READ: + if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD); + if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE); + if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL); + return(AFAIL); + case DENY_NONE: + if (old_deny==DENY_WRITE) return(AREAD); + if (old_deny==DENY_READ) return(AWRITE); + if (old_deny==DENY_NONE) return(AALL); + return(AFAIL); + } + return(AFAIL); } /**************************************************************************** @@ -712,17 +742,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, return False; } - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - - return False; - } - { int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, share->pid,fname); |