pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring sesssetup_user;
-extern fstring myworkgroup;
+extern fstring global_myworkgroup;
+extern pstring global_myname;
char *InBuffer = NULL;
char *OutBuffer = NULL;
extern BOOL short_case_preserve;
extern BOOL case_mangle;
time_t smb_last_time=(time_t)0;
+extern BOOL global_machine_pasword_needs_changing;
extern int smb_read_error;
extern int dcelogin_atmost_once;
#endif /* DFS_AUTH */
+/*
+ * This is set on startup - it defines the SID for this
+ * machine.
+ */
+extern DOM_SID global_machine_sid;
+
connection_struct Connections[MAX_CONNECTIONS];
-files_struct Files[MAX_OPEN_FILES];
+files_struct Files[MAX_FNUMS];
/*
* Indirection for file fd's. Needed as POSIX locking
extern pstring OriginalDir;
/* these can be set by some functions to override the error codes */
-int unix_ERR_class=SUCCESS;
+int unix_ERR_class=SMB_SUCCESS;
int unix_ERR_code=0;
if (is_8_3(name2, True))
return(False);
- strcpy(tmpname,name2);
- mangle_name_83(tmpname);
+ pstrcpy(tmpname,name2);
+ mangle_name_83(tmpname,sizeof(tmpname));
return(strequal(name1,tmpname));
}
path = ".";
if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
- strcpy(name, dname);
+ pstrcpy(name, dname);
return(True);
}
* (JRA).
*/
if (mangled)
- mangled = !check_mangled_stack(name);
+ mangled = !check_mangled_cache( name );
/* open the directory */
if (!(cur_dir = OpenDir(cnum, path, True)))
{
/* we've found the file, change it's name and return */
if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
- strcpy(name, dname);
+ pstrcpy(name, dname);
CloseDir(cur_dir);
return(True);
}
if(saved_last_component) {
end = strrchr(name, '/');
if(end)
- strcpy(saved_last_component, end + 1);
+ pstrcpy(saved_last_component, end + 1);
else
- strcpy(saved_last_component, name);
+ pstrcpy(saved_last_component, name);
}
if (!case_sensitive &&
{
char *s;
fstring name2;
- sprintf(name2,"%.6s.XXXXXX",remote_machine);
+ slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
/* sanitise the name */
for (s=name2 ; *s ; s++)
if (!issafe(*s)) *s = '_';
- strcpy(name,(char *)mktemp(name2));
+ pstrcpy(name,(char *)mktemp(name2));
}
return(True);
}
if (end) *end = 0;
if(saved_last_component != 0)
- strcpy(saved_last_component, end ? end + 1 : start);
+ pstrcpy(saved_last_component, end ? end + 1 : start);
/* check if the name exists up to this point */
if (sys_stat(name, &st) == 0)
/* check on the mangled stack to see if we can recover the
base of the filename */
if (is_mangled(start))
- check_mangled_stack(start);
+ check_mangled_cache( start );
DEBUG(5,("New file %s\n",start));
return(True);
/* restore the rest of the string */
if (end)
{
- strcpy(start+strlen(start)+1,rest);
+ pstrcpy(start+strlen(start)+1,rest);
end = start + strlen(start);
}
}
/* add to the dirpath that we have resolved so far */
- if (*dirpath) strcat(dirpath,"/");
- strcat(dirpath,start);
+ if (*dirpath) pstrcat(dirpath,"/");
+ pstrcat(dirpath,start);
/* restore the / that we wiped out earlier */
if (end) *end = '/';
pstring syscmd;
pstring outfile;
- sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
- sprintf(syscmd,"%s %s",df_command,path);
+ slprintf(outfile,sizeof(outfile)-1, "%s/dfree.smb.%d",tmpdir(),(int)getpid());
+ slprintf(syscmd,sizeof(syscmd)-1,"%s %s",df_command,path);
standard_sub_basic(syscmd);
ret = smbrun(syscmd,outfile,False);
if((fd == -1) && (errno == ENOENT) &&
(strchr(fname,'.')==NULL))
{
- strcat(fname,".");
+ pstrcat(fname,".");
fd = sys_open(fname,flags,mode);
}
return fd;
}
+/****************************************************************************
+Cache a uid_t currently with this file open. This is an optimization only
+used when multiple sessionsetup's have been done to one smbd.
+****************************************************************************/
+static void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u)
+{
+ if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t))
+ return;
+ fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u;
+}
+
+/****************************************************************************
+Remove a uid_t that currently has this file open. This is an optimization only
+used when multiple sessionsetup's have been done to one smbd.
+****************************************************************************/
+static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u)
+{
+ int i;
+ for(i = 0; i < fd_ptr->uid_cache_count; i++)
+ if(fd_ptr->uid_users_cache[i] == u) {
+ if(i < (fd_ptr->uid_cache_count-1))
+ memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1],
+ sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) );
+ fd_ptr->uid_cache_count--;
+ }
+ return;
+}
+
+/****************************************************************************
+Check if a uid_t that currently has this file open is present. This is an
+optimization only used when multiple sessionsetup's have been done to one smbd.
+****************************************************************************/
+static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u)
+{
+ int i;
+ for(i = 0; i < fd_ptr->uid_cache_count; i++)
+ if(fd_ptr->uid_users_cache[i] == u)
+ return True;
+ return False;
+}
+
/****************************************************************************
fd support routines - attempt to find an already open file by dev
and inode - increments the ref_count of the returned file_fd_struct *.
fd support routines - attempt to find a empty slot in the FileFd array.
Increments the ref_count of the returned entry.
****************************************************************************/
-static file_fd_struct *fd_get_new()
+static file_fd_struct *fd_get_new(void)
{
+ extern struct current_user current_user;
int i;
file_fd_struct *fd_ptr;
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
fd_ptr->real_open_flags = -1;
+ fd_ptr->uid_cache_count = 0;
+ fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid);
fd_ptr->ref_count++;
/* Increment max used counter if neccessary, cuts down
- on search time when re-using */
+ on search time when re-using */
if(i > max_file_fd_used)
max_file_fd_used = i;
DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
return fd_ptr;
}
}
- DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
-n"));
+ DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n"));
return 0;
}
****************************************************************************/
static int fd_attempt_close(file_fd_struct *fd_ptr)
{
+ extern struct current_user current_user;
+
DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
- fd_ptr - &FileFd[0],
- fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
- fd_ptr->real_open_flags,
- fd_ptr->ref_count));
+ fd_ptr - &FileFd[0],
+ fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
+ fd_ptr->real_open_flags,
+ fd_ptr->ref_count));
if(fd_ptr->ref_count > 0) {
fd_ptr->ref_count--;
if(fd_ptr->ref_count == 0) {
if(fd_ptr->fd != -1)
close(fd_ptr->fd);
if(fd_ptr->fd_readonly != -1)
- close(fd_ptr->fd_readonly);
+ close(fd_ptr->fd_readonly);
if(fd_ptr->fd_writeonly != -1)
- close(fd_ptr->fd_writeonly);
+ close(fd_ptr->fd_writeonly);
fd_ptr->fd = -1;
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
fd_ptr->real_open_flags = -1;
fd_ptr->dev = (uint32)-1;
fd_ptr->inode = (uint32)-1;
- }
+ fd_ptr->uid_cache_count = 0;
+ } else
+ fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
}
return fd_ptr->ref_count;
}
+/****************************************************************************
+fd support routines - check that current user has permissions
+to open this file. Used when uid not found in optimization cache.
+This is really ugly code, as due to POSIX locking braindamage we must
+fork and then attempt to open the file, and return success or failure
+via an exit code.
+****************************************************************************/
+static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
+{
+ pid_t child_pid;
+
+ if((child_pid = fork()) < 0) {
+ DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n"));
+ return False;
+ }
+
+ if(child_pid) {
+ /*
+ * Parent.
+ */
+ pid_t wpid;
+ int status_code;
+ if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) {
+ DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n"));
+ return(False);
+ }
+
+ if (child_pid != wpid) {
+ DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n"));
+ return(False);
+ }
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+ if (WIFEXITED(status_code) == 0) {
+ DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n"));
+ return(False);
+ }
+ if (WEXITSTATUS(status_code) != 0) {
+ DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
+ return(False);
+ }
+#else /* defined(WIFEXITED) && defined(WEXITSTATUS) */
+ if(status_code != 0) {
+ DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
+ return(False);
+ }
+#endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */
+
+ /*
+ * Success - the child could open the file.
+ */
+ DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code));
+ return True;
+ } else {
+ /*
+ * Child.
+ */
+ int fd;
+ DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode ));
+ if((fd = fd_attempt_open( fname, accmode, 0)) < 0) {
+ /* Access denied. */
+ _exit(EACCES);
+ }
+ close(fd);
+ DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n"));
+ _exit(0);
+ }
+
+ return False;
+}
+
/****************************************************************************
open a file
****************************************************************************/
* open fd table.
*/
if(sbuf == 0) {
- if(stat(fname, &statbuf) < 0) {
+ if(sys_stat(fname, &statbuf) < 0) {
if(errno != ENOENT) {
DEBUG(3,("Error doing stat on file %s (%s)\n",
fname,strerror(errno)));
* reference count (fd_get_already_open increments the ref_count).
*/
if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
+ /*
+ * File was already open.
+ */
- /* File was already open. */
+ /*
+ * Check it wasn't open for exclusive use.
+ */
if((flags & O_CREAT) && (flags & O_EXCL)) {
fd_ptr->ref_count--;
errno = EEXIST;
return;
}
+ /*
+ * Ensure that the user attempting to open
+ * this file has permissions to do so, if
+ * the user who originally opened the file wasn't
+ * the same as the current user.
+ */
+
+ if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) {
+ if(!check_access_allowed_for_current_user( fname, accmode )) {
+ /* Error - permission denied. */
+ DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n",
+ fname, flags, accmode));
+ /* Ensure the ref_count is decremented. */
+ fd_ptr->ref_count--;
+ fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
+ errno = EACCES;
+ return;
+ }
+ }
+
+ fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid);
+
/*
* If not opened O_RDWR try
* and do that here - a chmod may have been done
DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
check_for_pipe(fname);
+ fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
fd_ptr->ref_count--;
return;
}
fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
fd_ptr->real_open_flags = O_WRONLY;
} else {
- fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
+ fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
fd_ptr->real_open_flags = O_RDONLY;
}
}
}
if (fd_ptr->fd < 0)
- {
- DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
- fname,strerror(errno),flags));
- /* Ensure the ref_count is decremented. */
- fd_attempt_close(fd_ptr);
- check_for_pipe(fname);
- return;
- }
+ {
+ DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
+ fname,strerror(errno),flags));
+ /* Ensure the ref_count is decremented. */
+ fd_attempt_close(fd_ptr);
+ check_for_pipe(fname);
+ return;
+ }
if (fd_ptr->fd >= 0)
- {
- if(sbuf == 0) {
- /* Do the fstat */
- if(fstat(fd_ptr->fd, &statbuf) == -1) {
- /* Error - backout !! */
- DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
- fd_ptr->fd, fname,strerror(errno)));
- /* Ensure the ref_count is decremented. */
- fd_attempt_close(fd_ptr);
- return;
- }
- sbuf = &statbuf;
+ {
+ if(sbuf == 0) {
+ /* Do the fstat */
+ if(fstat(fd_ptr->fd, &statbuf) == -1) {
+ /* Error - backout !! */
+ DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
+ fd_ptr->fd, fname,strerror(errno)));
+ /* Ensure the ref_count is decremented. */
+ fd_attempt_close(fd_ptr);
+ return;
}
- /* Set the correct entries in fd_ptr. */
- fd_ptr->dev = (uint32)sbuf->st_dev;
- fd_ptr->inode = (uint32)sbuf->st_ino;
-
- fsp->fd_ptr = fd_ptr;
- Connections[cnum].num_files_open++;
- fsp->mode = sbuf->st_mode;
- GetTimeOfDay(&fsp->open_time);
- fsp->vuid = current_user.vuid;
- fsp->size = 0;
- fsp->pos = -1;
- fsp->open = True;
- fsp->mmap_ptr = NULL;
- fsp->mmap_size = 0;
- fsp->can_lock = True;
- fsp->can_read = ((flags & O_WRONLY)==0);
- fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
- fsp->share_mode = 0;
- 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;
+ sbuf = &statbuf;
+ }
- /*
- * If the printer is marked as postscript output a leading
- * file identifier to ensure the file is treated as a raw
- * postscript file.
- * This has a similar effect as CtrlD=0 in WIN.INI file.
- * tim@fsg.com 09/06/94
- */
- if (fsp->print_file && POSTSCRIPT(cnum) &&
- fsp->can_write)
- {
- DEBUG(3,("Writing postscript line\n"));
- write_file(fnum,"%!\n",3);
- }
-
- DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
- timestring(),Connections[cnum].user,fname,
- BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write),
- Connections[cnum].num_files_open,fnum));
+ /* Set the correct entries in fd_ptr. */
+ fd_ptr->dev = (uint32)sbuf->st_dev;
+ fd_ptr->inode = (uint32)sbuf->st_ino;
+
+ fsp->fd_ptr = fd_ptr;
+ Connections[cnum].num_files_open++;
+ fsp->mode = sbuf->st_mode;
+ GetTimeOfDay(&fsp->open_time);
+ fsp->vuid = current_user.vuid;
+ fsp->size = 0;
+ fsp->pos = -1;
+ fsp->open = True;
+ fsp->mmap_ptr = NULL;
+ fsp->mmap_size = 0;
+ fsp->can_lock = True;
+ fsp->can_read = ((flags & O_WRONLY)==0);
+ fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
+ fsp->share_mode = 0;
+ fsp->print_file = Connections[cnum].printer;
+ fsp->modified = False;
+ fsp->granted_oplock = False;
+ fsp->sent_oplock_break = False;
+ fsp->is_directory = False;
+ fsp->cnum = cnum;
+ /*
+ * Note that the file name here is the *untranslated* name
+ * ie. it is still in the DOS codepage sent from the client.
+ * All use of this filename will pass though the sys_xxxx
+ * functions which will do the dos_to_unix translation before
+ * mapping into a UNIX filename. JRA.
+ */
+ string_set(&fsp->name,fname);
+ fsp->wbmpx_ptr = NULL;
+ /*
+ * If the printer is marked as postscript output a leading
+ * file identifier to ensure the file is treated as a raw
+ * postscript file.
+ * This has a similar effect as CtrlD=0 in WIN.INI file.
+ * tim@fsg.com 09/06/94
+ */
+ if (fsp->print_file && POSTSCRIPT(cnum) && fsp->can_write)
+ {
+ DEBUG(3,("Writing postscript line\n"));
+ write_file(fnum,"%!\n",3);
}
+
+ DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
+ timestring(),
+ *sesssetup_user ? sesssetup_user : Connections[cnum].user,fname,
+ BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write),
+ Connections[cnum].num_files_open,fnum));
+
+ }
#if USE_MMAP
/* mmap it if read-only */
if (!fsp->can_write)
- {
- fsp->mmap_size = file_size(fname);
- fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
- PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
+ {
+ fsp->mmap_size = file_size(fname);
+ fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
+ PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
- if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr)
- {
- DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
- fsp->mmap_ptr = NULL;
- }
+ if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr)
+ {
+ DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
+ fsp->mmap_ptr = NULL;
}
+ }
#endif
}
if (*lp_magicoutput(SNUM(cnum)))
pstrcpy(magic_output,lp_magicoutput(SNUM(cnum)));
else
- sprintf(magic_output,"%s.out",fname);
+ slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
chmod(fname,0755);
ret = smbrun(fname,magic_output,False);
}
}
+/****************************************************************************
+ Common code to close a file or a directory.
+****************************************************************************/
+
+static void close_filestruct(files_struct *fs_p)
+{
+ int cnum = fs_p->cnum;
+
+ fs_p->reserved = False;
+ fs_p->open = False;
+ fs_p->is_directory = False;
+
+ Connections[cnum].num_files_open--;
+ if(fs_p->wbmpx_ptr)
+ {
+ free((char *)fs_p->wbmpx_ptr);
+ fs_p->wbmpx_ptr = NULL;
+ }
+
+#if USE_MMAP
+ if(fs_p->mmap_ptr)
+ {
+ munmap(fs_p->mmap_ptr,fs_p->mmap_size);
+ fs_p->mmap_ptr = NULL;
+ }
+#endif
+}
/****************************************************************************
-close a file - possibly invalidating the read prediction
+ Close a file - possibly invalidating the read prediction.
-If normal_close is 1 then this came from a normal SMBclose (or equivalent)
-operation otherwise it came as the result of some other operation such as
-the closing of the connection. In the latter case printing and
-magic scripts are not run
+ If normal_close is 1 then this came from a normal SMBclose (or equivalent)
+ operation otherwise it came as the result of some other operation such as
+ the closing of the connection. In the latter case printing and
+ magic scripts are not run.
****************************************************************************/
+
void close_file(int fnum, BOOL normal_close)
{
files_struct *fs_p = &Files[fnum];
uint32 inode = fs_p->fd_ptr->inode;
int token;
- Files[fnum].reserved = False;
+ close_filestruct(fs_p);
#if USE_READ_PREDICTION
invalidate_read_prediction(fs_p->fd_ptr->fd);
#endif
- fs_p->open = False;
- Connections[cnum].num_files_open--;
- if(fs_p->wbmpx_ptr)
- {
- free((char *)fs_p->wbmpx_ptr);
- fs_p->wbmpx_ptr = NULL;
- }
-
-#if USE_MMAP
- if(fs_p->mmap_ptr)
- {
- munmap(fs_p->mmap_ptr,fs_p->mmap_size);
- fs_p->mmap_ptr = NULL;
- }
-#endif
-
if (lp_share_modes(SNUM(cnum)))
{
lock_share_entry( cnum, dev, inode, &token);
DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
timestring(),Connections[cnum].user,fs_p->name,
Connections[cnum].num_files_open));
+
+ if (fs_p->name) {
+ string_free(&fs_p->name);
+ }
+
+ /* we will catch bugs faster by zeroing this structure */
+ memset(fs_p, 0, sizeof(*fs_p));
+}
+
+/****************************************************************************
+ Close a directory opened by an NT SMB call.
+****************************************************************************/
+
+void close_directory(int fnum)
+{
+ files_struct *fs_p = &Files[fnum];
+
+ /*
+ * Do the code common to files and directories.
+ */
+ close_filestruct(fs_p);
+
+ if (fs_p->name) {
+ string_free(&fs_p->name);
+ }
+
+ /* we will catch bugs faster by zeroing this structure */
+ memset(fs_p, 0, sizeof(*fs_p));
+}
+
+/****************************************************************************
+ Open a directory from an NT SMB call.
+****************************************************************************/
+
+void open_directory(int fnum,int cnum,char *fname, int *action)
+{
+ extern struct current_user current_user;
+ files_struct *fsp = &Files[fnum];
+
+ fsp->fd_ptr = NULL;
+ Connections[cnum].num_files_open++;
+ fsp->mode = 0;
+ GetTimeOfDay(&fsp->open_time);
+ fsp->vuid = current_user.vuid;
+ fsp->size = 0;
+ fsp->pos = -1;
+ fsp->open = True;
+ fsp->mmap_ptr = NULL;
+ fsp->mmap_size = 0;
+ fsp->can_lock = True;
+ fsp->can_read = False;
+ fsp->can_write = False;
+ fsp->share_mode = 0;
+ fsp->print_file = False;
+ fsp->modified = False;
+ fsp->granted_oplock = False;
+ fsp->sent_oplock_break = False;
+ fsp->is_directory = True;
+ fsp->cnum = cnum;
+ /*
+ * Note that the file name here is the *untranslated* name
+ * ie. it is still in the DOS codepage sent from the client.
+ * All use of this filename will pass though the sys_xxxx
+ * functions which will do the dos_to_unix translation before
+ * mapping into a UNIX filename. JRA.
+ */
+ string_set(&fsp->name,fname);
+ fsp->wbmpx_ptr = NULL;
+
+ *action = FILE_WAS_OPENED;
}
enum {AFAIL,AREAD,AWRITE,AALL};
if(!lp_share_modes(SNUM(cnum)))
return True;
- if (stat(fname,&sbuf) == -1) return(True);
+ if (sys_stat(fname,&sbuf) == -1) return(True);
dev = (uint32)sbuf.st_dev;
inode = (uint32)sbuf.st_ino;
BOOL *share_locked)
{
if (Files[fnum].can_write){
- if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
+ if (is_locked(fnum,cnum,0x3FFFFFFF,0,F_WRLCK)){
/* If share modes are in force for this connection we
have the share entry locked. Unlock it before closing. */
if (*share_locked && lp_share_modes(SNUM(cnum)))
{
unix_ERR_class = ERRDOS;
/* OS/2 Workplace shell fix may be main code stream in a later release. */
-#ifdef OS2_WPS_FIX
+#if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */
unix_ERR_code = ERRcannotopen;
#else /* OS2_WPS_FIX */
unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
flags = O_RDONLY;
break;
}
+
+#if defined(O_SYNC)
+ if (share_mode&(1<<14)) {
+ flags2 |= O_SYNC;
+ }
+#endif /* O_SYNC */
if (flags != O_RDONLY && file_existed &&
(!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
if (action)
{
- if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
- if (!file_existed) *action = 2;
- if (file_existed && (flags2 & O_TRUNC)) *action = 3;
+ if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED;
+ if (!file_existed) *action = FILE_WAS_CREATED;
+ if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN;
}
/* We must create the share mode entry before truncate as
truncate can fail due to locking and have to close the
#if USE_MMAP
if (Files[fnum].mmap_ptr)
{
- int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
+ int num = (Files[fnum].mmap_size > pos) ? (Files[fnum].mmap_size - pos) : -1;
+ num = MIN(n,num);
if (num > 0)
{
memcpy(data,Files[fnum].mmap_ptr+pos,num);
if (iService < 0)
{
char *phome_dir = get_home_dir(service);
+
+ if(!phome_dir)
+ {
+ /*
+ * Try mapping the servicename, it may
+ * be a Windows to unix mapped user name.
+ */
+ if(map_username(service))
+ phome_dir = get_home_dir(service);
+ }
+
DEBUG(3,("checking for home directory %s gave %s\n",service,
- phome_dir?phome_dir:"(NULL)"));
+ phome_dir?phome_dir:"(NULL)"));
+
if (phome_dir)
{
- int iHomeService;
- if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
- {
- lp_add_home(service,iHomeService,phome_dir);
- iService = lp_servicenumber(service);
- }
+ int iHomeService;
+ if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
+ {
+ lp_add_home(service,iHomeService,phome_dir);
+ iService = lp_servicenumber(service);
+ }
}
}
/* just possibly it's a default service? */
if (iService < 0)
+ {
+ char *pdefservice = lp_defaultservice();
+ if (pdefservice && *pdefservice && !strequal(pdefservice,service))
{
- char *defservice = lp_defaultservice();
- if (defservice && *defservice && !strequal(defservice,service)) {
- iService = find_service(defservice);
- if (iService >= 0) {
- string_sub(service,"_","/");
- iService = lp_add_service(service,iService);
- }
+ /*
+ * We need to do a local copy here as lp_defaultservice()
+ * returns one of the rotating lp_string buffers that
+ * could get overwritten by the recursive find_service() call
+ * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
+ */
+ pstring defservice;
+ pstrcpy(defservice, pdefservice);
+ iService = find_service(defservice);
+ if (iService >= 0)
+ {
+ string_sub(service,"_","/");
+ iService = lp_add_service(service,iService);
}
}
+ }
if (iService >= 0)
- if (!VALID_SNUM(iService))
- {
- DEBUG(0,("Invalid snum %d for %s\n",iService,service));
- iService = -1;
- }
+ if (!VALID_SNUM(iService))
+ {
+ DEBUG(0,("Invalid snum %d for %s\n",iService,service));
+ iService = -1;
+ }
if (iService < 0)
- DEBUG(3,("find_service() failed to find service %s\n", service));
+ DEBUG(3,("find_service() failed to find service %s\n", service));
return (iService);
}
int ecode=def_code;
int i=0;
- if (unix_ERR_class != SUCCESS)
+ if (unix_ERR_class != SMB_SUCCESS)
{
eclass = unix_ERR_class;
ecode = unix_ERR_code;
- unix_ERR_class = SUCCESS;
+ unix_ERR_class = SMB_SUCCESS;
unix_ERR_code = 0;
}
else
int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
{
int outsize = set_message(outbuf,0,0,True);
- int cmd;
- cmd = CVAL(inbuf,smb_com);
-
- CVAL(outbuf,smb_rcls) = error_class;
- SSVAL(outbuf,smb_err,error_code);
-
- DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
+ int cmd = CVAL(inbuf,smb_com);
+ int flgs2 = SVAL(outbuf,smb_flg2);
+
+ if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES)
+ {
+ SIVAL(outbuf,smb_rcls,error_code);
+
+ DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n",
+ timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf)));
+ }
+ else
+ {
+ CVAL(outbuf,smb_rcls) = error_class;
+ SSVAL(outbuf,smb_err,error_code);
+ DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
timestring(),
line,
(int)CVAL(inbuf,smb_com),
error_class,
error_code));
+ }
+
if (errno != 0)
DEBUG(3,("error string = %s\n",strerror(errno)));
/****************************************************************************
this prevents zombie child processes
****************************************************************************/
-static int sig_cld()
+static int sig_cld(void)
{
static int depth = 0;
if (depth != 0)
/****************************************************************************
this is called when the client exits abruptly
**************************************************************************/
-static int sig_pipe()
+static int sig_pipe(void)
{
struct cli_state *cli;
BlockSignals(True,SIGPIPE);
return True;
}
close(Client); /* The parent doesn't need this socket */
+
+ /*
+ * Force parent to check log size after spawning child.
+ * Fix from klausr@ITAP.Physik.Uni-Stuttgart.De.
+ * The parent smbd will log to logserver.smb.
+ * It writes only two messages for each child
+ * started/finished. But each child writes, say, 50 messages also in
+ * logserver.smb, begining with the debug_count of the parent, before the
+ * child opens its own log file logserver.client. In a worst case
+ * scenario the size of logserver.smb would be checked after about
+ * 50*50=2500 messages (ca. 100kb).
+ */
+ force_check_log_size();
+
#endif /* NO_FORK_DEBUG */
} /* end for num */
} /* end while 1 */
static void process_smb(char *inbuf, char *outbuf)
{
extern int Client;
+#ifdef USE_SSL
+ extern BOOL sslEnabled; /* don't use function for performance reasons */
+ static int sslConnected = 0;
+#endif /* USE_SSL */
static int trans_num;
int msg_type = CVAL(inbuf,0);
int32 len = smb_len(inbuf);
DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
+#ifdef USE_SSL
+ if(sslEnabled && !sslConnected){
+ sslConnected = sslutil_negotiate_ssl(Client, msg_type);
+ if(sslConnected < 0){ /* an error occured */
+ exit_server("SSL negotiation failed");
+ }else if(sslConnected){
+ trans_num++;
+ return;
+ }
+ }
+#endif /* USE_SSL */
+
#ifdef WITH_VTP
if(trans_num == 1 && VT_Check(inbuf))
{
/****************************************************************************
open the oplock IPC socket communication
****************************************************************************/
-static BOOL open_oplock_ipc()
+static BOOL open_oplock_ipc(void)
{
struct sockaddr_in sock_name;
int len = sizeof(sock_name);
****************************************************************************/
BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
{
+ extern struct current_user current_user;
extern int Client;
char *inbuf = NULL;
char *outbuf = NULL;
int fnum;
time_t start_time;
BOOL shutdown_server = False;
+ int saved_cnum;
+ int saved_vuid;
+ pstring saved_dir;
DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \
global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open));
/* We need to search the file open table for the
entry containing this dev and inode, and ensure
we have an oplock on it. */
- for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++)
+ for( fnum = 0; fnum < MAX_FNUMS; fnum++)
{
if(OPEN_FNUM(fnum))
{
start_time = time(NULL);
+ /*
+ * Save the information we need to re-become the
+ * user, then unbecome the user whilst we're doing this.
+ */
+ saved_cnum = fsp->cnum;
+ saved_vuid = current_user.vuid;
+ GetWd(saved_dir);
+ unbecome_user();
+
while(OPEN_FNUM(fnum) && fsp->granted_oplock)
{
if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
}
}
+ /*
+ * Go back to being the user who requested the oplock
+ * break.
+ */
+ if(!become_user(&Connections[saved_cnum], saved_cnum, saved_vuid))
+ {
+ DEBUG(0,("%s oplock_break: unable to re-become user ! Shutting down server\n",
+ timestring()));
+ close_sockets();
+ close(oplock_sock);
+ exit_server("unable to re-become user");
+ }
+ /* Including the directory. */
+ ChDir(saved_dir);
+
/* Free the buffers we've been using to recurse. */
free(inbuf);
free(outbuf);
BOOL ret;
if (lp_loaded())
+ {
+ pstring fname;
+ pstrcpy(fname,lp_configfile());
+ if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
{
- pstring fname;
- pstrcpy(fname,lp_configfile());
- if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
- {
- pstrcpy(servicesf,fname);
- test = False;
- }
+ pstrcpy(servicesf,fname);
+ test = False;
}
+ }
reopen_logs();
}
}
- reset_mangled_stack( lp_mangledstack() );
+ reset_mangled_cache();
/* this forces service parameters to be flushed */
become_service(-1,True);
/****************************************************************************
this prevents zombie child processes
****************************************************************************/
-static int sig_hup()
+static BOOL reload_after_sighup = False;
+
+static int sig_hup(void)
{
BlockSignals(True,SIGHUP);
DEBUG(0,("Got SIGHUP\n"));
- reload_services(False);
+
+ /*
+ * Fix from <branko.cibej@hermes.si> here.
+ * We used to reload in the signal handler - this
+ * is a *BIG* no-no.
+ */
+
+ reload_after_sighup = True;
#ifndef DONT_REINSTALL_SIG
signal(SIGHUP,SIGNAL_CAST sig_hup);
#endif
snum = find_service(service);
if (snum < 0)
{
+ extern int Client;
if (strequal(service,"IPC$"))
{
DEBUG(3,("%s refusing IPC connection\n",timestring()));
return(-3);
}
- DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
+ DEBUG(0,("%s %s (%s) couldn't find service %s\n",timestring(),remote_machine,client_addr(Client),service));
return(-2);
}
if (*user && Get_Pwnam(user,True))
return(make_connection(user,user,password,pwlen,dev,vuid));
- if (validated_username(vuid))
- {
- strcpy(user,validated_username(vuid));
- return(make_connection(user,user,password,pwlen,dev,vuid));
- }
+ if(lp_security() != SEC_SHARE)
+ {
+ if (validated_username(vuid))
+ {
+ pstrcpy(user,validated_username(vuid));
+ return(make_connection(user,user,password,pwlen,dev,vuid));
+ }
+ }
+ else
+ {
+ /*
+ * Security = share. Try with sesssetup_user as the username.
+ */
+ if(*sesssetup_user)
+ {
+ pstrcpy(user,sesssetup_user);
+ return(make_connection(user,user,password,pwlen,dev,vuid));
+ }
+ }
}
if (!lp_snum_ok(snum) || !check_access(snum)) {
/* you can only connect to the IPC$ service as an ipc device */
if (strequal(service,"IPC$"))
- strcpy(dev,"IPC");
+ pstrcpy(dev,"IPC");
if (*dev == '?' || !*dev)
{
if (lp_print_ok(snum))
- strcpy(dev,"LPT1:");
+ pstrcpy(dev,"LPT1:");
else
- strcpy(dev,"A:");
+ pstrcpy(dev,"A:");
}
/* if the request is as a printer and you can't print then refuse */
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;
+ first_file = (getpid() ^ (int)time(NULL)) % MAX_FNUMS;
if (first_file == 0) first_file = 1;
}
- if (first_file >= MAX_OPEN_FILES)
+ if (first_file >= MAX_FNUMS)
first_file = 1;
- for (i=first_file;i<MAX_OPEN_FILES;i++)
+ for (i=first_file;i<MAX_FNUMS;i++)
if (!Files[i].open && !Files[i].reserved) {
memset(&Files[i], 0, sizeof(Files[i]));
first_file = i+1;
* files batch oplocked for quite a long time
* after they have finished with them.
*/
- for (i=first_file;i<MAX_OPEN_FILES;i++) {
+ for (i=first_file;i<MAX_FNUMS;i++) {
if(attempt_close_oplocked_file( &Files[i])) {
memset(&Files[i], 0, sizeof(Files[i]));
first_file = i+1;
}
}
- for (i=1;i<MAX_OPEN_FILES;i++) {
+ for (i=1;i<MAX_FNUMS;i++) {
if(attempt_close_oplocked_file( &Files[i])) {
memset(&Files[i], 0, sizeof(Files[i]));
first_file = i+1;
int reply_nt1(char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
- int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS;
+ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS
+#ifdef HAVE_NT_SMBS
+ |CAP_NT_SMBS
+#endif /* HAVE_NT_SMBS */
+ ;
+
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
/* decide where (if) to put the encryption challenge, and
follow it with the OEM'd domain name
*/
- data_len = crypt_len + strlen(myworkgroup) + 1;
+ data_len = crypt_len + strlen(global_myworkgroup) + 1;
set_message(outbuf,17,data_len,True);
- strcpy(smb_buf(outbuf)+crypt_len, myworkgroup);
+ pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup);
CVAL(outbuf,smb_vwv1) = secword;
SSVALS(outbuf,smb_vwv16+1,crypt_len);
/****************************************************************************
reply to a negprot
****************************************************************************/
-static int reply_negprot(char *inbuf,char *outbuf)
+static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = set_message(outbuf,1,0,True);
int Index=0;
/* a special case to stop password server loops */
if (Index == 1 && strequal(remote_machine,myhostname) &&
- lp_security()==SEC_SERVER)
+ (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
exit_server("Password server loop!");
/* Check for protocols, most desirable first */
static void close_open_files(int cnum)
{
int i;
- for (i=0;i<MAX_OPEN_FILES;i++)
+ for (i=0;i<MAX_FNUMS;i++)
if( Files[i].cnum == cnum && Files[i].open) {
- close_file(i,False);
+ if(Files[i].is_directory)
+ close_directory(i);
+ else
+ close_file(i,False);
}
}
if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid))
{
pstring cmd;
- strcpy(cmd,lp_postexec(SNUM(cnum)));
+ pstrcpy(cmd,lp_postexec(SNUM(cnum)));
standard_sub(cnum,cmd);
smbrun(cmd,NULL,False);
unbecome_user();
if (*lp_rootpostexec(SNUM(cnum)))
{
pstring cmd;
- strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
+ pstrcpy(cmd,lp_rootpostexec(SNUM(cnum)));
standard_sub(cnum,cmd);
smbrun(cmd,NULL,False);
}
pstring dname;
pstrcpy(dname,debugf);
if ((p=strrchr(dname,'/'))) *p=0;
- strcat(dname,"/corefiles");
+ pstrcat(dname,"/corefiles");
mkdir(dname,0700);
sys_chown(dname,getuid(),getgid());
chmod(dname,0700);
case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
/*
* Patch from jkf@soton.ac.uk
- * Left the %N (NIS server name) in standard_sub_basic as it
- * is a feature for logon servers, hence uses the username.
+ * Left the %N (NIS server name) in standard_sub_basic as it
+ * is a feature for logon servers, hence uses the username.
* The %p (NIS server path) code is here as it is used
* instead of the default "path =" string in [homes] and so
* needs the service name, not the username.
{
int code;
char *name;
- int (*fn)();
+ int (*fn)(char *, char *, int, int);
int flags;
#if PROFILING
unsigned long time;
/* LANMAN2.0 PROTOCOL FOLLOWS */
{SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
{SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
- {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK },
+ {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER },
{SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
+#ifdef HAVE_NT_SMBS
+ /* NT PROTOCOL FOLLOWS */
+ {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
+ {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
+ {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
+ {SMBntcancel, "SMBntcancel", reply_ntcancel, AS_USER },
+#endif /* HAVE_NT_SMBS */
+
/* messaging routines */
{SMBsends,"SMBsends",reply_sends,AS_GUEST},
{SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
/* make sure this is an SMB packet */
if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
- {
- DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
- return(-1);
- }
+ {
+ DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
+ return(-1);
+ }
for (match=0;match<num_smb_messages;match++)
if (smb_messages[match].code == type)
break;
if (match == num_smb_messages)
- {
- DEBUG(0,("Unknown message type %d!\n",type));
- outsize = reply_unknown(inbuf,outbuf);
- }
+ {
+ DEBUG(0,("Unknown message type %d!\n",type));
+ outsize = reply_unknown(inbuf,outbuf);
+ }
else
+ {
+ DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
+
+ if(global_oplock_break && (smb_messages[match].flags & QUEUE_IN_OPLOCK))
{
- DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
+ /*
+ * Queue this message as we are the process of an oplock break.
+ */
- if(global_oplock_break && (smb_messages[match].flags & QUEUE_IN_OPLOCK))
- {
- /*
- * Queue this message as we are the process of an oplock break.
- */
+ DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n",
+ timestring() ));
- DEBUG(2,("%s: switch_message: queueing message due to being in oplock break state.\n",
- timestring() ));
+ push_smb_message( inbuf, size);
+ return -1;
+ }
- push_smb_message( inbuf, size);
- return -1;
- }
+ if (smb_messages[match].fn)
+ {
+ int cnum = SVAL(inbuf,smb_tid);
+ int flags = smb_messages[match].flags;
+ static uint16 last_session_tag = UID_FIELD_INVALID;
+ /* In share mode security we must ignore the vuid. */
+ uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
+ /* Ensure this value is replaced in the incoming packet. */
+ SSVAL(inbuf,smb_uid,session_tag);
- if (smb_messages[match].fn)
- {
- int cnum = SVAL(inbuf,smb_tid);
- int flags = smb_messages[match].flags;
- /* In share mode security we must ignore the vuid. */
- uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
- /* Ensure this value is replaced in the incoming packet. */
- SSVAL(inbuf,smb_uid,session_tag);
-
- /* does this protocol need to be run as root? */
- if (!(flags & AS_USER))
- unbecome_user();
-
- /* does this protocol need to be run as the connected user? */
- if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) {
- if (flags & AS_GUEST)
- flags &= ~AS_USER;
- else
- return(ERROR(ERRSRV,ERRinvnid));
- }
- /* this code is to work around a bug is MS client 3 without
- introducing a security hole - it needs to be able to do
- print queue checks as guest if it isn't logged in properly */
- if (flags & AS_USER)
- flags &= ~AS_GUEST;
+ /*
+ * Ensure the correct username is in sesssetup_user.
+ * This is a really ugly bugfix for problems with
+ * multiple session_setup_and_X's being done and
+ * allowing %U and %G substitutions to work correctly.
+ * There is a reason this code is done here, don't
+ * move it unless you know what you're doing... :-).
+ * JRA.
+ */
+ if(session_tag != last_session_tag ) {
+ user_struct *vuser = NULL;
+
+ last_session_tag = session_tag;
+ if(session_tag != UID_FIELD_INVALID)
+ vuser = get_valid_user_struct(session_tag);
+ if(vuser != NULL)
+ pstrcpy( sesssetup_user, vuser->requested_name);
+ }
- /* does it need write permission? */
- if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
- return(ERROR(ERRSRV,ERRaccess));
+ /* does this protocol need to be run as root? */
+ if (!(flags & AS_USER))
+ unbecome_user();
- /* ipc services are limited */
- if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
- return(ERROR(ERRSRV,ERRaccess));
+ /* does this protocol need to be run as the connected user? */
+ if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) {
+ if (flags & AS_GUEST)
+ flags &= ~AS_USER;
+ else
+ return(ERROR(ERRSRV,ERRinvnid));
+ }
+ /* this code is to work around a bug is MS client 3 without
+ introducing a security hole - it needs to be able to do
+ print queue checks as guest if it isn't logged in properly */
+ if (flags & AS_USER)
+ flags &= ~AS_GUEST;
- /* load service specific parameters */
- if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
- return(ERROR(ERRSRV,ERRaccess));
+ /* does it need write permission? */
+ if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
+ return(ERROR(ERRSRV,ERRaccess));
- /* does this protocol need to be run as guest? */
- if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
- return(ERROR(ERRSRV,ERRaccess));
+ /* ipc services are limited */
+ if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
+ return(ERROR(ERRSRV,ERRaccess));
- last_inbuf = inbuf;
+ /* load service specific parameters */
+ if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
+ return(ERROR(ERRSRV,ERRaccess));
- outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
- }
- else
- {
- outsize = reply_unknown(inbuf,outbuf);
- }
+ /* does this protocol need to be run as guest? */
+ if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
+ return(ERROR(ERRSRV,ERRaccess));
+
+ last_inbuf = inbuf;
+
+ outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
}
+ else
+ {
+ outsize = reply_unknown(inbuf,outbuf);
+ }
+ }
#if PROFILING
GetTimeOfDay(&msg_end_time);
if (!(smb_messages[match].flags & TIME_INIT))
- {
- smb_messages[match].time = 0;
- smb_messages[match].flags |= TIME_INIT;
- }
+ {
+ smb_messages[match].time = 0;
+ smb_messages[match].flags |= TIME_INIT;
+ }
{
unsigned long this_time =
(msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
- (msg_end_time.tv_usec - msg_start_time.tv_usec);
+ (msg_end_time.tv_usec - msg_start_time.tv_usec);
smb_messages[match].time += this_time;
total_time += this_time;
}
DEBUG(2,("TIME %s %d usecs %g pct\n",
- smb_fn_name(type),smb_messages[match].time,
- (100.0*smb_messages[match].time) / total_time));
+ smb_fn_name(type),smb_messages[match].time,
+ (100.0*smb_messages[match].time) / total_time));
#endif
return(outsize);
CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
memcpy(outbuf2+4,inbuf2+4,4);
- CVAL(outbuf2,smb_rcls) = SUCCESS;
+ CVAL(outbuf2,smb_rcls) = SMB_SUCCESS;
CVAL(outbuf2,smb_reh) = 0;
CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
means a reply */
SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
- SSVAL(outbuf2,smb_err,SUCCESS);
+ SSVAL(outbuf2,smb_err,SMB_SUCCESS);
SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
set_message(outbuf,0,0,True);
memcpy(outbuf+4,inbuf+4,4);
- CVAL(outbuf,smb_rcls) = SUCCESS;
+ CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
CVAL(outbuf,smb_reh) = 0;
CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
means a reply */
SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
- SSVAL(outbuf,smb_err,SUCCESS);
+ SSVAL(outbuf,smb_err,SMB_SUCCESS);
SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
reload_services(True);
}
+ /*
+ * If reload_after_sighup == True then we got a SIGHUP
+ * and are being asked to reload. Fix from <branko.cibej@hermes.si>
+ */
+
+ if (reload_after_sighup)
+ {
+ DEBUG(0,("Reloading services after SIGHUP\n"));
+ reload_services(False);
+ reload_after_sighup = False;
+ }
+
/* automatic timeout if all connections are closed */
if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT)
{
DEBUG(2,("%s Closing idle connection 2\n",timestring()));
return;
}
+
+ if(global_machine_pasword_needs_changing)
+ {
+ unsigned char trust_passwd_hash[16];
+ time_t lct;
+ pstring remote_machine_list;
+
+ /*
+ * We're in domain level security, and the code that
+ * read the machine password flagged that the machine
+ * password needs changing.
+ */
+
+ /*
+ * First, open the machine password file with an exclusive lock.
+ */
+
+ if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
+ DEBUG(0,("process: unable to open the machine account password file for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ continue;
+ }
+
+ if(!get_trust_account_password( trust_passwd_hash, &lct)) {
+ DEBUG(0,("process: unable to read the machine account password for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+ trust_password_unlock();
+ continue;
+ }
+
+ /*
+ * Make sure someone else hasn't already done this.
+ */
+
+ if(t < lct + lp_machine_password_timeout()) {
+ trust_password_unlock();
+ global_machine_pasword_needs_changing = False;
+ continue;
+ }
+
+ pstrcpy(remote_machine_list, lp_passwordserver());
+
+ change_trust_account_password( global_myworkgroup, remote_machine_list);
+ trust_password_unlock();
+ global_machine_pasword_needs_changing = False;
+ }
}
if(got_smb)
int i;
get_myname(myhostname,NULL);
+ /*
+ * Set the machine NETBIOS name if not already
+ * set from the config file.
+ */
+
+ if (!*global_myname)
+ {
+ char *p;
+ fstrcpy( global_myname, myhostname );
+ p = strchr( global_myname, '.' );
+ if (p)
+ *p = 0;
+ }
+ strupper( global_myname );
+
for (i=0;i<MAX_CONNECTIONS;i++)
{
Connections[i].open = False;
string_init(&Connections[i].origpath,"");
}
- for (i=0;i<MAX_OPEN_FILES;i++)
+ for (i=0;i<MAX_FNUMS;i++)
{
Files[i].open = False;
string_init(&Files[i].name,"");
-
}
for (i=0;i<MAX_OPEN_FILES;i++)
TimeInit();
- strcpy(debugf,SMBLOGFILE);
+ pstrcpy(debugf,SMBLOGFILE);
- strcpy(remote_machine, "smb");
+ pstrcpy(remote_machine, "smb");
setup_logging(argv[0],False);
seteuid(0);
#endif
- fault_setup(exit_server);
+ fault_setup((void (*)(void *))exit_server);
signal(SIGTERM , SIGNAL_CAST dflt_sig);
/* we want total control over the permissions on created files,
switch (opt)
{
case 'O':
- strcpy(user_socket_options,optarg);
+ pstrcpy(user_socket_options,optarg);
break;
case 'i':
- strcpy(scope,optarg);
+ pstrcpy(scope,optarg);
break;
case 'P':
{
}
break;
case 's':
- strcpy(servicesf,optarg);
+ pstrcpy(servicesf,optarg);
break;
case 'l':
- strcpy(debugf,optarg);
+ pstrcpy(debugf,optarg);
break;
case 'a':
{
if (!reload_services(False))
return(-1);
+#ifdef USE_SSL
+ {
+ extern BOOL sslEnabled;
+ sslEnabled = lp_ssl_enabled();
+ if(sslEnabled)
+ sslutil_init(True);
+ }
+#endif /* USE_SSL */
+
codepage_initialise(lp_client_code_page());
- strcpy(myworkgroup, lp_workgroup());
+ pstrcpy(global_myworkgroup, lp_workgroup());
+
+ if(!pdb_generate_machine_sid())
+ {
+ DEBUG(0,("ERROR: Samba cannot get a machine SID.\n"));
+ exit(1);
+ }
#ifndef NO_SIGNAL_TEST
signal(SIGHUP,SIGNAL_CAST sig_hup);
if (!locking_init(0))
exit(1);
+ if(!initialize_password_db())
+ exit(1);
+
/* possibly reload the services file. */
reload_services(True);
exit_server("normal exit");
return(0);
}
-
-