2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
36 BOOL share_mode_pending = False;
38 /* the last message the was processed */
39 int last_message = -1;
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
45 extern int DEBUGLEVEL;
46 extern int case_default;
47 extern BOOL case_sensitive;
48 extern BOOL case_preserve;
49 extern BOOL use_mangled_map;
50 extern BOOL short_case_preserve;
51 extern BOOL case_mangle;
52 extern time_t smb_last_time;
54 extern int smb_read_error;
56 extern pstring user_socket_options;
58 connection_struct Connections[MAX_CONNECTIONS];
59 files_struct Files[MAX_OPEN_FILES];
62 * Indirection for file fd's. Needed as POSIX locking
63 * is based on file/process, not fd/process.
65 file_fd_struct FileFd[MAX_OPEN_FILES];
66 int max_file_fd_used = 0;
70 int maxxmit = BUFFER_SIZE;
72 /* a fnum to use when chaining */
75 /* number of open connections */
76 static int num_connections_open = 0;
78 extern fstring remote_machine;
82 /* these can be set by some functions to override the error codes */
83 int unix_ERR_class=SUCCESS;
87 extern int extra_time_offset;
89 extern pstring myhostname;
91 static int find_free_connection(int hash);
93 /* for readability... */
94 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
95 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
96 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
97 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
98 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
100 /****************************************************************************
101 when exiting, take the whole family
102 ****************************************************************************/
105 exit_server("caught signal");
107 /****************************************************************************
108 Send a SIGTERM to our process group.
109 *****************************************************************************/
112 if(am_parent) kill(0,SIGTERM);
115 /****************************************************************************
116 change a dos mode to a unix mode
117 base permission for files:
118 everybody gets read bit set
119 dos readonly is represented in unix by removing everyone's write bit
120 dos archive is represented in unix by the user's execute bit
121 dos system is represented in unix by the group's execute bit
122 dos hidden is represented in unix by the other's execute bit
123 base permission for directories:
124 dos directory is represented in unix by unix's dir bit and the exec bit
125 ****************************************************************************/
126 mode_t unix_mode(int cnum,int dosmode)
128 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
130 if ( !IS_DOS_READONLY(dosmode) )
131 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
133 if (IS_DOS_DIR(dosmode))
134 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
136 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
139 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
142 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
145 result &= CREATE_MODE(cnum);
150 /****************************************************************************
151 change a unix mode to a dos mode
152 ****************************************************************************/
153 int dos_mode(int cnum,char *path,struct stat *sbuf)
156 extern struct current_user current_user;
158 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
159 if (!((sbuf->st_mode & S_IWOTH) ||
160 Connections[cnum].admin_user ||
161 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
162 ((sbuf->st_mode & S_IWGRP) &&
163 in_group(sbuf->st_gid,current_user.gid,
164 current_user.ngroups,current_user.igroups))))
167 if ((sbuf->st_mode & S_IWUSR) == 0)
171 if ((sbuf->st_mode & S_IXUSR) != 0)
174 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
177 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
180 if (S_ISDIR(sbuf->st_mode))
181 result = aDIR | (result & aRONLY);
184 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
188 /* hide files with a name starting with a . */
189 if (lp_hide_dot_files(SNUM(cnum)))
191 char *p = strrchr(path,'/');
197 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
205 /*******************************************************************
206 chmod a file - but preserve some bits
207 ********************************************************************/
208 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
217 if (sys_stat(fname,st)) return(-1);
220 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
222 if (dos_mode(cnum,fname,st) == dosmode) return(0);
224 unixmode = unix_mode(cnum,dosmode);
226 /* preserve the s bits */
227 mask |= (S_ISUID | S_ISGID);
229 /* preserve the t bit */
234 /* possibly preserve the x bits */
235 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
236 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
237 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
239 unixmode |= (st->st_mode & mask);
241 /* if we previously had any r bits set then leave them alone */
242 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
243 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
247 /* if we previously had any w bits set then leave them alone
248 if the new mode is not rdonly */
249 if (!IS_DOS_READONLY(dosmode) &&
250 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
251 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
255 return(sys_chmod(fname,unixmode));
259 /****************************************************************************
260 check if two filenames are equal
262 this needs to be careful about whether we are case sensitive
263 ****************************************************************************/
264 static BOOL fname_equal(char *name1, char *name2)
266 int l1 = strlen(name1);
267 int l2 = strlen(name2);
269 /* handle filenames ending in a single dot */
270 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
274 ret = fname_equal(name1,name2);
279 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
283 ret = fname_equal(name1,name2);
288 /* now normal filename handling */
290 return(strcmp(name1,name2) == 0);
292 return(strequal(name1,name2));
296 /****************************************************************************
297 mangle the 2nd name and check if it is then equal to the first name
298 ****************************************************************************/
299 static BOOL mangled_equal(char *name1, char *name2)
306 strcpy(tmpname,name2);
307 mangle_name_83(tmpname);
309 return(strequal(name1,tmpname));
313 /****************************************************************************
314 scan a directory to find a filename, matching without case sensitivity
316 If the name looks like a mangled name then try via the mangling functions
317 ****************************************************************************/
318 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
325 mangled = is_mangled(name);
327 /* handle null paths */
331 if (docache && (dname = DirCacheCheck(path,name,snum))) {
337 check_mangled_stack(name);
339 /* open the directory */
340 if (!(cur_dir = OpenDir(path)))
342 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
346 /* now scan for matching names */
347 while ((dname = ReadDirName(cur_dir)))
350 (strequal(dname,".") || strequal(dname,"..")))
354 if (!name_map_mangle(name2,False,snum)) continue;
356 if ((mangled && mangled_equal(name,name2))
357 || fname_equal(name, name2))
359 /* we've found the file, change it's name and return */
360 if (docache) DirCacheAdd(path,name,dname,snum);
371 /****************************************************************************
372 This routine is called to convert names from the dos namespace to unix
373 namespace. It needs to handle any case conversions, mangling, format
376 We assume that we have already done a chdir() to the right "root" directory
379 The function will return False if some part of the name except for the last
380 part cannot be resolved
382 If the saved_last_component != 0, then the unmodified last component
383 of the pathname is returned there. This is used in an exceptional
384 case in reply_mv (so far). If saved_last_component == 0 then nothing
386 ****************************************************************************/
387 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
394 if(saved_last_component)
395 *saved_last_component = 0;
397 /* convert to basic unix format - removing \ chars and cleaning it up */
399 unix_clean_name(name);
401 if (!case_sensitive &&
402 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
405 /* names must be relative to the root of the service - trim any leading /.
406 also trim trailing /'s */
407 trim_string(name,"/","/");
409 /* check if it's a printer file */
410 if (Connections[cnum].printer)
412 if ((! *name) || strchr(name,'/') || !is_8_3(name))
416 sprintf(name2,"%.6s.XXXXXX",remote_machine);
417 /* sanitise the name */
418 for (s=name2 ; *s ; s++)
419 if (!issafe(*s)) *s = '_';
420 strcpy(name,(char *)mktemp(name2));
426 * Ensure saved_last_component is valid even if file exists.
428 if(saved_last_component) {
429 end = strrchr(name, '/');
431 strcpy(saved_last_component, end + 1);
433 strcpy(saved_last_component, name);
436 /* stat the name - if it exists then we are all done! */
437 if (sys_stat(name,&st) == 0)
440 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
442 /* a special case - if we don't have any mangling chars and are case
443 sensitive then searching won't help */
444 if (case_sensitive && !is_mangled(name) &&
445 !lp_strip_dot() && !use_mangled_map)
448 /* now we need to recursively match the name against the real
449 directory structure */
452 while (strncmp(start,"./",2) == 0)
455 /* now match each part of the path name separately, trying the names
456 as is first, then trying to scan the directory for matching names */
457 for (;start;start = (end?end+1:(char *)NULL))
459 /* pinpoint the end of this section of the filename */
460 end = strchr(start, '/');
462 /* chop the name at this point */
465 if(saved_last_component != 0)
466 strcpy(saved_last_component, end ? end + 1 : start);
468 /* check if the name exists up to this point */
469 if (sys_stat(name, &st) == 0)
471 /* it exists. it must either be a directory or this must be
472 the last part of the path for it to be OK */
473 if (end && !(st.st_mode & S_IFDIR))
475 /* an intermediate part of the name isn't a directory */
476 DEBUG(5,("Not a dir %s\n",start));
487 /* remember the rest of the pathname so it can be restored
489 if (end) strcpy(rest,end+1);
491 /* try to find this part of the path in the directory */
492 if (strchr(start,'?') || strchr(start,'*') ||
493 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
497 /* an intermediate part of the name can't be found */
498 DEBUG(5,("Intermediate not found %s\n",start));
503 /* just the last part of the name doesn't exist */
504 /* we may need to strupper() or strlower() it in case
505 this conversion is being used for file creation
507 /* if the filename is of mixed case then don't normalise it */
508 if (!case_preserve &&
509 (!strhasupper(start) || !strhaslower(start)))
512 /* check on the mangled stack to see if we can recover the
513 base of the filename */
514 if (is_mangled(start))
515 check_mangled_stack(start);
517 DEBUG(5,("New file %s\n",start));
521 /* restore the rest of the string */
524 strcpy(start+strlen(start)+1,rest);
525 end = start + strlen(start);
529 /* add to the dirpath that we have resolved so far */
530 if (*dirpath) strcat(dirpath,"/");
531 strcat(dirpath,start);
533 /* restore the / that we wiped out earlier */
537 /* the name has been resolved */
538 DEBUG(5,("conversion finished %s\n",name));
543 /****************************************************************************
544 normalise for DOS usage
545 ****************************************************************************/
546 static void disk_norm(int *bsize,int *dfree,int *dsize)
548 /* check if the disk is beyond the max disk size */
549 int maxdisksize = lp_maxdisksize();
551 /* convert to blocks - and don't overflow */
552 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
553 if (*dsize > maxdisksize) *dsize = maxdisksize;
554 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
559 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
564 if (*bsize > WORDMAX )
567 if (*dsize > WORDMAX)
569 if (*dfree > WORDMAX)
576 /****************************************************************************
577 return number of 1K blocks available on a path and total number
578 ****************************************************************************/
579 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
581 char *df_command = lp_dfree_command();
595 if (disk_quotas(path, bsize, dfree, dsize))
597 disk_norm(bsize,dfree,dsize);
598 return(((*bsize)/1024)*(*dfree));
603 /* possibly use system() to get the result */
604 if (df_command && *df_command)
610 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
611 sprintf(syscmd,"%s %s",df_command,path);
612 standard_sub_basic(syscmd);
614 ret = smbrun(syscmd,outfile,False);
615 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
618 FILE *f = fopen(outfile,"r");
624 fscanf(f,"%d %d %d",dsize,dfree,bsize);
628 DEBUG(0,("Can't open %s\n",outfile));
632 disk_norm(bsize,dfree,dsize);
633 return(((*bsize)/1024)*(*dfree));
637 DEBUG(1,("Warning - no statfs function\n"));
641 if (statfs(path,&fs,sizeof(fs),0) != 0)
644 if (statvfs(path, &fs))
647 if (statfs(path,&fs,sizeof(fs)) == -1)
649 if (statfs(path,&fs) == -1)
651 #endif /* USE_STATVFS */
654 DEBUG(3,("dfree call failed code errno=%d\n",errno));
658 return(((*bsize)/1024)*(*dfree));
663 *dfree = fs.fd_req.bfree;
664 *dsize = fs.fd_req.btot;
667 *bsize = fs.f_frsize;
670 /* eg: osf1 has f_fsize = fundamental filesystem block size,
671 f_bsize = optimal transfer block size (MX: 94-04-19) */
676 #endif /* USE_STATVFS */
681 *dfree = fs.f_bavail;
683 *dsize = fs.f_blocks;
686 #if defined(SCO) || defined(ISC) || defined(MIPS)
690 /* handle rediculous bsize values - some OSes are broken */
691 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
693 disk_norm(bsize,dfree,dsize);
699 DEBUG(0,("dfree seems to be broken on your system\n"));
700 *dsize = 20*1024*1024/(*bsize);
701 *dfree = MAX(1,*dfree);
703 return(((*bsize)/1024)*(*dfree));
708 /****************************************************************************
709 wrap it to get filenames right
710 ****************************************************************************/
711 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
713 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
718 /****************************************************************************
719 check a filename - possibly caling reducename
721 This is called by every routine before it allows an operation on a filename.
722 It does any final confirmation necessary to ensure that the filename is
723 a valid one for the user to access.
724 ****************************************************************************/
725 BOOL check_name(char *name,int cnum)
731 if( is_vetoed_path(name))
733 DEBUG(5,("file path name %s vetoed\n",name));
737 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
739 DEBUG(5,("check_name on %s failed\n",name));
744 /****************************************************************************
745 check a filename - possibly caling reducename
746 ****************************************************************************/
747 static void check_for_pipe(char *fname)
749 /* special case of pipe opens */
753 if (strstr(s,"pipe/"))
755 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
756 unix_ERR_class = ERRSRV;
757 unix_ERR_code = ERRaccess;
761 /****************************************************************************
762 fd support routines - attempt to do a sys_open
763 ****************************************************************************/
765 int fd_attempt_open(char *fname, int flags, int mode)
767 int fd = sys_open(fname,flags,mode);
769 /* Fix for files ending in '.' */
770 if((fd == -1) && (errno == ENOENT) &&
771 (strchr(fname,'.')==NULL))
774 fd = sys_open(fname,flags,mode);
777 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
778 if ((fd == -1) && (errno == ENAMETOOLONG))
781 char *p = strrchr(fname, '/');
783 if (p == fname) /* name is "/xxx" */
785 max_len = pathconf("/", _PC_NAME_MAX);
788 else if ((p == NULL) || (p == fname))
791 max_len = pathconf(".", _PC_NAME_MAX);
796 max_len = pathconf(fname, _PC_NAME_MAX);
800 if (strlen(p) > max_len)
802 char tmp = p[max_len];
805 if ((fd = sys_open(fname,flags,mode)) == -1)
813 /****************************************************************************
814 fd support routines - attempt to find an already open file by dev
815 and inode - increments the ref_count of the returned file_fd_struct *.
816 ****************************************************************************/
817 file_fd_struct *fd_get_already_open(struct stat *sbuf)
820 file_fd_struct *fd_ptr;
825 for(i = 0; i <= max_file_fd_used; i++) {
827 if((fd_ptr->ref_count > 0) &&
828 (((int32)sbuf->st_dev) == fd_ptr->dev) &&
829 (((int32)sbuf->st_ino) == fd_ptr->inode)) {
832 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
833 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
840 /****************************************************************************
841 fd support routines - attempt to find a empty slot in the FileFd array.
842 Increments the ref_count of the returned entry.
843 ****************************************************************************/
844 file_fd_struct *fd_get_new()
847 file_fd_struct *fd_ptr;
849 for(i = 0; i < MAX_OPEN_FILES; i++) {
851 if(fd_ptr->ref_count == 0) {
852 fd_ptr->dev = (int32)-1;
853 fd_ptr->inode = (int32)-1;
855 fd_ptr->fd_readonly = -1;
856 fd_ptr->fd_writeonly = -1;
857 fd_ptr->real_open_flags = -1;
859 /* Increment max used counter if neccessary, cuts down
860 on search time when re-using */
861 if(i > max_file_fd_used)
862 max_file_fd_used = i;
863 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
864 i, fd_ptr->dev, fd_ptr->inode));
868 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
873 /****************************************************************************
874 fd support routines - attempt to re-open an already open fd as O_RDWR.
875 Save the already open fd (we cannot close due to POSIX file locking braindamage.
876 ****************************************************************************/
878 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
880 int fd = sys_open( fname, O_RDWR, mode);
885 if(fd_ptr->real_open_flags == O_RDONLY)
886 fd_ptr->fd_readonly = fd_ptr->fd;
887 if(fd_ptr->real_open_flags == O_WRONLY)
888 fd_ptr->fd_writeonly = fd_ptr->fd;
891 fd_ptr->real_open_flags = O_RDWR;
894 /****************************************************************************
895 fd support routines - attempt to close the file referenced by this fd.
896 Decrements the ref_count and returns it.
897 ****************************************************************************/
898 int fd_attempt_close(file_fd_struct *fd_ptr)
900 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
902 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
903 fd_ptr->real_open_flags,
905 if(fd_ptr->ref_count > 0) {
907 if(fd_ptr->ref_count == 0) {
910 if(fd_ptr->fd_readonly != -1)
911 close(fd_ptr->fd_readonly);
912 if(fd_ptr->fd_writeonly != -1)
913 close(fd_ptr->fd_writeonly);
915 fd_ptr->fd_readonly = -1;
916 fd_ptr->fd_writeonly = -1;
917 fd_ptr->real_open_flags = -1;
922 return fd_ptr->ref_count;
925 /****************************************************************************
927 ****************************************************************************/
928 void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
930 extern struct current_user current_user;
933 file_fd_struct *fd_ptr;
935 Files[fnum].open = False;
936 Files[fnum].fd_ptr = 0;
939 strcpy(fname,fname1);
941 /* check permissions */
942 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
944 DEBUG(3,("Permission denied opening %s\n",fname));
945 check_for_pipe(fname);
949 /* this handles a bug in Win95 - it doesn't say to create the file when it
951 if (Connections[cnum].printer)
955 if (flags == O_WRONLY)
956 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
960 /* XXXX - is this OK?? */
961 /* this works around a utime bug but can cause other problems */
962 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
967 * Ensure we have a valid struct stat so we can search the
971 if(stat(fname, &statbuf) < 0) {
972 if(errno != ENOENT) {
973 DEBUG(3,("Error doing stat on file %s (%s)\n",
974 fname,strerror(errno)));
976 check_for_pipe(fname);
986 * Check to see if we have this file already
987 * open. If we do, just use the already open fd and increment the
988 * reference count (fd_get_already_open increments the ref_count).
990 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
992 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
994 /* File was already open. */
995 if((flags & O_CREAT) && (flags & O_EXCL)) {
1002 * If not opened O_RDWR try
1003 * and do that here - a chmod may have been done
1004 * between the last open and now.
1006 if(fd_ptr->real_open_flags != O_RDWR)
1007 fd_attempt_reopen(fname, mode, fd_ptr);
1010 * Ensure that if we wanted write access
1011 * it has been opened for write, and if we wanted read it
1012 * was open for read.
1014 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1015 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1016 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1017 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1018 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1019 check_for_pipe(fname);
1020 fd_ptr->ref_count--;
1025 * If O_TRUNC was set, ensure we truncate the file.
1026 * open_file_shared explicitly clears this flag before
1027 * calling open_file, so we can safely do this here.
1030 ftruncate(fd_ptr->fd, 0);
1034 /* We need to allocate a new file_fd_struct (this increments the
1036 if((fd_ptr = fd_get_new()) == 0)
1039 * Whatever the requested flags, attempt read/write access,
1040 * as we don't know what flags future file opens may require.
1041 * If this fails, try again with the required flags.
1042 * Even if we open read/write when only read access was
1043 * requested the setting of the can_write flag in
1044 * the file_struct will protect us from errant
1045 * write requests. We never need to worry about O_APPEND
1046 * as this is not set anywhere in Samba.
1048 fd_ptr->real_open_flags = O_RDWR;
1049 /* Set the flags as needed without the read/write modes. */
1050 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1051 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1053 * On some systems opening a file for R/W access on a read only
1054 * filesystems sets errno to EROFS.
1057 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1058 #else /* No EROFS */
1059 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1061 if(flags & O_WRONLY) {
1062 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1063 fd_ptr->real_open_flags = O_WRONLY;
1065 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1066 fd_ptr->real_open_flags = O_RDONLY;
1071 if ((fd_ptr->fd >=0) &&
1072 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1076 strcpy(dname,fname);
1077 p = strrchr(dname,'/');
1079 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1080 lp_minprintspace(SNUM(cnum))) {
1081 fd_attempt_close(fd_ptr);
1082 Files[fnum].fd_ptr = 0;
1083 if(fd_ptr->ref_count == 0)
1092 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1093 fname,strerror(errno),flags));
1094 /* Ensure the ref_count is decremented. */
1095 fd_attempt_close(fd_ptr);
1096 check_for_pipe(fname);
1100 if (fd_ptr->fd >= 0)
1104 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1105 /* Error - backout !! */
1106 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1107 fd_ptr->fd, fname,strerror(errno)));
1108 /* Ensure the ref_count is decremented. */
1109 fd_attempt_close(fd_ptr);
1114 /* Set the correct entries in fd_ptr. */
1115 fd_ptr->dev = (int32)sbuf->st_dev;
1116 fd_ptr->inode = (int32)sbuf->st_ino;
1118 Files[fnum].fd_ptr = fd_ptr;
1119 Connections[cnum].num_files_open++;
1120 Files[fnum].mode = sbuf->st_mode;
1121 GetTimeOfDay(&Files[fnum].open_time);
1122 Files[fnum].uid = current_user.id;
1123 Files[fnum].size = 0;
1124 Files[fnum].pos = -1;
1125 Files[fnum].open = True;
1126 Files[fnum].mmap_ptr = NULL;
1127 Files[fnum].mmap_size = 0;
1128 Files[fnum].can_lock = True;
1129 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1130 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1131 Files[fnum].share_mode = 0;
1132 Files[fnum].share_pending = False;
1133 Files[fnum].print_file = Connections[cnum].printer;
1134 Files[fnum].modified = False;
1135 Files[fnum].cnum = cnum;
1136 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1137 Files[fnum].wbmpx_ptr = NULL;
1140 * If the printer is marked as postscript output a leading
1141 * file identifier to ensure the file is treated as a raw
1143 * This has a similar effect as CtrlD=0 in WIN.INI file.
1144 * tim@fsg.com 09/06/94
1146 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1147 Files[fnum].can_write)
1149 DEBUG(3,("Writing postscript line\n"));
1150 write_file(fnum,"%!\n",3);
1153 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1154 timestring(),Connections[cnum].user,fname,
1155 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1156 Connections[cnum].num_files_open,fnum));
1161 /* mmap it if read-only */
1162 if (!Files[fnum].can_write)
1164 Files[fnum].mmap_size = file_size(fname);
1165 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1166 PROT_READ,MAP_SHARED,Files[fnum]->fd_ptr.fd,0);
1168 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1170 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1171 Files[fnum].mmap_ptr = NULL;
1177 /*******************************************************************
1179 ********************************************************************/
1180 void sync_file(int fnum)
1183 fsync(Files[fnum].fd_ptr->fd);
1187 /****************************************************************************
1188 run a file if it is a magic script
1189 ****************************************************************************/
1190 static void check_magic(int fnum,int cnum)
1192 if (!*lp_magicscript(SNUM(cnum)))
1195 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1199 if (!(p = strrchr(Files[fnum].name,'/')))
1200 p = Files[fnum].name;
1204 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1210 pstring magic_output;
1212 strcpy(fname,Files[fnum].name);
1214 if (*lp_magicoutput(SNUM(cnum)))
1215 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1217 sprintf(magic_output,"%s.out",fname);
1220 ret = smbrun(fname,magic_output,False);
1221 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1227 /****************************************************************************
1228 close a file - possibly invalidating the read prediction
1229 ****************************************************************************/
1230 void close_file(int fnum)
1232 int cnum = Files[fnum].cnum;
1233 invalidate_read_prediction(Files[fnum].fd_ptr->fd);
1234 Files[fnum].open = False;
1235 Connections[cnum].num_files_open--;
1236 if(Files[fnum].wbmpx_ptr)
1238 free((char *)Files[fnum].wbmpx_ptr);
1239 Files[fnum].wbmpx_ptr = NULL;
1243 if(Files[fnum].mmap_ptr)
1245 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1246 Files[fnum].mmap_ptr = NULL;
1250 if (lp_share_modes(SNUM(cnum)))
1251 del_share_mode(fnum);
1253 fd_attempt_close(Files[fnum].fd_ptr);
1255 /* NT uses smbclose to start a print - weird */
1256 if (Files[fnum].print_file)
1259 /* check for magic scripts */
1260 check_magic(fnum,cnum);
1262 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1263 timestring(),Connections[cnum].user,Files[fnum].name,
1264 Connections[cnum].num_files_open));
1267 enum {AFAIL,AREAD,AWRITE,AALL};
1269 /*******************************************************************
1270 reproduce the share mode access table
1271 ********************************************************************/
1272 static int access_table(int new_deny,int old_deny,int old_mode,
1273 int share_pid,char *fname)
1275 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1277 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1278 if (old_deny == new_deny && share_pid == getpid())
1281 if (old_mode == 0) return(AREAD);
1283 /* the new smbpub.zip spec says that if the file extension is
1284 .com, .dll, .exe or .sym then allow the open. I will force
1285 it to read-only as this seems sensible although the spec is
1286 a little unclear on this. */
1287 if ((fname = strrchr(fname,'.'))) {
1288 if (strequal(fname,".com") ||
1289 strequal(fname,".dll") ||
1290 strequal(fname,".exe") ||
1291 strequal(fname,".sym"))
1301 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1302 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1303 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1306 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1307 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1308 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1311 if (old_deny==DENY_WRITE) return(AREAD);
1312 if (old_deny==DENY_READ) return(AWRITE);
1313 if (old_deny==DENY_NONE) return(AALL);
1319 /*******************************************************************
1320 check if the share mode on a file allows it to be deleted or unlinked
1321 return True if sharing doesn't prevent the operation
1322 ********************************************************************/
1323 BOOL check_file_sharing(int cnum,char *fname)
1326 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1328 if (!pid || !share_mode) return(True);
1330 if (share_mode == DENY_DOS)
1331 return(pid == getpid());
1333 /* XXXX exactly what share mode combinations should be allowed for
1334 deleting/renaming? */
1338 /****************************************************************************
1340 Helper for open_file_shared.
1341 Truncate a file after checking locking; close file if locked.
1342 **************************************************************************/
1343 static void truncate_unless_locked(int fnum, int cnum)
1345 if (Files[fnum].can_write){
1346 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1349 unix_ERR_class = ERRDOS;
1350 unix_ERR_code = ERRlock;
1353 ftruncate(Files[fnum].fd_ptr->fd,0);
1358 /****************************************************************************
1359 open a file with a share mode
1360 ****************************************************************************/
1361 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1362 int mode,int *Access,int *action)
1366 int deny_mode = (share_mode>>4)&7;
1368 BOOL file_existed = file_exist(fname,&sbuf);
1369 BOOL fcbopen = False;
1372 Files[fnum].open = False;
1373 Files[fnum].fd_ptr = 0;
1375 /* this is for OS/2 EAs - try and say we don't support them */
1376 if (strstr(fname,".+,;=[].")) {
1377 unix_ERR_class = ERRDOS;
1378 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1382 if ((ofun & 0x3) == 0 && file_existed) {
1389 if ((ofun & 0x3) == 2)
1392 /* note that we ignore the append flag as
1393 append does not mean the same thing under dos and unix */
1395 switch (share_mode&0xF)
1412 if (flags != O_RDONLY && file_existed &&
1413 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1421 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1422 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1427 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1429 if (lp_share_modes(SNUM(cnum))) {
1433 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1436 /* someone else has a share lock on it, check to see
1438 int old_open_mode = old_share&0xF;
1439 int old_deny_mode = (old_share>>4)&7;
1441 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1442 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1443 deny_mode,old_deny_mode,old_open_mode,fname));
1445 unix_ERR_class = ERRDOS;
1446 unix_ERR_code = ERRbadshare;
1451 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1454 if ((access_allowed == AFAIL) ||
1455 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1456 (access_allowed == AREAD && flags == O_WRONLY) ||
1457 (access_allowed == AWRITE && flags == O_RDONLY)) {
1458 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1459 deny_mode,old_deny_mode,old_open_mode,
1463 unix_ERR_class = ERRDOS;
1464 unix_ERR_code = ERRbadshare;
1468 if (access_allowed == AREAD)
1471 if (access_allowed == AWRITE)
1477 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1478 flags,flags2,mode));
1480 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1481 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1483 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1486 if (Files[fnum].open) {
1500 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1501 Files[fnum].share_pending = True;
1504 (*Access) = open_mode;
1508 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1509 if (!file_existed) *action = 2;
1510 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1514 share_mode_pending = True;
1516 if ((flags2&O_TRUNC) && file_existed)
1517 truncate_unless_locked(fnum,cnum);
1523 /*******************************************************************
1524 check for files that we should now set our share modes on
1525 ********************************************************************/
1526 static void check_share_modes(void)
1529 for (i=0;i<MAX_OPEN_FILES;i++)
1530 if(Files[i].open && Files[i].share_pending) {
1531 if (lp_share_modes(SNUM(Files[i].cnum))) {
1533 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1535 set_share_mode(i,Files[i].share_mode);
1536 Files[i].share_pending = False;
1539 Files[i].share_pending = False;
1545 /****************************************************************************
1546 seek a file. Try to avoid the seek if possible
1547 ****************************************************************************/
1548 int seek_file(int fnum,int pos)
1551 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1554 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1555 return(Files[fnum].pos);
1558 /****************************************************************************
1560 ****************************************************************************/
1561 int read_file(int fnum,char *data,int pos,int n)
1565 if (!Files[fnum].can_write)
1567 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1575 if (Files[fnum].mmap_ptr)
1577 int num = MIN(n,Files[fnum].mmap_size-pos);
1580 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1592 if (seek_file(fnum,pos) != pos)
1594 DEBUG(3,("Failed to seek to %d\n",pos));
1599 readret = read(Files[fnum].fd_ptr->fd,data,n);
1600 if (readret > 0) ret += readret;
1607 /****************************************************************************
1609 ****************************************************************************/
1610 int write_file(int fnum,char *data,int n)
1612 if (!Files[fnum].can_write) {
1617 if (!Files[fnum].modified) {
1619 Files[fnum].modified = True;
1620 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1621 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1622 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1623 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1628 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1632 /****************************************************************************
1633 load parameters specific to a connection/service
1634 ****************************************************************************/
1635 BOOL become_service(int cnum,BOOL do_chdir)
1637 extern char magic_char;
1638 static int last_cnum = -1;
1641 if (!OPEN_CNUM(cnum))
1647 Connections[cnum].lastused = smb_last_time;
1652 ChDir(Connections[cnum].connectpath) != 0 &&
1653 ChDir(Connections[cnum].origpath) != 0)
1655 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1656 Connections[cnum].connectpath,cnum));
1660 if (cnum == last_cnum)
1665 case_default = lp_defaultcase(snum);
1666 case_preserve = lp_preservecase(snum);
1667 short_case_preserve = lp_shortpreservecase(snum);
1668 case_mangle = lp_casemangle(snum);
1669 case_sensitive = lp_casesensitive(snum);
1670 magic_char = lp_magicchar(snum);
1671 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1676 /****************************************************************************
1677 find a service entry
1678 ****************************************************************************/
1679 int find_service(char *service)
1683 string_sub(service,"\\","/");
1685 iService = lp_servicenumber(service);
1687 /* now handle the special case of a home directory */
1690 char *phome_dir = get_home_dir(service);
1691 DEBUG(3,("checking for home directory %s gave %s\n",service,
1692 phome_dir?phome_dir:"(NULL)"));
1696 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1698 lp_add_home(service,iHomeService,phome_dir);
1699 iService = lp_servicenumber(service);
1704 /* If we still don't have a service, attempt to add it as a printer. */
1707 int iPrinterService;
1709 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1713 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1715 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1717 DEBUG(3,("%s is a valid printer name\n", service));
1718 DEBUG(3,("adding %s as a printer service\n", service));
1719 lp_add_printer(service,iPrinterService);
1720 iService = lp_servicenumber(service);
1722 DEBUG(0,("failed to add %s as a printer service!\n", service));
1725 DEBUG(3,("%s is not a valid printer name\n", service));
1729 /* just possibly it's a default service? */
1732 char *defservice = lp_defaultservice();
1733 if (defservice && *defservice && !strequal(defservice,service)) {
1734 iService = find_service(defservice);
1735 if (iService >= 0) {
1736 string_sub(service,"_","/");
1737 iService = lp_add_service(service,iService);
1743 if (!VALID_SNUM(iService))
1745 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1750 DEBUG(3,("find_service() failed to find service %s\n", service));
1756 /****************************************************************************
1757 create an error packet from a cached error.
1758 ****************************************************************************/
1759 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1761 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1763 int32 eclass = wbmpx->wr_errclass;
1764 int32 err = wbmpx->wr_error;
1766 /* We can now delete the auxiliary struct */
1767 free((char *)wbmpx);
1768 Files[fnum].wbmpx_ptr = NULL;
1769 return error_packet(inbuf,outbuf,eclass,err,line);
1778 } unix_smb_errmap[] =
1780 {EPERM,ERRDOS,ERRnoaccess},
1781 {EACCES,ERRDOS,ERRnoaccess},
1782 {ENOENT,ERRDOS,ERRbadfile},
1783 {EIO,ERRHRD,ERRgeneral},
1784 {EBADF,ERRSRV,ERRsrverror},
1785 {EINVAL,ERRSRV,ERRsrverror},
1786 {EEXIST,ERRDOS,ERRfilexists},
1787 {ENFILE,ERRDOS,ERRnofids},
1788 {EMFILE,ERRDOS,ERRnofids},
1789 {ENOSPC,ERRHRD,ERRdiskfull},
1791 {EDQUOT,ERRHRD,ERRdiskfull},
1794 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1797 {EXDEV,ERRDOS,ERRdiffdevice},
1799 {EROFS,ERRHRD,ERRnowrite},
1804 /****************************************************************************
1805 create an error packet from errno
1806 ****************************************************************************/
1807 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1809 int eclass=def_class;
1813 if (unix_ERR_class != SUCCESS)
1815 eclass = unix_ERR_class;
1816 ecode = unix_ERR_code;
1817 unix_ERR_class = SUCCESS;
1822 while (unix_smb_errmap[i].smbclass != 0)
1824 if (unix_smb_errmap[i].unixerror == errno)
1826 eclass = unix_smb_errmap[i].smbclass;
1827 ecode = unix_smb_errmap[i].smbcode;
1834 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1838 /****************************************************************************
1839 create an error packet. Normally called using the ERROR() macro
1840 ****************************************************************************/
1841 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1843 int outsize = set_message(outbuf,0,0,True);
1845 cmd = CVAL(inbuf,smb_com);
1847 CVAL(outbuf,smb_rcls) = error_class;
1848 SSVAL(outbuf,smb_err,error_code);
1850 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1853 (int)CVAL(inbuf,smb_com),
1854 smb_fn_name(CVAL(inbuf,smb_com)),
1859 DEBUG(3,("error string = %s\n",strerror(errno)));
1865 #ifndef SIGCLD_IGNORE
1866 /****************************************************************************
1867 this prevents zombie child processes
1868 ****************************************************************************/
1869 static int sig_cld()
1871 static int depth = 0;
1874 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1880 BlockSignals(True,SIGCLD);
1881 DEBUG(5,("got SIGCLD\n"));
1884 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1888 /* Stevens, Adv. Unix Prog. says that on system V you must call
1889 wait before reinstalling the signal handler, because the kernel
1890 calls the handler from within the signal-call when there is a
1891 child that has exited. This would lead to an infinite recursion
1892 if done vice versa. */
1894 #ifndef DONT_REINSTALL_SIG
1895 #ifdef SIGCLD_IGNORE
1896 signal(SIGCLD, SIG_IGN);
1898 signal(SIGCLD, SIGNAL_CAST sig_cld);
1903 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1906 BlockSignals(False,SIGCLD);
1911 /****************************************************************************
1912 this is called when the client exits abruptly
1913 **************************************************************************/
1914 static int sig_pipe()
1916 extern int password_client;
1917 BlockSignals(True,SIGPIPE);
1919 if (password_client != -1) {
1920 DEBUG(3,("lost connection to password server\n"));
1921 close(password_client);
1922 password_client = -1;
1923 #ifndef DONT_REINSTALL_SIG
1924 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1926 BlockSignals(False,SIGPIPE);
1930 exit_server("Got sigpipe\n");
1934 /****************************************************************************
1935 open the socket communication
1936 ****************************************************************************/
1937 static BOOL open_sockets(BOOL is_daemon,int port)
1944 struct sockaddr addr;
1945 int in_addrlen = sizeof(addr);
1948 #ifdef SIGCLD_IGNORE
1949 signal(SIGCLD, SIG_IGN);
1951 signal(SIGCLD, SIGNAL_CAST sig_cld);
1954 /* open an incoming socket */
1955 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1959 /* ready to listen */
1960 if (listen(s, 5) == -1)
1962 DEBUG(0,("listen: %s",strerror(errno)));
1970 /* now accept incoming connections - forking a new process
1971 for each incoming connection */
1972 DEBUG(2,("waiting for a connection\n"));
1975 Client = accept(s,&addr,&in_addrlen);
1977 if (Client == -1 && errno == EINTR)
1982 DEBUG(0,("accept: %s",strerror(errno)));
1986 #ifdef NO_FORK_DEBUG
1987 #ifndef NO_SIGNAL_TEST
1988 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1989 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1993 if (Client != -1 && fork()==0)
1995 #ifndef NO_SIGNAL_TEST
1996 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1997 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1999 /* close the listening socket */
2002 /* close our standard file descriptors */
2006 set_socket_options(Client,"SO_KEEPALIVE");
2007 set_socket_options(Client,user_socket_options);
2011 close(Client); /* The parent doesn't need this socket */
2017 /* We will abort gracefully when the client or remote system
2019 #ifndef NO_SIGNAL_TEST
2020 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2024 /* close our standard file descriptors */
2027 set_socket_options(Client,"SO_KEEPALIVE");
2028 set_socket_options(Client,user_socket_options);
2035 /****************************************************************************
2036 check if a snum is in use
2037 ****************************************************************************/
2038 BOOL snum_used(int snum)
2041 for (i=0;i<MAX_CONNECTIONS;i++)
2042 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2047 /****************************************************************************
2048 reload the services file
2049 **************************************************************************/
2050 BOOL reload_services(BOOL test)
2057 strcpy(fname,lp_configfile());
2058 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2060 strcpy(servicesf,fname);
2067 if (test && !lp_file_list_changed())
2070 lp_killunused(snum_used);
2072 ret = lp_load(servicesf,False);
2074 /* perhaps the config filename is now set */
2076 reload_services(True);
2085 set_socket_options(Client,"SO_KEEPALIVE");
2086 set_socket_options(Client,user_socket_options);
2090 create_mangled_stack(lp_mangledstack());
2092 /* this forces service parameters to be flushed */
2093 become_service(-1,True);
2100 /****************************************************************************
2101 this prevents zombie child processes
2102 ****************************************************************************/
2103 static int sig_hup()
2105 BlockSignals(True,SIGHUP);
2106 DEBUG(0,("Got SIGHUP\n"));
2107 reload_services(False);
2108 #ifndef DONT_REINSTALL_SIG
2109 signal(SIGHUP,SIGNAL_CAST sig_hup);
2111 BlockSignals(False,SIGHUP);
2115 /****************************************************************************
2116 Setup the groups a user belongs to.
2117 ****************************************************************************/
2118 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2119 int **p_igroups, gid_t **p_groups)
2121 if (-1 == initgroups(user,gid))
2125 DEBUG(0,("Unable to initgroups!\n"));
2126 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2127 DEBUG(0,("This is probably a problem with the account %s\n",user));
2135 ngroups = getgroups(0,&grp);
2138 igroups = (int *)malloc(sizeof(int)*ngroups);
2139 for (i=0;i<ngroups;i++)
2140 igroups[i] = 0x42424242;
2141 ngroups = getgroups(ngroups,(gid_t *)igroups);
2143 if (igroups[0] == 0x42424242)
2146 *p_ngroups = ngroups;
2148 /* The following bit of code is very strange. It is due to the
2149 fact that some OSes use int* and some use gid_t* for
2150 getgroups, and some (like SunOS) use both, one in prototypes,
2151 and one in man pages and the actual code. Thus we detect it
2152 dynamically using some very ugly code */
2155 /* does getgroups return ints or gid_t ?? */
2156 static BOOL groups_use_ints = True;
2158 if (groups_use_ints &&
2160 SVAL(igroups,2) == 0x4242)
2161 groups_use_ints = False;
2163 for (i=0;groups_use_ints && i<ngroups;i++)
2164 if (igroups[i] == 0x42424242)
2165 groups_use_ints = False;
2167 if (groups_use_ints)
2169 *p_igroups = igroups;
2170 *p_groups = (gid_t *)igroups;
2174 gid_t *groups = (gid_t *)igroups;
2175 igroups = (int *)malloc(sizeof(int)*ngroups);
2176 for (i=0;i<ngroups;i++)
2177 igroups[i] = groups[i];
2178 *p_igroups = igroups;
2179 *p_groups = (gid_t *)groups;
2182 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2183 for (i=0;i<ngroups;i++)
2184 DEBUG(3,("%d ",igroups[i]));
2190 /****************************************************************************
2191 make a connection to a service
2192 ****************************************************************************/
2193 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2197 struct passwd *pass = NULL;
2198 connection_struct *pcon;
2201 static BOOL first_connection = True;
2205 snum = find_service(service);
2208 if (strequal(service,"IPC$"))
2210 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2214 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2218 if (strequal(service,HOMES_NAME))
2220 if (*user && Get_Pwnam(user,True))
2221 return(make_connection(user,user,password,pwlen,dev,vuid));
2223 if (validated_username(vuid))
2225 strcpy(user,validated_username(vuid));
2226 return(make_connection(user,user,password,pwlen,dev,vuid));
2230 if (!lp_snum_ok(snum) || !check_access(snum)) {
2234 /* you can only connect to the IPC$ service as an ipc device */
2235 if (strequal(service,"IPC$"))
2238 if (*dev == '?' || !*dev)
2240 if (lp_print_ok(snum))
2241 strcpy(dev,"LPT1:");
2246 /* if the request is as a printer and you can't print then refuse */
2248 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2249 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2253 /* lowercase the user name */
2256 /* add it as a possible user name */
2257 add_session_user(service);
2259 /* shall we let them in? */
2260 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2262 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2266 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2269 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2273 pcon = &Connections[cnum];
2274 bzero((char *)pcon,sizeof(*pcon));
2276 /* find out some info about the user */
2277 pass = Get_Pwnam(user,True);
2281 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2285 pcon->read_only = lp_readonly(snum);
2289 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2290 string_sub(list,"%S",service);
2292 if (user_in_list(user,list))
2293 pcon->read_only = True;
2295 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2296 string_sub(list,"%S",service);
2298 if (user_in_list(user,list))
2299 pcon->read_only = False;
2302 /* admin user check */
2303 if (user_in_list(user,lp_admin_users(snum)) &&
2306 pcon->admin_user = True;
2307 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2310 pcon->admin_user = False;
2312 pcon->force_user = force;
2314 pcon->uid = pass->pw_uid;
2315 pcon->gid = pass->pw_gid;
2316 pcon->num_files_open = 0;
2317 pcon->lastused = time(NULL);
2318 pcon->service = snum;
2320 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2321 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2322 pcon->dirptr = NULL;
2323 string_set(&pcon->dirpath,"");
2324 string_set(&pcon->user,user);
2327 if (*lp_force_group(snum))
2332 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2333 /* default service may be a group name */
2334 string_sub(gname,"%S",service);
2335 gptr = (struct group *)getgrnam(gname);
2339 pcon->gid = gptr->gr_gid;
2340 DEBUG(3,("Forced group %s\n",gname));
2343 DEBUG(1,("Couldn't find group %s\n",gname));
2347 if (*lp_force_user(snum))
2349 struct passwd *pass2;
2351 strcpy(fuser,lp_force_user(snum));
2352 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2355 pcon->uid = pass2->pw_uid;
2356 string_set(&pcon->user,fuser);
2358 pcon->force_user = True;
2359 DEBUG(3,("Forced user %s\n",fuser));
2362 DEBUG(1,("Couldn't find user %s\n",fuser));
2367 strcpy(s,lp_pathname(snum));
2368 standard_sub(cnum,s);
2369 string_set(&pcon->connectpath,s);
2370 DEBUG(3,("Connect path is %s\n",s));
2373 /* groups stuff added by ih */
2375 pcon->groups = NULL;
2379 /* Find all the groups this uid is in and store them. Used by become_user() */
2380 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2382 /* check number of connections */
2383 if (!claim_connection(cnum,
2384 lp_servicename(SNUM(cnum)),
2385 lp_max_connections(SNUM(cnum)),False))
2387 DEBUG(1,("too many connections - rejected\n"));
2391 if (lp_status(SNUM(cnum)))
2392 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2394 first_connection = False;
2399 /* execute any "root preexec = " line */
2400 if (*lp_rootpreexec(SNUM(cnum)))
2403 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2404 standard_sub(cnum,cmd);
2405 DEBUG(5,("cmd=%s\n",cmd));
2406 smbrun(cmd,NULL,False);
2409 if (!become_user(cnum,pcon->vuid))
2411 DEBUG(0,("Can't become connected user!\n"));
2413 if (!IS_IPC(cnum)) {
2414 yield_connection(cnum,
2415 lp_servicename(SNUM(cnum)),
2416 lp_max_connections(SNUM(cnum)));
2417 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2422 if (ChDir(pcon->connectpath) != 0)
2424 DEBUG(0,("Can't change directory to %s (%s)\n",
2425 pcon->connectpath,strerror(errno)));
2428 if (!IS_IPC(cnum)) {
2429 yield_connection(cnum,
2430 lp_servicename(SNUM(cnum)),
2431 lp_max_connections(SNUM(cnum)));
2432 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2437 string_set(&pcon->origpath,pcon->connectpath);
2439 #if SOFTLINK_OPTIMISATION
2440 /* resolve any soft links early */
2443 strcpy(s,pcon->connectpath);
2445 string_set(&pcon->connectpath,s);
2446 ChDir(pcon->connectpath);
2450 num_connections_open++;
2451 add_session_user(user);
2453 /* execute any "preexec = " line */
2454 if (*lp_preexec(SNUM(cnum)))
2457 strcpy(cmd,lp_preexec(SNUM(cnum)));
2458 standard_sub(cnum,cmd);
2459 smbrun(cmd,NULL,False);
2462 /* we've finished with the sensitive stuff */
2466 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2470 lp_servicename(SNUM(cnum)),user,
2480 /****************************************************************************
2481 find first available file slot
2482 ****************************************************************************/
2483 int find_free_file(void )
2486 /* we start at 1 here for an obscure reason I can't now remember,
2487 but I think is important :-) */
2488 for (i=1;i<MAX_OPEN_FILES;i++)
2491 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2495 /****************************************************************************
2496 find first available connection slot, starting from a random position.
2497 The randomisation stops problems with the server dieing and clients
2498 thinking the server is still available.
2499 ****************************************************************************/
2500 static int find_free_connection(int hash )
2504 hash = (hash % (MAX_CONNECTIONS-2))+1;
2508 for (i=hash+1;i!=hash;)
2510 if (!Connections[i].open && Connections[i].used == used)
2512 DEBUG(3,("found free connection number %d\n",i));
2516 if (i == MAX_CONNECTIONS)
2526 DEBUG(1,("ERROR! Out of connection structures\n"));
2531 /****************************************************************************
2532 reply for the core protocol
2533 ****************************************************************************/
2534 int reply_corep(char *outbuf)
2536 int outsize = set_message(outbuf,1,0,True);
2538 Protocol = PROTOCOL_CORE;
2544 /****************************************************************************
2545 reply for the coreplus protocol
2546 ****************************************************************************/
2547 int reply_coreplus(char *outbuf)
2549 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2550 int outsize = set_message(outbuf,13,0,True);
2551 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2552 readbraw and writebraw (possibly) */
2553 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2554 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2556 Protocol = PROTOCOL_COREPLUS;
2562 /****************************************************************************
2563 reply for the lanman 1.0 protocol
2564 ****************************************************************************/
2565 int reply_lanman1(char *outbuf)
2567 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2569 BOOL doencrypt = SMBENCRYPT();
2570 time_t t = time(NULL);
2572 if (lp_security()>=SEC_USER) secword |= 1;
2573 if (doencrypt) secword |= 2;
2575 set_message(outbuf,13,doencrypt?8:0,True);
2576 SSVAL(outbuf,smb_vwv1,secword);
2578 /* Create a token value and add it to the outgoing packet. */
2580 generate_next_challenge(smb_buf(outbuf));
2583 Protocol = PROTOCOL_LANMAN1;
2585 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2586 DEBUG(3,("using password server validation\n"));
2588 if (doencrypt) set_challenge(smb_buf(outbuf));
2592 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2593 SSVAL(outbuf,smb_vwv2,maxxmit);
2594 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2595 SSVAL(outbuf,smb_vwv4,1);
2596 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2597 readbraw writebraw (possibly) */
2598 SIVAL(outbuf,smb_vwv6,getpid());
2599 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2601 put_dos_date(outbuf,smb_vwv8,t);
2603 return (smb_len(outbuf)+4);
2607 /****************************************************************************
2608 reply for the lanman 2.0 protocol
2609 ****************************************************************************/
2610 int reply_lanman2(char *outbuf)
2612 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2614 BOOL doencrypt = SMBENCRYPT();
2615 time_t t = time(NULL);
2617 if (lp_security()>=SEC_USER) secword |= 1;
2618 if (doencrypt) secword |= 2;
2620 set_message(outbuf,13,doencrypt?8:0,True);
2621 SSVAL(outbuf,smb_vwv1,secword);
2623 /* Create a token value and add it to the outgoing packet. */
2625 generate_next_challenge(smb_buf(outbuf));
2628 SIVAL(outbuf,smb_vwv6,getpid());
2630 Protocol = PROTOCOL_LANMAN2;
2632 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2633 DEBUG(3,("using password server validation\n"));
2635 if (doencrypt) set_challenge(smb_buf(outbuf));
2639 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2640 SSVAL(outbuf,smb_vwv2,maxxmit);
2641 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2642 SSVAL(outbuf,smb_vwv4,1);
2643 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2644 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2645 put_dos_date(outbuf,smb_vwv8,t);
2647 return (smb_len(outbuf)+4);
2650 /****************************************************************************
2651 reply for the nt protocol
2652 ****************************************************************************/
2653 int reply_nt1(char *outbuf)
2655 int capabilities=0x300; /* has dual names + lock_and_read */
2657 BOOL doencrypt = SMBENCRYPT();
2658 time_t t = time(NULL);
2660 if (lp_security()>=SEC_USER) secword |= 1;
2661 if (doencrypt) secword |= 2;
2663 set_message(outbuf,17,doencrypt?8:0,True);
2664 CVAL(outbuf,smb_vwv1) = secword;
2666 /* Create a token value and add it to the outgoing packet. */
2668 generate_next_challenge(smb_buf(outbuf));
2669 /* Tell the nt machine how long the challenge is. */
2670 SSVALS(outbuf,smb_vwv16+1,8);
2674 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2676 Protocol = PROTOCOL_NT1;
2678 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2679 DEBUG(3,("using password server validation\n"));
2681 if (doencrypt) set_challenge(smb_buf(outbuf));
2685 if (lp_readraw() && lp_writeraw())
2688 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2689 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2690 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2691 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2692 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2693 put_long_date(outbuf+smb_vwv11+1,t);
2694 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2696 return (smb_len(outbuf)+4);
2700 /* these are the protocol lists used for auto architecture detection:
2703 protocol [PC NETWORK PROGRAM 1.0]
2704 protocol [XENIX CORE]
2705 protocol [MICROSOFT NETWORKS 1.03]
2706 protocol [LANMAN1.0]
2707 protocol [Windows for Workgroups 3.1a]
2708 protocol [LM1.2X002]
2709 protocol [LANMAN2.1]
2710 protocol [NT LM 0.12]
2713 protocol [PC NETWORK PROGRAM 1.0]
2714 protocol [XENIX CORE]
2715 protocol [MICROSOFT NETWORKS 1.03]
2716 protocol [LANMAN1.0]
2717 protocol [Windows for Workgroups 3.1a]
2718 protocol [LM1.2X002]
2719 protocol [LANMAN2.1]
2720 protocol [NT LM 0.12]
2723 protocol [PC NETWORK PROGRAM 1.0]
2724 protocol [XENIX CORE]
2725 protocol [LANMAN1.0]
2726 protocol [LM1.2X002]
2727 protocol [LANMAN2.1]
2731 * Modified to recognize the architecture of the remote machine better.
2733 * This appears to be the matrix of which protocol is used by which
2735 Protocol WfWg Win95 WinNT OS/2
2736 PC NETWORK PROGRAM 1.0 1 1 1 1
2738 MICROSOFT NETWORKS 3.0 2 2
2740 MICROSOFT NETWORKS 1.03 3
2743 Windows for Workgroups 3.1a 5 5 5
2748 * tim@fsg.com 09/29/95
2751 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2752 #define ARCH_WIN95 0x2
2753 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2754 #define ARCH_WINNT 0x8
2755 #define ARCH_SAMBA 0x10
2757 #define ARCH_ALL 0x1F
2759 /* List of supported protocols, most desired first */
2763 int (*proto_reply_fn)(char *);
2765 } supported_protocols[] = {
2766 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2767 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2768 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2769 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2770 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2771 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2772 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2773 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2774 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2779 /****************************************************************************
2781 ****************************************************************************/
2782 static int reply_negprot(char *inbuf,char *outbuf)
2784 extern fstring remote_arch;
2785 int outsize = set_message(outbuf,1,0,True);
2790 int bcc = SVAL(smb_buf(inbuf),-2);
2791 int arch = ARCH_ALL;
2793 p = smb_buf(inbuf)+1;
2794 while (p < (smb_buf(inbuf) + bcc))
2797 DEBUG(3,("Requested protocol [%s]\n",p));
2798 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2799 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2800 else if (strcsequal(p,"DOS LM1.2X002"))
2801 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2802 else if (strcsequal(p,"DOS LANMAN2.1"))
2803 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2804 else if (strcsequal(p,"NT LM 0.12"))
2805 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2806 else if (strcsequal(p,"LANMAN2.1"))
2807 arch &= ( ARCH_WINNT | ARCH_OS2 );
2808 else if (strcsequal(p,"LM1.2X002"))
2809 arch &= ( ARCH_WINNT | ARCH_OS2 );
2810 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2812 else if (strcsequal(p,"XENIX CORE"))
2813 arch &= ( ARCH_WINNT | ARCH_OS2 );
2814 else if (strcsequal(p,"Samba")) {
2824 strcpy(remote_arch,"Samba");
2827 strcpy(remote_arch,"WfWg");
2830 strcpy(remote_arch,"Win95");
2833 strcpy(remote_arch,"WinNT");
2836 strcpy(remote_arch,"OS2");
2839 strcpy(remote_arch,"UNKNOWN");
2843 /* possibly reload - change of architecture */
2844 reload_services(True);
2846 /* a special case to stop password server loops */
2847 if (Index == 1 && strequal(remote_machine,myhostname) &&
2848 lp_security()==SEC_SERVER)
2849 exit_server("Password server loop!");
2851 /* Check for protocols, most desirable first */
2852 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2854 p = smb_buf(inbuf)+1;
2856 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2857 while (p < (smb_buf(inbuf) + bcc))
2859 if (strequal(p,supported_protocols[protocol].proto_name))
2868 SSVAL(outbuf,smb_vwv0,choice);
2870 extern fstring remote_proto;
2871 strcpy(remote_proto,supported_protocols[protocol].short_name);
2872 reload_services(True);
2873 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2874 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2877 DEBUG(0,("No protocol supported !\n"));
2879 SSVAL(outbuf,smb_vwv0,choice);
2881 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2887 /****************************************************************************
2888 close all open files for a connection
2889 ****************************************************************************/
2890 static void close_open_files(int cnum)
2893 for (i=0;i<MAX_OPEN_FILES;i++)
2894 if( Files[i].cnum == cnum && Files[i].open) {
2901 /****************************************************************************
2903 ****************************************************************************/
2904 void close_cnum(int cnum, uint16 vuid)
2906 DirCacheFlush(SNUM(cnum));
2910 if (!OPEN_CNUM(cnum))
2912 DEBUG(0,("Can't close cnum %d\n",cnum));
2916 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2918 remote_machine,client_addr(),
2919 lp_servicename(SNUM(cnum))));
2921 yield_connection(cnum,
2922 lp_servicename(SNUM(cnum)),
2923 lp_max_connections(SNUM(cnum)));
2925 if (lp_status(SNUM(cnum)))
2926 yield_connection(cnum,"STATUS.",MAXSTATUS);
2928 close_open_files(cnum);
2929 dptr_closecnum(cnum);
2931 /* execute any "postexec = " line */
2932 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
2935 strcpy(cmd,lp_postexec(SNUM(cnum)));
2936 standard_sub(cnum,cmd);
2937 smbrun(cmd,NULL,False);
2942 /* execute any "root postexec = " line */
2943 if (*lp_rootpostexec(SNUM(cnum)))
2946 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2947 standard_sub(cnum,cmd);
2948 smbrun(cmd,NULL,False);
2951 Connections[cnum].open = False;
2952 num_connections_open--;
2953 if (Connections[cnum].ngroups && Connections[cnum].groups)
2955 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2956 free(Connections[cnum].groups);
2957 free(Connections[cnum].igroups);
2958 Connections[cnum].groups = NULL;
2959 Connections[cnum].igroups = NULL;
2960 Connections[cnum].ngroups = 0;
2963 string_set(&Connections[cnum].user,"");
2964 string_set(&Connections[cnum].dirpath,"");
2965 string_set(&Connections[cnum].connectpath,"");
2969 /****************************************************************************
2970 simple routines to do connection counting
2971 ****************************************************************************/
2972 BOOL yield_connection(int cnum,char *name,int max_connections)
2974 struct connect_record crec;
2977 int mypid = getpid();
2980 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2982 if (max_connections <= 0)
2985 bzero(&crec,sizeof(crec));
2987 strcpy(fname,lp_lockdir());
2988 standard_sub(cnum,fname);
2989 trim_string(fname,"","/");
2993 strcat(fname,".LCK");
2995 f = fopen(fname,"r+");
2998 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3002 fseek(f,0,SEEK_SET);
3004 /* find a free spot */
3005 for (i=0;i<max_connections;i++)
3007 if (fread(&crec,sizeof(crec),1,f) != 1)
3009 DEBUG(2,("Entry not found in lock file %s\n",fname));
3013 if (crec.pid == mypid && crec.cnum == cnum)
3017 if (crec.pid != mypid || crec.cnum != cnum)
3020 DEBUG(2,("Entry not found in lock file %s\n",fname));
3024 bzero((void *)&crec,sizeof(crec));
3026 /* remove our mark */
3027 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3028 fwrite(&crec,sizeof(crec),1,f) != 1)
3030 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3035 DEBUG(3,("Yield successful\n"));
3042 /****************************************************************************
3043 simple routines to do connection counting
3044 ****************************************************************************/
3045 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3047 struct connect_record crec;
3050 int snum = SNUM(cnum);
3054 if (max_connections <= 0)
3057 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3059 strcpy(fname,lp_lockdir());
3060 standard_sub(cnum,fname);
3061 trim_string(fname,"","/");
3063 if (!directory_exist(fname,NULL))
3068 strcat(fname,".LCK");
3070 if (!file_exist(fname,NULL))
3072 int oldmask = umask(022);
3073 f = fopen(fname,"w");
3078 total_recs = file_size(fname) / sizeof(crec);
3080 f = fopen(fname,"r+");
3084 DEBUG(1,("couldn't open lock file %s\n",fname));
3088 /* find a free spot */
3089 for (i=0;i<max_connections;i++)
3092 if (i>=total_recs ||
3093 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3094 fread(&crec,sizeof(crec),1,f) != 1)
3096 if (foundi < 0) foundi = i;
3100 if (Clear && crec.pid && !process_exists(crec.pid))
3102 fseek(f,i*sizeof(crec),SEEK_SET);
3103 bzero((void *)&crec,sizeof(crec));
3104 fwrite(&crec,sizeof(crec),1,f);
3105 if (foundi < 0) foundi = i;
3108 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3117 DEBUG(3,("no free locks in %s\n",fname));
3122 /* fill in the crec */
3123 bzero((void *)&crec,sizeof(crec));
3124 crec.magic = 0x280267;
3125 crec.pid = getpid();
3127 crec.uid = Connections[cnum].uid;
3128 crec.gid = Connections[cnum].gid;
3129 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3130 crec.start = time(NULL);
3132 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3133 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3136 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3137 fwrite(&crec,sizeof(crec),1,f) != 1)
3148 /*******************************************************************
3149 prepare to dump a core file - carefully!
3150 ********************************************************************/
3151 static BOOL dump_core(void)
3155 strcpy(dname,debugf);
3156 if ((p=strrchr(dname,'/'))) *p=0;
3157 strcat(dname,"/corefiles");
3159 sys_chown(dname,getuid(),getgid());
3161 if (chdir(dname)) return(False);
3164 #ifndef NO_GETRLIMIT
3168 getrlimit(RLIMIT_CORE, &rlp);
3169 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3170 setrlimit(RLIMIT_CORE, &rlp);
3171 getrlimit(RLIMIT_CORE, &rlp);
3172 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3178 DEBUG(0,("Dumping core in %s\n",dname));
3183 /****************************************************************************
3185 ****************************************************************************/
3186 void exit_server(char *reason)
3188 static int firsttime=1;
3191 if (!firsttime) exit(0);
3195 DEBUG(2,("Closing connections\n"));
3196 for (i=0;i<MAX_CONNECTIONS;i++)
3197 if (Connections[i].open)
3200 if (dcelogin_atmost_once)
3204 int oldlevel = DEBUGLEVEL;
3206 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3208 show_msg(last_inbuf);
3209 DEBUGLEVEL = oldlevel;
3210 DEBUG(0,("===============================================================\n"));
3212 if (dump_core()) return;
3216 #if FAST_SHARE_MODES
3217 stop_share_mode_mgmt();
3220 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3224 /****************************************************************************
3225 do some standard substitutions in a string
3226 ****************************************************************************/
3227 void standard_sub(int cnum,char *s)
3229 if (!strchr(s,'%')) return;
3231 if (VALID_CNUM(cnum))
3233 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3234 string_sub(s,"%P",Connections[cnum].connectpath);
3235 string_sub(s,"%u",Connections[cnum].user);
3236 if (strstr(s,"%H")) {
3237 char *home = get_home_dir(Connections[cnum].user);
3238 if (home) string_sub(s,"%H",home);
3240 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3242 standard_sub_basic(s);
3246 These flags determine some of the permissions required to do an operation
3248 Note that I don't set NEED_WRITE on some write operations because they
3249 are used by some brain-dead clients when printing, and I don't want to
3250 force write permissions on print services.
3252 #define AS_USER (1<<0)
3253 #define NEED_WRITE (1<<1)
3254 #define TIME_INIT (1<<2)
3255 #define CAN_IPC (1<<3)
3256 #define AS_GUEST (1<<5)
3260 define a list of possible SMB messages and their corresponding
3261 functions. Any message that has a NULL function is unimplemented -
3262 please feel free to contribute implementations!
3264 struct smb_message_struct
3278 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3279 {SMBtcon,"SMBtcon",reply_tcon,0},
3280 {SMBtdis,"SMBtdis",reply_tdis,0},
3281 {SMBexit,"SMBexit",reply_exit,0},
3282 {SMBioctl,"SMBioctl",reply_ioctl,0},
3283 {SMBecho,"SMBecho",reply_echo,0},
3284 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3285 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3286 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3287 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3288 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3289 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3290 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3291 {SMBopen,"SMBopen",reply_open,AS_USER},
3293 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3294 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3295 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3297 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3298 {SMBread,"SMBread",reply_read,AS_USER},
3299 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3300 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3301 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3302 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3303 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3304 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3306 /* this is a Pathworks specific call, allowing the
3307 changing of the root path */
3308 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3310 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3311 {SMBflush,"SMBflush",reply_flush,AS_USER},
3312 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3313 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3314 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3315 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3316 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3317 {SMBlock,"SMBlock",reply_lock,AS_USER},
3318 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3320 /* CORE+ PROTOCOL FOLLOWS */
3322 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3323 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3324 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3325 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3326 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3328 /* LANMAN1.0 PROTOCOL FOLLOWS */
3330 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3331 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3332 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3333 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3334 {SMBwritec,"SMBwritec",NULL,AS_USER},
3335 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3336 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3337 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3338 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3339 {SMBioctls,"SMBioctls",NULL,AS_USER},
3340 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3341 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3343 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3344 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3345 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3346 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3348 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3349 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3350 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3352 /* LANMAN2.0 PROTOCOL FOLLOWS */
3353 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3354 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3355 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3356 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3358 /* messaging routines */
3359 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3360 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3361 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3362 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3364 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3366 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3367 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3368 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3369 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3372 /****************************************************************************
3373 return a string containing the function name of a SMB command
3374 ****************************************************************************/
3375 char *smb_fn_name(int type)
3377 static char *unknown_name = "SMBunknown";
3378 static int num_smb_messages =
3379 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3382 for (match=0;match<num_smb_messages;match++)
3383 if (smb_messages[match].code == type)
3386 if (match == num_smb_messages)
3387 return(unknown_name);
3389 return(smb_messages[match].name);
3393 /****************************************************************************
3394 do a switch on the message type, and return the response size
3395 ****************************************************************************/
3396 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3400 static int num_smb_messages =
3401 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3405 struct timeval msg_start_time;
3406 struct timeval msg_end_time;
3407 static unsigned long total_time = 0;
3409 GetTimeOfDay(&msg_start_time);
3416 last_message = type;
3418 /* make sure this is an SMB packet */
3419 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3421 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3425 for (match=0;match<num_smb_messages;match++)
3426 if (smb_messages[match].code == type)
3429 if (match == num_smb_messages)
3431 DEBUG(0,("Unknown message type %d!\n",type));
3432 outsize = reply_unknown(inbuf,outbuf);
3436 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3437 if (smb_messages[match].fn)
3439 int cnum = SVAL(inbuf,smb_tid);
3440 int flags = smb_messages[match].flags;
3441 uint16 session_tag = SVAL(inbuf,smb_uid);
3443 /* does this protocol need to be run as root? */
3444 if (!(flags & AS_USER))
3447 /* does this protocol need to be run as the connected user? */
3448 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3449 if (flags & AS_GUEST)
3452 return(ERROR(ERRSRV,ERRinvnid));
3454 /* this code is to work around a bug is MS client 3 without
3455 introducing a security hole - it needs to be able to do
3456 print queue checks as guest if it isn't logged in properly */
3457 if (flags & AS_USER)
3460 /* does it need write permission? */
3461 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3462 return(ERROR(ERRSRV,ERRaccess));
3464 /* ipc services are limited */
3465 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3466 return(ERROR(ERRSRV,ERRaccess));
3468 /* load service specific parameters */
3469 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3470 return(ERROR(ERRSRV,ERRaccess));
3472 /* does this protocol need to be run as guest? */
3473 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3474 return(ERROR(ERRSRV,ERRaccess));
3478 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3482 outsize = reply_unknown(inbuf,outbuf);
3487 GetTimeOfDay(&msg_end_time);
3488 if (!(smb_messages[match].flags & TIME_INIT))
3490 smb_messages[match].time = 0;
3491 smb_messages[match].flags |= TIME_INIT;
3494 unsigned long this_time =
3495 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3496 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3497 smb_messages[match].time += this_time;
3498 total_time += this_time;
3500 DEBUG(2,("TIME %s %d usecs %g pct\n",
3501 smb_fn_name(type),smb_messages[match].time,
3502 (100.0*smb_messages[match].time) / total_time));
3509 /****************************************************************************
3510 construct a chained reply and add it to the already made reply
3511 **************************************************************************/
3512 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3514 static char *orig_inbuf;
3515 static char *orig_outbuf;
3516 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3517 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3518 char *inbuf2, *outbuf2;
3520 char inbuf_saved[smb_wct];
3521 char outbuf_saved[smb_wct];
3522 extern int chain_size;
3523 int wct = CVAL(outbuf,smb_wct);
3524 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3526 /* maybe its not chained */
3527 if (smb_com2 == 0xFF) {
3528 CVAL(outbuf,smb_vwv0) = 0xFF;
3532 if (chain_size == 0) {
3533 /* this is the first part of the chain */
3535 orig_outbuf = outbuf;
3538 /* we need to tell the client where the next part of the reply will be */
3539 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3540 CVAL(outbuf,smb_vwv0) = smb_com2;
3542 /* remember how much the caller added to the chain, only counting stuff
3543 after the parameter words */
3544 chain_size += outsize - smb_wct;
3546 /* work out pointers into the original packets. The
3547 headers on these need to be filled in */
3548 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3549 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3551 /* remember the original command type */
3552 smb_com1 = CVAL(orig_inbuf,smb_com);
3554 /* save the data which will be overwritten by the new headers */
3555 memcpy(inbuf_saved,inbuf2,smb_wct);
3556 memcpy(outbuf_saved,outbuf2,smb_wct);
3558 /* give the new packet the same header as the last part of the SMB */
3559 memmove(inbuf2,inbuf,smb_wct);
3561 /* create the in buffer */
3562 CVAL(inbuf2,smb_com) = smb_com2;
3564 /* create the out buffer */
3565 bzero(outbuf2,smb_size);
3566 set_message(outbuf2,0,0,True);
3567 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3569 memcpy(outbuf2+4,inbuf2+4,4);
3570 CVAL(outbuf2,smb_rcls) = SUCCESS;
3571 CVAL(outbuf2,smb_reh) = 0;
3572 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3574 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3575 SSVAL(outbuf2,smb_err,SUCCESS);
3576 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3577 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3578 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3579 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3581 DEBUG(3,("Chained message\n"));
3584 /* process the request */
3585 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3586 bufsize-chain_size);
3588 /* copy the new reply and request headers over the old ones, but
3589 preserve the smb_com field */
3590 memmove(orig_outbuf,outbuf2,smb_wct);
3591 CVAL(orig_outbuf,smb_com) = smb_com1;
3593 /* restore the saved data, being careful not to overwrite any
3594 data from the reply header */
3595 memcpy(inbuf2,inbuf_saved,smb_wct);
3597 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3598 if (ofs < 0) ofs = 0;
3599 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3607 /****************************************************************************
3608 construct a reply to the incoming packet
3609 ****************************************************************************/
3610 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3612 int type = CVAL(inbuf,smb_com);
3614 int msg_type = CVAL(inbuf,0);
3615 extern int chain_size;
3617 smb_last_time = time(NULL);
3622 bzero(outbuf,smb_size);
3625 return(reply_special(inbuf,outbuf));
3627 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3628 set_message(outbuf,0,0,True);
3630 memcpy(outbuf+4,inbuf+4,4);
3631 CVAL(outbuf,smb_rcls) = SUCCESS;
3632 CVAL(outbuf,smb_reh) = 0;
3633 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3635 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3636 SSVAL(outbuf,smb_err,SUCCESS);
3637 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3638 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3639 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3640 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3642 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3644 outsize += chain_size;
3647 smb_setlen(outbuf,outsize - 4);
3652 /****************************************************************************
3653 process commands from the client
3654 ****************************************************************************/
3655 static void process(void)
3657 static int trans_num = 0;
3661 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3662 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3663 if ((InBuffer == NULL) || (OutBuffer == NULL))
3666 InBuffer += SMB_ALIGNMENT;
3667 OutBuffer += SMB_ALIGNMENT;
3670 DEBUG(3,("priming nmbd\n"));
3673 ip = *interpret_addr2("localhost");
3674 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3676 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3686 int deadtime = lp_deadtime()*60;
3688 int last_keepalive=0;
3691 deadtime = DEFAULT_SMBD_TIMEOUT;
3693 if (lp_readprediction())
3694 do_read_prediction();
3697 extern pstring share_del_pending;
3698 if (*share_del_pending) {
3700 if (!unlink(share_del_pending))
3701 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3703 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3704 share_del_pending[0] = 0;
3708 if (share_mode_pending) {
3710 check_share_modes();
3711 share_mode_pending=False;
3716 for (counter=SMBD_SELECT_LOOP;
3717 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3718 counter += SMBD_SELECT_LOOP)
3722 BOOL allidle = True;
3723 extern int keepalive;
3725 if (smb_read_error == READ_EOF) {
3726 DEBUG(3,("end of file from client\n"));
3730 if (smb_read_error == READ_ERROR) {
3731 DEBUG(3,("receive_smb error (%s) exiting\n",
3738 /* become root again if waiting */
3741 /* check for smb.conf reload */
3742 if (!(counter%SMBD_RELOAD_CHECK))
3743 reload_services(True);
3745 /* check the share modes every 10 secs */
3746 if (!(counter%SHARE_MODES_CHECK))
3747 check_share_modes();
3749 /* clean the share modes every 5 minutes */
3750 if (!(counter%SHARE_MODES_CLEAN))
3751 clean_share_modes();
3753 /* automatic timeout if all connections are closed */
3754 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3755 DEBUG(2,("%s Closing idle connection\n",timestring()));
3759 if (keepalive && (counter-last_keepalive)>keepalive) {
3760 extern int password_client;
3761 if (!send_keepalive(Client)) {
3762 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3765 /* also send a keepalive to the password server if its still
3767 if (password_client != -1)
3768 send_keepalive(password_client);
3769 last_keepalive = counter;
3772 /* check for connection timeouts */
3773 for (i=0;i<MAX_CONNECTIONS;i++)
3774 if (Connections[i].open)
3776 /* close dirptrs on connections that are idle */
3777 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3780 if (Connections[i].num_files_open > 0 ||
3781 (t-Connections[i].lastused)<deadtime)
3785 if (allidle && num_connections_open>0) {
3786 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3791 msg_type = CVAL(InBuffer,0);
3792 msg_flags = CVAL(InBuffer,1);
3793 type = CVAL(InBuffer,smb_com);
3795 len = smb_len(InBuffer);
3797 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3801 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3804 if(trans_num == 1 && VT_Check(InBuffer)) {
3814 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3817 if (CVAL(OutBuffer,0) == 0)
3818 show_msg(OutBuffer);
3820 if (nread != smb_len(OutBuffer) + 4)
3822 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3824 smb_len(OutBuffer)));
3827 send_smb(Client,OutBuffer);
3834 /****************************************************************************
3835 initialise connect, service and file structs
3836 ****************************************************************************/
3837 static void init_structs(void )
3840 get_myname(myhostname,NULL);
3842 for (i=0;i<MAX_CONNECTIONS;i++)
3844 Connections[i].open = False;
3845 Connections[i].num_files_open=0;
3846 Connections[i].lastused=0;
3847 Connections[i].used=False;
3848 string_init(&Connections[i].user,"");
3849 string_init(&Connections[i].dirpath,"");
3850 string_init(&Connections[i].connectpath,"");
3851 string_init(&Connections[i].origpath,"");
3854 for (i=0;i<MAX_OPEN_FILES;i++)
3856 Files[i].open = False;
3857 string_init(&Files[i].name,"");
3861 for (i=0;i<MAX_OPEN_FILES;i++)
3863 file_fd_struct *fd_ptr = &FileFd[i];
3864 fd_ptr->ref_count = 0;
3865 fd_ptr->dev = (int32)-1;
3866 fd_ptr->inode = (int32)-1;
3868 fd_ptr->fd_readonly = -1;
3869 fd_ptr->fd_writeonly = -1;
3870 fd_ptr->real_open_flags = -1;
3876 /****************************************************************************
3877 usage on the program
3878 ****************************************************************************/
3879 static void usage(char *pname)
3881 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3883 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3884 printf("Version %s\n",VERSION);
3885 printf("\t-D become a daemon\n");
3886 printf("\t-p port listen on the specified port\n");
3887 printf("\t-d debuglevel set the debuglevel\n");
3888 printf("\t-l log basename. Basename for log/debug files\n");
3889 printf("\t-s services file. Filename of services file\n");
3890 printf("\t-P passive only\n");
3891 printf("\t-a overwrite log file, don't append\n");
3896 /****************************************************************************
3898 ****************************************************************************/
3899 int main(int argc,char *argv[])
3901 extern BOOL append_log;
3902 /* shall I run as a daemon */
3903 BOOL is_daemon = False;
3904 int port = SMB_PORT;
3906 extern char *optarg;
3907 char pidFile[100] = { 0 };
3909 #ifdef NEED_AUTH_PARAMETERS
3910 set_auth_parameters(argc,argv);
3921 strcpy(debugf,SMBLOGFILE);
3923 setup_logging(argv[0],False);
3925 charset_initialise();
3927 /* make absolutely sure we run as root - to handle cases whre people
3928 are crazy enough to have it setuid */
3938 fault_setup(exit_server);
3939 signal(SIGTERM , SIGNAL_CAST dflt_sig);
3941 /* we want total control over the permissions on created files,
3942 so set our umask to 0 */
3949 /* this is for people who can't start the program correctly */
3950 while (argc > 1 && (*argv[1] != '-'))
3956 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
3960 strncpy(pidFile, optarg, sizeof(pidFile));
3963 strcpy(user_socket_options,optarg);
3966 strcpy(scope,optarg);
3970 extern BOOL passive;
3975 strcpy(servicesf,optarg);
3978 strcpy(debugf,optarg);
3982 extern BOOL append_log;
3983 append_log = !append_log;
3993 DEBUGLEVEL = atoi(optarg);
3996 port = atoi(optarg);
4009 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4010 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4012 #ifndef NO_GETRLIMIT
4013 #ifdef RLIMIT_NOFILE
4016 getrlimit(RLIMIT_NOFILE, &rlp);
4017 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4018 setrlimit(RLIMIT_NOFILE, &rlp);
4019 getrlimit(RLIMIT_NOFILE, &rlp);
4020 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4026 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4027 getuid(),getgid(),geteuid(),getegid()));
4029 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4031 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4037 if (!reload_services(False))
4040 #ifndef NO_SIGNAL_TEST
4041 signal(SIGHUP,SIGNAL_CAST sig_hup);
4044 DEBUG(3,("%s loaded services\n",timestring()));
4046 if (!is_daemon && !is_a_socket(0))
4048 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4054 DEBUG(3,("%s becoming a daemon\n",timestring()));
4063 if ((fd = open(pidFile,
4064 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4066 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4069 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4071 DEBUG(0,("ERROR: smbd is already running\n"));
4074 sprintf(buf, "%u\n", (unsigned int) getpid());
4075 if (write(fd, buf, strlen(buf)) < 0)
4077 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4080 /* Leave pid file open & locked for the duration... */
4083 if (!open_sockets(is_daemon,port))
4086 #if FAST_SHARE_MODES
4087 if (!start_share_mode_mgmt())
4091 /* possibly reload the services file. */
4092 reload_services(True);
4094 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4098 if (sys_chroot(lp_rootdir()) == 0)
4099 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4105 exit_server("normal exit");