summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/open.c99
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);