return(True);
}
+#if 0
+ /*
+ * This code I believe is incorrect - and commenting it out
+ * is the correct fix for the bug mentioned below in the
+ * comment 'name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra)'.
+ * The incoming name can be mangled, and if we de-mangle it
+ * here it will not compare correctly against the filename (name2)
+ * read from the directory and then mangled by the name_map_mangle()
+ * call. We need to mangle both names or neither.
+ * (JRA).
+ */
if (mangled)
check_mangled_stack(name);
+#endif
/* open the directory */
if (!(cur_dir = OpenDir(cnum, path, True)))
struct stat statbuf;
file_fd_struct *fd_ptr;
files_struct *fsp = &Files[fnum];
+ int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
fsp->open = False;
fsp->fd_ptr = 0;
pstrcpy(fname,fname1);
/* check permissions */
- if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
- {
+
+ /*
+ * This code was changed after seeing a client open request
+ * containing the open mode of (DENY_WRITE/read-only) with
+ * the 'create if not exist' bit set. The previous code
+ * would fail to open the file read only on a read-only share
+ * as it was checking the flags parameter directly against O_RDONLY,
+ * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
+ * JRA.
+ */
+
+ if (!CAN_WRITE(cnum) && !Connections[cnum].printer) {
+ /* It's a read-only share - fail if we wanted to write. */
+ if(accmode != O_RDONLY) {
DEBUG(3,("Permission denied opening %s\n",fname));
check_for_pipe(fname);
return;
}
+ else if(flags & O_CREAT) {
+ /* We don't want to write - but we must make sure that O_CREAT
+ doesn't create the file if we have write access into the
+ directory.
+ */
+ flags &= ~O_CREAT;
+ }
+ }
/* this handles a bug in Win95 - it doesn't say to create the file when it
should */
*/
if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
- int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
-
/* File was already open. */
if((flags & O_CREAT) && (flags & O_EXCL)) {
fd_ptr->ref_count--;
fsp->print_file = Connections[cnum].printer;
fsp->modified = False;
fsp->granted_oplock = False;
+ fsp->sent_oplock_break = False;
fsp->cnum = cnum;
string_set(&fsp->name,dos_to_unix(fname,False));
fsp->wbmpx_ptr = NULL;
if(fs_p->granted_oplock == True)
global_oplocks_open--;
+ fs_p->sent_oplock_break = False;
+
DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
timestring(),Connections[cnum].user,fs_p->name,
Connections[cnum].num_files_open));
!IS_VETO_OPLOCK_PATH(cnum,fname))
{
fs_p->granted_oplock = True;
+ fs_p->sent_oplock_break = False;
global_oplocks_open++;
port = oplock_port;
return True;
}
close(Client); /* The parent doesn't need this socket */
-#endif /NO_FORK_DEBUG */
+#endif /* NO_FORK_DEBUG */
} /* end for num */
} /* end while 1 */
} /* end if is_daemon */
if (msg_type == 0)
show_msg(inbuf);
+ else if(msg_type == 0x85)
+ return; /* Keepalive packet. */
nread = construct_reply(inbuf,outbuf,nread,max_send);
DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \
global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open));
- if(inbuf == NULL)
- {
- inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- if(inbuf == NULL) {
- DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
- return False;
- }
- outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- if(outbuf == NULL) {
- DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
- free(inbuf);
- inbuf = NULL;
- return False;
- }
- }
-
/* We need to search the file open table for the
entry containing this dev and inode, and ensure
we have an oplock on it. */
if(fsp == NULL)
{
/* The file could have been closed in the meantime - return success. */
- DEBUG(3,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
+ DEBUG(0,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
allowing break to succeed.\n", timestring(), dev, inode, fnum));
return True;
}
if(!fsp->granted_oplock)
{
- DEBUG(3,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \
-Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode));
+ DEBUG(0,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode));
return True;
}
+ /* mark the oplock break as sent - we don't want to send twice! */
+ if (fsp->sent_oplock_break)
+ {
+ DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode));
+
+ /* We have to fail the open here as we cannot send another oplock break on this
+ file whilst we are awaiting a response from the client - neither can we
+ allow another open to succeed while we are waiting for the client. */
+ return False;
+ }
+
/* Now comes the horrid part. We must send an oplock break to the client,
and then process incoming messages until we get a close or oplock release.
+ At this point we know we need a new inbuf/outbuf buffer pair.
+ We cannot use these staticaly as we may recurse into here due to
+ messages crossing on the wire.
*/
+ if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+ {
+ DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
+ return False;
+ }
+
+ if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+ {
+ DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
+ free(inbuf);
+ inbuf = NULL;
+ return False;
+ }
+
/* Prepare the SMBlockingX message. */
bzero(outbuf,smb_size);
set_message(outbuf,8,0,True);
send_smb(Client, outbuf);
+ /* Remember we just sent an oplock break on this file. */
+ fsp->sent_oplock_break = True;
+
/* We need this in case a readraw crosses on the wire. */
global_oplock_break = True;
}
}
+ /* Free the buffers we've been using to recurse. */
+ free(inbuf);
+ free(outbuf);
+
/* We need this in case a readraw crossed on the wire. */
if(global_oplock_break)
global_oplock_break = False;
from the sharemode. */
/* Paranoia.... */
fsp->granted_oplock = False;
- global_oplocks_open--;
+ fsp->sent_oplock_break = False;
+ global_oplocks_open--;
}
/* Santity check - remove this later. JRA */
process_local_message(oplock_sock, inbuf, bufsize);
continue;
}
+
+ if(ret && (CVAL(inbuf,0) == 0x85))
+ {
+ /* Keepalive packet. */
+ got_smb = False;
+ }
+
}
while(ret && !got_smb);
****************************************************************************/
int find_free_file(void )
{
- int i;
- /* we start at 1 here for an obscure reason I can't now remember,
- but I think is important :-) */
- for (i=1;i<MAX_OPEN_FILES;i++)
- if (!Files[i].open)
- return(i);
- DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
- return(-1);
+ int i;
+ static int first_file;
+
+ /* we want to give out file handles differently on each new
+ connection because of a common bug in MS clients where they try to
+ reuse a file descriptor from an earlier smb connection. This code
+ increases the chance that the errant client will get an error rather
+ than causing corruption */
+ if (first_file == 0) {
+ first_file = (getpid() ^ (int)time(NULL)) % MAX_OPEN_FILES;
+ if (first_file == 0) first_file = 1;
+ }
+
+ for (i=first_file;i<MAX_OPEN_FILES;i++)
+ if (!Files[i].open) {
+ memset(&Files[i], 0, sizeof(Files[i]));
+ return(i);
+ }
+
+ /* returning a file handle of 0 is a bad idea - so we start at 1 */
+ for (i=1;i<first_file;i++)
+ if (!Files[i].open) {
+ memset(&Files[i], 0, sizeof(Files[i]));
+ return(i);
+ }
+
+
+ DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
+ return(-1);
}
/****************************************************************************
{
int cnum = SVAL(inbuf,smb_tid);
int flags = smb_messages[match].flags;
- uint16 session_tag = SVAL(inbuf,smb_uid);
+ /* In share mode security we must ignore the vuid. */
+ uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
/* does this protocol need to be run as root? */
if (!(flags & AS_USER))
int port = SMB_PORT;
int opt;
extern char *optarg;
- char pidFile[100] = { 0 };
+ char pidFile[100];
+
+ *pidFile = '\0';
#ifdef NEED_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
#ifndef NO_SIGNAL_TEST
signal(SIGHUP,SIGNAL_CAST sig_hup);
#endif
-
+
+ /* Setup the signals that allow the debug log level
+ to by dynamically changed. */
+
+#if defined(SIGUSR1)
+ signal( SIGUSR1, SIGNAL_CAST sig_usr1 );
+#endif /* SIGUSR1 */
+
+#if defined(SIGUSR2)
+ signal( SIGUSR2, SIGNAL_CAST sig_usr2 );
+#endif /* SIGUSR2 */
+
DEBUG(3,("%s loaded services\n",timestring()));
if (!is_daemon && !is_a_socket(0))