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;
33 BOOL share_mode_pending = False;
35 /* the last message the was processed */
36 int last_message = -1;
38 /* a useful macro to debug the last message processed */
39 #define LAST_MESSAGE() smb_fn_name(last_message)
42 extern int DEBUGLEVEL;
43 extern int case_default;
44 extern BOOL case_sensitive;
45 extern BOOL case_preserve;
46 extern BOOL use_mangled_map;
47 extern BOOL short_case_preserve;
48 extern BOOL case_mangle;
49 extern time_t smb_last_time;
51 extern int smb_read_error;
53 extern pstring user_socket_options;
55 connection_struct Connections[MAX_CONNECTIONS];
56 files_struct Files[MAX_OPEN_FILES];
60 int maxxmit = BUFFER_SIZE;
64 /* a fnum to use when chaining */
67 /* number of open connections */
68 static int num_connections_open = 0;
70 extern fstring remote_machine;
73 /* these can be set by some functions to override the error codes */
74 int unix_ERR_class=SUCCESS;
78 extern int extra_time_offset;
80 extern pstring myhostname;
82 static int find_free_connection(int hash);
84 /* for readability... */
85 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
86 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
87 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
88 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
89 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
93 /****************************************************************************
94 change a dos mode to a unix mode
95 base permission for files:
96 everybody gets read bit set
97 dos readonly is represented in unix by removing everyone's write bit
98 dos archive is represented in unix by the user's execute bit
99 dos system is represented in unix by the group's execute bit
100 dos hidden is represented in unix by the other's execute bit
101 base permission for directories:
102 dos directory is represented in unix by unix's dir bit and the exec bit
103 ****************************************************************************/
104 mode_t unix_mode(int cnum,int dosmode)
106 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
108 if ( !IS_DOS_READONLY(dosmode) )
109 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
111 if (IS_DOS_DIR(dosmode))
112 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
114 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
117 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
120 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
123 result &= CREATE_MODE(cnum);
128 /****************************************************************************
129 change a unix mode to a dos mode
130 ****************************************************************************/
131 int dos_mode(int cnum,char *path,struct stat *sbuf)
134 extern struct current_user current_user;
136 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
137 if (!((sbuf->st_mode & S_IWOTH) ||
138 Connections[cnum].admin_user ||
139 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
140 ((sbuf->st_mode & S_IWGRP) &&
141 in_group(sbuf->st_gid,current_user.gid,
142 current_user.ngroups,current_user.igroups))))
145 if ((sbuf->st_mode & S_IWUSR) == 0)
149 if ((sbuf->st_mode & S_IXUSR) != 0)
152 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
155 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
158 if (S_ISDIR(sbuf->st_mode))
159 result = aDIR | (result & aRONLY);
162 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
166 /* hide files with a name starting with a . */
167 if (lp_hide_dot_files(SNUM(cnum)))
169 char *p = strrchr(path,'/');
175 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
183 /*******************************************************************
184 chmod a file - but preserve some bits
185 ********************************************************************/
186 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
195 if (sys_stat(fname,st)) return(-1);
198 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
200 if (dos_mode(cnum,fname,st) == dosmode) return(0);
202 unixmode = unix_mode(cnum,dosmode);
204 /* preserve the s bits */
205 mask |= (S_ISUID | S_ISGID);
207 /* preserve the t bit */
212 /* possibly preserve the x bits */
213 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
214 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
215 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
217 unixmode |= (st->st_mode & mask);
219 /* if we previously had any r bits set then leave them alone */
220 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
221 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
225 /* if we previously had any w bits set then leave them alone
226 if the new mode is not rdonly */
227 if (!IS_DOS_READONLY(dosmode) &&
228 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
229 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
233 return(chmod(fname,unixmode));
237 /****************************************************************************
238 check if two filenames are equal
240 this needs to be careful about whether we are case sensitive
241 ****************************************************************************/
242 static BOOL fname_equal(char *name1, char *name2)
244 int l1 = strlen(name1);
245 int l2 = strlen(name2);
247 /* handle filenames ending in a single dot */
248 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
252 ret = fname_equal(name1,name2);
257 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
261 ret = fname_equal(name1,name2);
266 /* now normal filename handling */
268 return(strcmp(name1,name2) == 0);
270 return(strequal(name1,name2));
274 /****************************************************************************
275 mangle the 2nd name and check if it is then equal to the first name
276 ****************************************************************************/
277 static BOOL mangled_equal(char *name1, char *name2)
284 strcpy(tmpname,name2);
285 mangle_name_83(tmpname);
287 return(strequal(name1,tmpname));
291 /****************************************************************************
292 scan a directory to find a filename, matching without case sensitivity
294 If the name looks like a mangled name then try via the mangling functions
295 ****************************************************************************/
296 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
303 mangled = is_mangled(name);
305 /* handle null paths */
309 if (docache && (dname = DirCacheCheck(path,name,snum))) {
315 check_mangled_stack(name);
317 /* open the directory */
318 if (!(cur_dir = OpenDir(path)))
320 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
324 /* now scan for matching names */
325 while ((dname = ReadDirName(cur_dir)))
328 (strequal(dname,".") || strequal(dname,"..")))
332 if (!name_map_mangle(name2,False,snum)) continue;
334 if ((mangled && mangled_equal(name,name2))
335 || fname_equal(name, name2))
337 /* we've found the file, change it's name and return */
338 if (docache) DirCacheAdd(path,name,dname,snum);
349 /****************************************************************************
350 This routine is called to convert names from the dos namespace to unix
351 namespace. It needs to handle any case conversions, mangling, format
354 We assume that we have already done a chdir() to the right "root" directory
357 The function will return False if some part of the name except for the last
358 part cannot be resolved
359 ****************************************************************************/
360 BOOL unix_convert(char *name,int cnum)
368 /* convert to basic unix format - removing \ chars and cleaning it up */
370 unix_clean_name(name);
372 if (!case_sensitive &&
373 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
376 /* names must be relative to the root of the service - trim any leading /.
377 also trim trailing /'s */
378 trim_string(name,"/","/");
380 /* check if it's a printer file */
381 if (Connections[cnum].printer)
383 if ((! *name) || strchr(name,'/') || !is_8_3(name))
387 sprintf(name2,"%.6s.XXXXXX",remote_machine);
388 /* sanitise the name */
389 for (s=name2 ; *s ; s++)
390 if (!issafe(*s)) *s = '_';
391 strcpy(name,(char *)mktemp(name2));
396 /* stat the name - if it exists then we are all done! */
397 if (sys_stat(name,&st) == 0)
400 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
402 /* a special case - if we don't have any mangling chars and are case
403 sensitive then searching won't help */
404 if (case_sensitive && !is_mangled(name) &&
405 !lp_strip_dot() && !use_mangled_map)
408 /* now we need to recursively match the name against the real
409 directory structure */
412 while (strncmp(start,"./",2) == 0)
415 /* now match each part of the path name separately, trying the names
416 as is first, then trying to scan the directory for matching names */
417 for (;start;start = (end?end+1:(char *)NULL))
419 /* pinpoint the end of this section of the filename */
420 end = strchr(start, '/');
422 /* chop the name at this point */
425 /* check if the name exists up to this point */
426 if (sys_stat(name, &st) == 0)
428 /* it exists. it must either be a directory or this must be
429 the last part of the path for it to be OK */
430 if (end && !(st.st_mode & S_IFDIR))
432 /* an intermediate part of the name isn't a directory */
433 DEBUG(5,("Not a dir %s\n",start));
444 /* remember the rest of the pathname so it can be restored
446 if (end) strcpy(rest,end+1);
449 /* try to find this part of the path in the directory */
450 if (strchr(start,'?') || strchr(start,'*') ||
451 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
455 /* an intermediate part of the name can't be found */
456 DEBUG(5,("Intermediate not found %s\n",start));
461 /* just the last part of the name doesn't exist */
462 /* we may need to strupper() or strlower() it in case
463 this conversion is being used for file creation
465 /* if the filename is of mixed case then don't normalise it */
466 if (!case_preserve &&
467 (!strhasupper(start) || !strhaslower(start)))
470 /* check on the mangled stack to see if we can recover the
471 base of the filename */
472 if (is_mangled(start))
473 check_mangled_stack(start);
475 DEBUG(5,("New file %s\n",start));
479 /* restore the rest of the string */
482 strcpy(start+strlen(start)+1,rest);
483 end = start + strlen(start);
487 /* add to the dirpath that we have resolved so far */
488 if (*dirpath) strcat(dirpath,"/");
489 strcat(dirpath,start);
491 /* restore the / that we wiped out earlier */
495 /* the name has been resolved */
496 DEBUG(5,("conversion finished %s\n",name));
501 /****************************************************************************
502 normalise for DOS usage
503 ****************************************************************************/
504 static void disk_norm(int *bsize,int *dfree,int *dsize)
506 /* check if the disk is beyond the max disk size */
507 int maxdisksize = lp_maxdisksize();
509 /* convert to blocks - and don't overflow */
510 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
511 if (*dsize > maxdisksize) *dsize = maxdisksize;
512 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
517 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
522 if (*bsize > WORDMAX )
525 if (*dsize > WORDMAX)
527 if (*dfree > WORDMAX)
534 /****************************************************************************
535 return number of 1K blocks available on a path and total number
536 ****************************************************************************/
537 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
539 char *df_command = lp_dfree_command();
553 if (disk_quotas(path, bsize, dfree, dsize))
555 disk_norm(bsize,dfree,dsize);
556 return(((*bsize)/1024)*(*dfree));
561 /* possibly use system() to get the result */
562 if (df_command && *df_command)
568 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
569 sprintf(syscmd,"%s %s",df_command,path);
570 standard_sub_basic(syscmd);
572 ret = smbrun(syscmd,outfile);
573 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
576 FILE *f = fopen(outfile,"r");
582 fscanf(f,"%d %d %d",dsize,dfree,bsize);
586 DEBUG(0,("Can't open %s\n",outfile));
590 disk_norm(bsize,dfree,dsize);
591 return(((*bsize)/1024)*(*dfree));
595 DEBUG(1,("Warning - no statfs function\n"));
599 if (statfs(path,&fs,sizeof(fs),0) != 0)
602 if (statvfs(path, &fs))
605 if (statfs(path,&fs,sizeof(fs)) == -1)
607 if (statfs(path,&fs) == -1)
609 #endif /* USE_STATVFS */
612 DEBUG(3,("dfree call failed code errno=%d\n",errno));
616 return(((*bsize)/1024)*(*dfree));
621 *dfree = fs.fd_req.bfree;
622 *dsize = fs.fd_req.btot;
625 *bsize = fs.f_frsize;
628 /* eg: osf1 has f_fsize = fundamental filesystem block size,
629 f_bsize = optimal transfer block size (MX: 94-04-19) */
634 #endif /* USE_STATVFS */
639 *dfree = fs.f_bavail;
641 *dsize = fs.f_blocks;
644 #if defined(SCO) || defined(ISC) || defined(MIPS)
648 /* handle rediculous bsize values - some OSes are broken */
649 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
651 disk_norm(bsize,dfree,dsize);
657 DEBUG(0,("dfree seems to be broken on your system\n"));
658 *dsize = 20*1024*1024/(*bsize);
659 *dfree = MAX(1,*dfree);
661 return(((*bsize)/1024)*(*dfree));
666 /****************************************************************************
667 wrap it to get filenames right
668 ****************************************************************************/
669 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
671 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
676 /****************************************************************************
677 check a filename - possibly caling reducename
679 This is called by every routine before it allows an operation on a filename.
680 It does any final confirmation necessary to ensure that the filename is
681 a valid one for the user to access.
682 ****************************************************************************/
683 BOOL check_name(char *name,int cnum)
689 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
691 DEBUG(5,("check_name on %s failed\n",name));
696 /****************************************************************************
697 check a filename - possibly caling reducename
698 ****************************************************************************/
699 static void check_for_pipe(char *fname)
701 /* special case of pipe opens */
705 if (strstr(s,"pipe/"))
707 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
708 unix_ERR_class = ERRSRV;
709 unix_ERR_code = ERRaccess;
714 /****************************************************************************
716 ****************************************************************************/
717 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
721 Files[fnum].open = False;
725 strcpy(fname,fname1);
727 /* check permissions */
728 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
730 DEBUG(3,("Permission denied opening %s\n",fname));
731 check_for_pipe(fname);
735 /* this handles a bug in Win95 - it doesn't say to create the file when it
737 if (Connections[cnum].printer)
741 if (flags == O_WRONLY)
742 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
746 /* XXXX - is this OK?? */
747 /* this works around a utime bug but can cause other problems */
748 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
753 Files[fnum].fd = sys_open(fname,flags,mode);
755 if ((Files[fnum].fd>=0) &&
756 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
761 p = strrchr(dname,'/');
763 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
764 lp_minprintspace(SNUM(cnum))) {
765 close(Files[fnum].fd);
774 /* Fix for files ending in '.' */
775 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
776 (strchr(fname,'.')==NULL))
779 Files[fnum].fd = sys_open(fname,flags,mode);
782 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
783 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
786 char *p = strrchr(fname, '/');
788 if (p == fname) /* name is "/xxx" */
790 max_len = pathconf("/", _PC_NAME_MAX);
793 else if ((p == NULL) || (p == fname))
796 max_len = pathconf(".", _PC_NAME_MAX);
801 max_len = pathconf(fname, _PC_NAME_MAX);
805 if (strlen(p) > max_len)
807 char tmp = p[max_len];
810 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
816 if (Files[fnum].fd < 0)
818 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
819 fname,strerror(errno),flags));
820 check_for_pipe(fname);
824 if (Files[fnum].fd >= 0)
827 Connections[cnum].num_files_open++;
828 fstat(Files[fnum].fd,&st);
829 Files[fnum].mode = st.st_mode;
830 Files[fnum].open_time = time(NULL);
831 Files[fnum].size = 0;
832 Files[fnum].pos = -1;
833 Files[fnum].open = True;
834 Files[fnum].mmap_ptr = NULL;
835 Files[fnum].mmap_size = 0;
836 Files[fnum].can_lock = True;
837 Files[fnum].can_read = ((flags & O_WRONLY)==0);
838 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
839 Files[fnum].share_mode = 0;
840 Files[fnum].share_pending = False;
841 Files[fnum].print_file = Connections[cnum].printer;
842 Files[fnum].modified = False;
843 Files[fnum].cnum = cnum;
844 string_set(&Files[fnum].name,fname);
845 Files[fnum].wbmpx_ptr = NULL;
848 * If the printer is marked as postscript output a leading
849 * file identifier to ensure the file is treated as a raw
851 * This has a similar effect as CtrlD=0 in WIN.INI file.
852 * tim@fsg.com 09/06/94
854 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
855 Files[fnum].can_write)
857 DEBUG(3,("Writing postscript line\n"));
858 write_file(fnum,"%!\n",3);
861 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
862 timestring(),Connections[cnum].user,fname,
863 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
864 Connections[cnum].num_files_open,fnum));
869 /* mmap it if read-only */
870 if (!Files[fnum].can_write)
872 Files[fnum].mmap_size = file_size(fname);
873 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
874 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
876 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
878 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
879 Files[fnum].mmap_ptr = NULL;
885 /*******************************************************************
887 ********************************************************************/
888 void sync_file(int fnum)
891 fsync(Files[fnum].fd);
895 /****************************************************************************
896 run a file if it is a magic script
897 ****************************************************************************/
898 static void check_magic(int fnum,int cnum)
900 if (!*lp_magicscript(SNUM(cnum)))
903 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
907 if (!(p = strrchr(Files[fnum].name,'/')))
908 p = Files[fnum].name;
912 if (!strequal(lp_magicscript(SNUM(cnum)),p))
918 pstring magic_output;
920 strcpy(fname,Files[fnum].name);
922 if (*lp_magicoutput(SNUM(cnum)))
923 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
925 sprintf(magic_output,"%s.out",fname);
928 ret = smbrun(fname,magic_output);
929 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
935 /****************************************************************************
936 close a file - possibly invalidating the read prediction
937 ****************************************************************************/
938 void close_file(int fnum)
940 int cnum = Files[fnum].cnum;
941 invalidate_read_prediction(Files[fnum].fd);
942 Files[fnum].open = False;
943 Connections[cnum].num_files_open--;
944 if(Files[fnum].wbmpx_ptr)
946 free((char *)Files[fnum].wbmpx_ptr);
947 Files[fnum].wbmpx_ptr = NULL;
951 if(Files[fnum].mmap_ptr)
953 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
954 Files[fnum].mmap_ptr = NULL;
958 if (lp_share_modes(SNUM(cnum)))
959 del_share_mode(fnum);
961 close(Files[fnum].fd);
963 /* NT uses smbclose to start a print - weird */
964 if (Files[fnum].print_file)
967 /* check for magic scripts */
968 check_magic(fnum,cnum);
970 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
971 timestring(),Connections[cnum].user,Files[fnum].name,
972 Connections[cnum].num_files_open));
975 enum {AFAIL,AREAD,AWRITE,AALL};
977 /*******************************************************************
978 reproduce the share mode access table
979 ********************************************************************/
980 static int access_table(int new_deny,int old_deny,int old_mode,
981 int share_pid,char *fname)
983 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
985 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
986 if (old_deny == new_deny && share_pid == getpid())
989 if (old_mode == 0) return(AREAD);
991 /* the new smbpub.zip spec says that if the file extension is
992 .com, .dll, .exe or .sym then allow the open. I will force
993 it to read-only as this seems sensible although the spec is
994 a little unclear on this. */
995 if ((fname = strrchr(fname,'.'))) {
996 if (strequal(fname,".com") ||
997 strequal(fname,".dll") ||
998 strequal(fname,".exe") ||
999 strequal(fname,".sym"))
1009 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1010 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1011 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1014 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1015 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1016 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1019 if (old_deny==DENY_WRITE) return(AREAD);
1020 if (old_deny==DENY_READ) return(AWRITE);
1021 if (old_deny==DENY_NONE) return(AALL);
1027 /*******************************************************************
1028 check if the share mode on a file allows it to be deleted or unlinked
1029 return True if sharing doesn't prevent the operation
1030 ********************************************************************/
1031 BOOL check_file_sharing(int cnum,char *fname)
1034 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1036 if (!pid || !share_mode) return(True);
1038 if (share_mode == DENY_DOS)
1039 return(pid == getpid());
1041 /* XXXX exactly what share mode combinations should be allowed for
1042 deleting/renaming? */
1046 /****************************************************************************
1048 Helper for open_file_shared.
1049 Truncate a file after checking locking; close file if locked.
1050 **************************************************************************/
1051 static void truncate_unless_locked(int fnum, int cnum)
1053 if (Files[fnum].can_write){
1054 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1057 unix_ERR_class = ERRDOS;
1058 unix_ERR_code = ERRlock;
1061 ftruncate(Files[fnum].fd,0);
1066 /****************************************************************************
1067 open a file with a share mode
1068 ****************************************************************************/
1069 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1070 int mode,int *Access,int *action)
1074 int deny_mode = (share_mode>>4)&7;
1076 BOOL file_existed = file_exist(fname,&sbuf);
1077 BOOL fcbopen = False;
1080 Files[fnum].open = False;
1081 Files[fnum].fd = -1;
1083 /* this is for OS/2 EAs - try and say we don't support them */
1084 if (strstr(fname,".+,;=[].")) {
1085 unix_ERR_class = ERRDOS;
1086 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1090 if ((ofun & 0x3) == 0 && file_existed) {
1097 if ((ofun & 0x3) == 2)
1100 /* note that we ignore the append flag as
1101 append does not mean the same thing under dos and unix */
1103 switch (share_mode&0xF)
1120 if (flags != O_RDONLY && file_existed &&
1121 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1129 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1130 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1135 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1137 if (lp_share_modes(SNUM(cnum))) {
1141 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1144 /* someone else has a share lock on it, check to see
1146 int old_open_mode = old_share&0xF;
1147 int old_deny_mode = (old_share>>4)&7;
1149 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1150 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1151 deny_mode,old_deny_mode,old_open_mode,fname));
1153 unix_ERR_class = ERRDOS;
1154 unix_ERR_code = ERRbadshare;
1159 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1162 if ((access_allowed == AFAIL) ||
1163 (access_allowed == AREAD && flags == O_WRONLY) ||
1164 (access_allowed == AWRITE && flags == O_RDONLY)) {
1165 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1166 deny_mode,old_deny_mode,old_open_mode,
1170 unix_ERR_class = ERRDOS;
1171 unix_ERR_code = ERRbadshare;
1175 if (access_allowed == AREAD)
1178 if (access_allowed == AWRITE)
1184 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1185 flags,flags2,mode));
1187 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1188 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1190 open_file(fnum,cnum,fname,flags,mode);
1193 if (Files[fnum].open) {
1207 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1208 Files[fnum].share_pending = True;
1211 (*Access) = open_mode;
1215 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1216 if (!file_existed) *action = 2;
1217 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1221 share_mode_pending = True;
1223 if ((flags2&O_TRUNC) && file_existed)
1224 truncate_unless_locked(fnum,cnum);
1230 /*******************************************************************
1231 check for files that we should now set our share modes on
1232 ********************************************************************/
1233 static void check_share_modes(void)
1236 for (i=0;i<MAX_OPEN_FILES;i++)
1237 if(Files[i].open && Files[i].share_pending) {
1238 if (lp_share_modes(SNUM(Files[i].cnum))) {
1240 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1242 set_share_mode(i,Files[i].share_mode);
1243 Files[i].share_pending = False;
1246 Files[i].share_pending = False;
1252 /****************************************************************************
1253 seek a file. Try to avoid the seek if possible
1254 ****************************************************************************/
1255 int seek_file(int fnum,int pos)
1258 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1261 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1262 return(Files[fnum].pos);
1265 /****************************************************************************
1267 ****************************************************************************/
1268 int read_file(int fnum,char *data,int pos,int n)
1272 if (!Files[fnum].can_write)
1274 ret = read_predict(Files[fnum].fd,pos,data,NULL,n);
1282 if (Files[fnum].mmap_ptr)
1284 int num = MIN(n,Files[fnum].mmap_size-pos);
1287 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1299 if (seek_file(fnum,pos) != pos)
1301 DEBUG(3,("Failed to seek to %d\n",pos));
1306 readret = read(Files[fnum].fd,data,n);
1307 if (readret > 0) ret += readret;
1314 /****************************************************************************
1316 ****************************************************************************/
1317 int write_file(int fnum,char *data,int n)
1319 if (!Files[fnum].can_write) {
1324 if (!Files[fnum].modified) {
1326 Files[fnum].modified = True;
1327 if (fstat(Files[fnum].fd,&st) == 0) {
1328 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1329 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1330 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1335 return(write_data(Files[fnum].fd,data,n));
1339 /****************************************************************************
1340 load parameters specific to a connection/service
1341 ****************************************************************************/
1342 BOOL become_service(int cnum,BOOL do_chdir)
1344 extern char magic_char;
1345 static int last_cnum = -1;
1348 if (!OPEN_CNUM(cnum))
1354 Connections[cnum].lastused = smb_last_time;
1359 ChDir(Connections[cnum].connectpath) != 0 &&
1360 ChDir(Connections[cnum].origpath) != 0)
1362 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1363 Connections[cnum].connectpath,cnum));
1367 if (cnum == last_cnum)
1372 case_default = lp_defaultcase(snum);
1373 case_preserve = lp_preservecase(snum);
1374 short_case_preserve = lp_shortpreservecase(snum);
1375 case_mangle = lp_casemangle(snum);
1376 case_sensitive = lp_casesensitive(snum);
1377 magic_char = lp_magicchar(snum);
1378 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1383 /****************************************************************************
1384 find a service entry
1385 ****************************************************************************/
1386 int find_service(char *service)
1390 string_sub(service,"\\","/");
1392 iService = lp_servicenumber(service);
1394 /* now handle the special case of a home directory */
1397 char *phome_dir = get_home_dir(service);
1398 DEBUG(3,("checking for home directory %s gave %s\n",service,
1399 phome_dir?phome_dir:"(NULL)"));
1403 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1405 lp_add_home(service,iHomeService,phome_dir);
1406 iService = lp_servicenumber(service);
1411 /* If we still don't have a service, attempt to add it as a printer. */
1414 int iPrinterService;
1416 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1420 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1422 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1424 DEBUG(3,("%s is a valid printer name\n", service));
1425 DEBUG(3,("adding %s as a printer service\n", service));
1426 lp_add_printer(service,iPrinterService);
1427 iService = lp_servicenumber(service);
1429 DEBUG(0,("failed to add %s as a printer service!\n", service));
1432 DEBUG(3,("%s is not a valid printer name\n", service));
1436 /* just possibly it's a default service? */
1439 char *defservice = lp_defaultservice();
1440 if (defservice && *defservice && !strequal(defservice,service)) {
1441 iService = find_service(defservice);
1442 if (iService >= 0) {
1443 string_sub(service,"_","/");
1444 iService = lp_add_service(service,iService);
1450 if (!VALID_SNUM(iService))
1452 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1457 DEBUG(3,("find_service() failed to find service %s\n", service));
1463 /****************************************************************************
1464 create an error packet from a cached error.
1465 ****************************************************************************/
1466 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1468 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1470 int32 eclass = wbmpx->wr_errclass;
1471 int32 err = wbmpx->wr_error;
1473 /* We can now delete the auxiliary struct */
1474 free((char *)wbmpx);
1475 Files[fnum].wbmpx_ptr = NULL;
1476 return error_packet(inbuf,outbuf,eclass,err,line);
1485 } unix_smb_errmap[] =
1487 {EPERM,ERRDOS,ERRnoaccess},
1488 {EACCES,ERRDOS,ERRnoaccess},
1489 {ENOENT,ERRDOS,ERRbadfile},
1490 {EIO,ERRHRD,ERRgeneral},
1491 {EBADF,ERRSRV,ERRsrverror},
1492 {EINVAL,ERRSRV,ERRsrverror},
1493 {EEXIST,ERRDOS,ERRfilexists},
1494 {ENFILE,ERRDOS,ERRnofids},
1495 {EMFILE,ERRDOS,ERRnofids},
1496 {ENOSPC,ERRHRD,ERRdiskfull},
1498 {EDQUOT,ERRHRD,ERRdiskfull},
1501 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1504 {EXDEV,ERRDOS,ERRdiffdevice},
1506 {EROFS,ERRHRD,ERRnowrite},
1511 /****************************************************************************
1512 create an error packet from errno
1513 ****************************************************************************/
1514 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1516 int eclass=def_class;
1520 if (unix_ERR_class != SUCCESS)
1522 eclass = unix_ERR_class;
1523 ecode = unix_ERR_code;
1524 unix_ERR_class = SUCCESS;
1529 while (unix_smb_errmap[i].smbclass != 0)
1531 if (unix_smb_errmap[i].unixerror == errno)
1533 eclass = unix_smb_errmap[i].smbclass;
1534 ecode = unix_smb_errmap[i].smbcode;
1541 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1545 /****************************************************************************
1546 create an error packet. Normally called using the ERROR() macro
1547 ****************************************************************************/
1548 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1550 int outsize = set_message(outbuf,0,0,True);
1552 cmd = CVAL(inbuf,smb_com);
1554 CVAL(outbuf,smb_rcls) = error_class;
1555 SSVAL(outbuf,smb_err,error_code);
1557 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1560 (int)CVAL(inbuf,smb_com),
1561 smb_fn_name(CVAL(inbuf,smb_com)),
1566 DEBUG(3,("error string = %s\n",strerror(errno)));
1572 #ifndef SIGCLD_IGNORE
1573 /****************************************************************************
1574 this prevents zombie child processes
1575 ****************************************************************************/
1576 static int sig_cld()
1578 static int depth = 0;
1581 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1588 DEBUG(5,("got SIGCLD\n"));
1591 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1595 /* Stevens, Adv. Unix Prog. says that on system V you must call
1596 wait before reinstalling the signal handler, because the kernel
1597 calls the handler from within the signal-call when there is a
1598 child that has exited. This would lead to an infinite recursion
1599 if done vice versa. */
1601 #ifndef DONT_REINSTALL_SIG
1602 #ifdef SIGCLD_IGNORE
1603 signal(SIGCLD, SIG_IGN);
1605 signal(SIGCLD, SIGNAL_CAST sig_cld);
1610 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1613 BlockSignals(False);
1618 /****************************************************************************
1619 this is called when the client exits abruptly
1620 **************************************************************************/
1621 static int sig_pipe()
1623 exit_server("Got sigpipe\n");
1627 /****************************************************************************
1628 open the socket communication
1629 ****************************************************************************/
1630 static BOOL open_sockets(BOOL is_daemon,int port)
1637 struct sockaddr addr;
1638 int in_addrlen = sizeof(addr);
1641 #ifdef SIGCLD_IGNORE
1642 signal(SIGCLD, SIG_IGN);
1644 signal(SIGCLD, SIGNAL_CAST sig_cld);
1647 /* open an incoming socket */
1648 s = open_socket_in(SOCK_STREAM, port, 0);
1652 /* ready to listen */
1653 if (listen(s, 5) == -1)
1655 DEBUG(0,("listen: %s",strerror(errno)));
1660 /* now accept incoming connections - forking a new process
1661 for each incoming connection */
1662 DEBUG(2,("waiting for a connection\n"));
1665 Client = accept(s,&addr,&in_addrlen);
1667 if (Client == -1 && errno == EINTR)
1672 DEBUG(0,("accept: %s",strerror(errno)));
1676 #ifdef NO_FORK_DEBUG
1677 #ifndef NO_SIGNAL_TEST
1678 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1679 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1683 if (Client != -1 && fork()==0)
1685 #ifndef NO_SIGNAL_TEST
1686 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1687 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1689 /* close the listening socket */
1692 /* close our standard file descriptors */
1695 set_socket_options(Client,"SO_KEEPALIVE");
1696 set_socket_options(Client,user_socket_options);
1700 close(Client); /* The parent doesn't need this socket */
1706 /* We will abort gracefully when the client or remote system
1708 #ifndef NO_SIGNAL_TEST
1709 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1713 /* close our standard file descriptors */
1716 set_socket_options(Client,"SO_KEEPALIVE");
1717 set_socket_options(Client,user_socket_options);
1724 /****************************************************************************
1725 check if a snum is in use
1726 ****************************************************************************/
1727 BOOL snum_used(int snum)
1730 for (i=0;i<MAX_CONNECTIONS;i++)
1731 if (OPEN_CNUM(i) && (SNUM(i) == snum))
1736 /****************************************************************************
1737 reload the services file
1738 **************************************************************************/
1739 BOOL reload_services(BOOL test)
1746 strcpy(fname,lp_configfile());
1747 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
1749 strcpy(servicesf,fname);
1756 if (test && !lp_file_list_changed())
1759 lp_killunused(snum_used);
1761 ret = lp_load(servicesf,False);
1763 /* perhaps the config filename is now set */
1765 reload_services(True);
1774 set_socket_options(Client,"SO_KEEPALIVE");
1775 set_socket_options(Client,user_socket_options);
1779 create_mangled_stack(lp_mangledstack());
1781 /* this forces service parameters to be flushed */
1782 become_service(-1,True);
1789 /****************************************************************************
1790 this prevents zombie child processes
1791 ****************************************************************************/
1792 static int sig_hup()
1795 DEBUG(0,("Got SIGHUP\n"));
1796 reload_services(False);
1797 #ifndef DONT_REINSTALL_SIG
1798 signal(SIGHUP,SIGNAL_CAST sig_hup);
1800 BlockSignals(False);
1804 /****************************************************************************
1805 Setup the groups a user belongs to.
1806 ****************************************************************************/
1807 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
1808 int **p_igroups, gid_t **p_groups)
1810 if (-1 == initgroups(user,gid))
1814 DEBUG(0,("Unable to initgroups!\n"));
1815 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
1816 DEBUG(0,("This is probably a problem with the account %s\n",user));
1824 ngroups = getgroups(0,&grp);
1827 igroups = (int *)malloc(sizeof(int)*ngroups);
1828 for (i=0;i<ngroups;i++)
1829 igroups[i] = 0x42424242;
1830 ngroups = getgroups(ngroups,(gid_t *)igroups);
1832 if (igroups[0] == 0x42424242)
1835 *p_ngroups = ngroups;
1837 /* The following bit of code is very strange. It is due to the
1838 fact that some OSes use int* and some use gid_t* for
1839 getgroups, and some (like SunOS) use both, one in prototypes,
1840 and one in man pages and the actual code. Thus we detect it
1841 dynamically using some very ugly code */
1844 /* does getgroups return ints or gid_t ?? */
1845 static BOOL groups_use_ints = True;
1847 if (groups_use_ints &&
1849 SVAL(igroups,2) == 0x4242)
1850 groups_use_ints = False;
1852 for (i=0;groups_use_ints && i<ngroups;i++)
1853 if (igroups[i] == 0x42424242)
1854 groups_use_ints = False;
1856 if (groups_use_ints)
1858 *p_igroups = igroups;
1859 *p_groups = (gid_t *)igroups;
1863 gid_t *groups = (gid_t *)igroups;
1864 igroups = (int *)malloc(sizeof(int)*ngroups);
1865 for (i=0;i<ngroups;i++)
1866 igroups[i] = groups[i];
1867 *p_igroups = igroups;
1868 *p_groups = (gid_t *)groups;
1871 DEBUG(3,("%s is in %d groups\n",user,ngroups));
1872 for (i=0;i<ngroups;i++)
1873 DEBUG(3,("%d ",igroups[i]));
1879 /****************************************************************************
1880 make a connection to a service
1881 ****************************************************************************/
1882 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
1886 struct passwd *pass = NULL;
1887 connection_struct *pcon;
1890 static BOOL first_connection = True;
1894 snum = find_service(service);
1897 if (strequal(service,"IPC$"))
1899 DEBUG(3,("%s refusing IPC connection\n",timestring()));
1903 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
1907 if (strequal(service,HOMES_NAME))
1909 if (*user && Get_Pwnam(user,True))
1910 return(make_connection(user,user,password,pwlen,dev,vuid));
1912 if (validated_username(vuid))
1914 strcpy(user,validated_username(vuid));
1915 return(make_connection(user,user,password,pwlen,dev,vuid));
1919 if (!lp_snum_ok(snum) || !check_access(snum)) {
1923 /* you can only connect to the IPC$ service as an ipc device */
1924 if (strequal(service,"IPC$"))
1927 if (*dev == '?' || !*dev)
1929 if (lp_print_ok(snum))
1930 strcpy(dev,"LPT1:");
1935 /* if the request is as a printer and you can't print then refuse */
1937 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
1938 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
1942 /* lowercase the user name */
1945 /* add it as a possible user name */
1946 add_session_user(service);
1948 /* shall we let them in? */
1949 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
1951 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
1955 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
1958 DEBUG(0,("%s couldn't find free connection\n",timestring()));
1962 pcon = &Connections[cnum];
1963 bzero((char *)pcon,sizeof(*pcon));
1965 /* find out some info about the user */
1966 pass = Get_Pwnam(user,True);
1970 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
1974 pcon->read_only = lp_readonly(snum);
1978 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
1979 string_sub(list,"%S",service);
1981 if (user_in_list(user,list))
1982 pcon->read_only = True;
1984 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
1985 string_sub(list,"%S",service);
1987 if (user_in_list(user,list))
1988 pcon->read_only = False;
1991 /* admin user check */
1992 if (user_in_list(user,lp_admin_users(snum)) &&
1995 pcon->admin_user = True;
1996 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
1999 pcon->admin_user = False;
2001 pcon->force_user = force;
2002 pcon->uid = pass->pw_uid;
2003 pcon->gid = pass->pw_gid;
2004 pcon->num_files_open = 0;
2005 pcon->lastused = time(NULL);
2006 pcon->service = snum;
2008 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2009 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2010 pcon->dirptr = NULL;
2011 string_set(&pcon->dirpath,"");
2012 string_set(&pcon->user,user);
2015 if (*lp_force_group(snum))
2017 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2020 pcon->gid = gptr->gr_gid;
2021 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2024 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2028 if (*lp_force_user(snum))
2030 struct passwd *pass2;
2032 strcpy(fuser,lp_force_user(snum));
2033 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2036 pcon->uid = pass2->pw_uid;
2037 string_set(&pcon->user,fuser);
2039 pcon->force_user = True;
2040 DEBUG(3,("Forced user %s\n",fuser));
2043 DEBUG(1,("Couldn't find user %s\n",fuser));
2048 strcpy(s,lp_pathname(snum));
2049 standard_sub(cnum,s);
2050 string_set(&pcon->connectpath,s);
2051 DEBUG(3,("Connect path is %s\n",s));
2054 /* groups stuff added by ih */
2056 pcon->groups = NULL;
2060 /* Find all the groups this uid is in and store them. Used by become_user() */
2061 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2063 /* check number of connections */
2064 if (!claim_connection(cnum,
2065 lp_servicename(SNUM(cnum)),
2066 lp_max_connections(SNUM(cnum)),False))
2068 DEBUG(1,("too many connections - rejected\n"));
2072 if (lp_status(SNUM(cnum)))
2073 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2075 first_connection = False;
2080 /* execute any "root preexec = " line */
2081 if (*lp_rootpreexec(SNUM(cnum)))
2084 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2085 standard_sub(cnum,cmd);
2086 DEBUG(5,("cmd=%s\n",cmd));
2090 if (!become_user(cnum,pcon->uid))
2092 DEBUG(0,("Can't become connected user!\n"));
2094 if (!IS_IPC(cnum)) {
2095 yield_connection(cnum,
2096 lp_servicename(SNUM(cnum)),
2097 lp_max_connections(SNUM(cnum)));
2098 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2103 if (ChDir(pcon->connectpath) != 0)
2105 DEBUG(0,("Can't change directory to %s (%s)\n",
2106 pcon->connectpath,strerror(errno)));
2109 if (!IS_IPC(cnum)) {
2110 yield_connection(cnum,
2111 lp_servicename(SNUM(cnum)),
2112 lp_max_connections(SNUM(cnum)));
2113 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2118 string_set(&pcon->origpath,pcon->connectpath);
2120 #if SOFTLINK_OPTIMISATION
2121 /* resolve any soft links early */
2124 strcpy(s,pcon->connectpath);
2126 string_set(&pcon->connectpath,s);
2127 ChDir(pcon->connectpath);
2131 num_connections_open++;
2132 add_session_user(user);
2134 /* execute any "preexec = " line */
2135 if (*lp_preexec(SNUM(cnum)))
2138 strcpy(cmd,lp_preexec(SNUM(cnum)));
2139 standard_sub(cnum,cmd);
2143 /* we've finished with the sensitive stuff */
2147 extern struct from_host Client_info;
2148 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2150 Client_info.name,Client_info.addr,
2151 lp_servicename(SNUM(cnum)),user,
2161 /****************************************************************************
2162 find first available file slot
2163 ****************************************************************************/
2164 int find_free_file(void )
2167 /* we start at 1 here for an obscure reason I can't now remember,
2168 but I think is important :-) */
2169 for (i=1;i<MAX_OPEN_FILES;i++)
2172 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2176 /****************************************************************************
2177 find first available connection slot, starting from a random position.
2178 The randomisation stops problems with the server dieing and clients
2179 thinking the server is still available.
2180 ****************************************************************************/
2181 static int find_free_connection(int hash )
2185 hash = (hash % (MAX_CONNECTIONS-2))+1;
2189 for (i=hash+1;i!=hash;)
2191 if (!Connections[i].open && Connections[i].used == used)
2193 DEBUG(3,("found free connection number %d\n",i));
2197 if (i == MAX_CONNECTIONS)
2207 DEBUG(1,("ERROR! Out of connection structures\n"));
2212 /****************************************************************************
2213 reply for the core protocol
2214 ****************************************************************************/
2215 int reply_corep(char *outbuf)
2217 int outsize = set_message(outbuf,1,0,True);
2219 Protocol = PROTOCOL_CORE;
2225 /****************************************************************************
2226 reply for the coreplus protocol
2227 ****************************************************************************/
2228 int reply_coreplus(char *outbuf)
2230 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2231 int outsize = set_message(outbuf,13,0,True);
2232 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2233 readbraw and writebraw (possibly) */
2234 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2235 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2237 Protocol = PROTOCOL_COREPLUS;
2243 /****************************************************************************
2244 reply for the lanman 1.0 protocol
2245 ****************************************************************************/
2246 int reply_lanman1(char *outbuf)
2248 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2250 BOOL doencrypt = SMBENCRYPT();
2251 time_t t = time(NULL);
2253 if (lp_security()>=SEC_USER) secword |= 1;
2254 if (doencrypt) secword |= 2;
2256 set_message(outbuf,13,doencrypt?8:0,True);
2257 SSVAL(outbuf,smb_vwv1,secword);
2259 /* Create a token value and add it to the outgoing packet. */
2261 generate_next_challenge(smb_buf(outbuf));
2264 Protocol = PROTOCOL_LANMAN1;
2266 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2267 DEBUG(3,("using password server validation\n"));
2269 if (doencrypt) set_challenge(smb_buf(outbuf));
2273 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2274 SSVAL(outbuf,smb_vwv2,maxxmit);
2275 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2276 SSVAL(outbuf,smb_vwv4,1);
2277 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2278 readbraw writebraw (possibly) */
2279 SIVAL(outbuf,smb_vwv6,getpid());
2280 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2282 put_dos_date(outbuf,smb_vwv8,t);
2284 return (smb_len(outbuf)+4);
2288 /****************************************************************************
2289 reply for the lanman 2.0 protocol
2290 ****************************************************************************/
2291 int reply_lanman2(char *outbuf)
2293 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2295 BOOL doencrypt = SMBENCRYPT();
2296 time_t t = time(NULL);
2298 if (lp_security()>=SEC_USER) secword |= 1;
2299 if (doencrypt) secword |= 2;
2301 set_message(outbuf,13,doencrypt?8:0,True);
2302 SSVAL(outbuf,smb_vwv1,secword);
2304 /* Create a token value and add it to the outgoing packet. */
2306 generate_next_challenge(smb_buf(outbuf));
2309 SIVAL(outbuf,smb_vwv6,getpid());
2311 Protocol = PROTOCOL_LANMAN2;
2313 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2314 DEBUG(3,("using password server validation\n"));
2316 if (doencrypt) set_challenge(smb_buf(outbuf));
2320 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2321 SSVAL(outbuf,smb_vwv2,maxxmit);
2322 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2323 SSVAL(outbuf,smb_vwv4,1);
2324 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2325 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2326 put_dos_date(outbuf,smb_vwv8,t);
2328 return (smb_len(outbuf)+4);
2331 /****************************************************************************
2332 reply for the nt protocol
2333 ****************************************************************************/
2334 int reply_nt1(char *outbuf)
2336 int capabilities=0x300; /* has dual names + lock_and_read */
2338 BOOL doencrypt = SMBENCRYPT();
2339 time_t t = time(NULL);
2341 if (lp_security()>=SEC_USER) secword |= 1;
2342 if (doencrypt) secword |= 2;
2344 set_message(outbuf,17,doencrypt?8:0,True);
2345 CVAL(outbuf,smb_vwv1) = secword;
2347 /* Create a token value and add it to the outgoing packet. */
2349 generate_next_challenge(smb_buf(outbuf));
2350 /* Tell the nt machine how long the challenge is. */
2351 SSVALS(outbuf,smb_vwv16+1,8);
2355 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2357 Protocol = PROTOCOL_NT1;
2359 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2360 DEBUG(3,("using password server validation\n"));
2362 if (doencrypt) set_challenge(smb_buf(outbuf));
2366 if (lp_readraw() && lp_writeraw())
2369 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2370 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2371 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2372 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2373 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2374 put_long_date(outbuf+smb_vwv11+1,t);
2375 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2377 return (smb_len(outbuf)+4);
2381 /* these are the protocol lists used for auto architecture detection:
2384 protocol [PC NETWORK PROGRAM 1.0]
2385 protocol [XENIX CORE]
2386 protocol [MICROSOFT NETWORKS 1.03]
2387 protocol [LANMAN1.0]
2388 protocol [Windows for Workgroups 3.1a]
2389 protocol [LM1.2X002]
2390 protocol [LANMAN2.1]
2391 protocol [NT LM 0.12]
2394 protocol [PC NETWORK PROGRAM 1.0]
2395 protocol [XENIX CORE]
2396 protocol [MICROSOFT NETWORKS 1.03]
2397 protocol [LANMAN1.0]
2398 protocol [Windows for Workgroups 3.1a]
2399 protocol [LM1.2X002]
2400 protocol [LANMAN2.1]
2401 protocol [NT LM 0.12]
2404 protocol [PC NETWORK PROGRAM 1.0]
2405 protocol [XENIX CORE]
2406 protocol [LANMAN1.0]
2407 protocol [LM1.2X002]
2408 protocol [LANMAN2.1]
2412 * Modified to recognize the architecture of the remote machine better.
2414 * This appears to be the matrix of which protocol is used by which
2416 Protocol WfWg Win95 WinNT OS/2
2417 PC NETWORK PROGRAM 1.0 1 1 1 1
2419 MICROSOFT NETWORKS 3.0 2 2
2421 MICROSOFT NETWORKS 1.03 3
2424 Windows for Workgroups 3.1a 5 5 5
2429 * tim@fsg.com 09/29/95
2432 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2433 #define ARCH_WIN95 0x2
2434 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2435 #define ARCH_WINNT 0x8
2436 #define ARCH_SAMBA 0x10
2438 #define ARCH_ALL 0x1F
2440 /* List of supported protocols, most desired first */
2444 int (*proto_reply_fn)(char *);
2446 } supported_protocols[] = {
2447 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2448 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2449 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2450 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2451 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2452 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2453 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2454 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2455 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2460 /****************************************************************************
2462 ****************************************************************************/
2463 static int reply_negprot(char *inbuf,char *outbuf)
2465 extern fstring remote_arch;
2466 int outsize = set_message(outbuf,1,0,True);
2471 int bcc = SVAL(smb_buf(inbuf),-2);
2472 int arch = ARCH_ALL;
2474 p = smb_buf(inbuf)+1;
2475 while (p < (smb_buf(inbuf) + bcc))
2478 DEBUG(3,("Requested protocol [%s]\n",p));
2479 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2480 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2481 else if (strcsequal(p,"DOS LM1.2X002"))
2482 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2483 else if (strcsequal(p,"DOS LANMAN2.1"))
2484 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2485 else if (strcsequal(p,"NT LM 0.12"))
2486 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2487 else if (strcsequal(p,"LANMAN2.1"))
2488 arch &= ( ARCH_WINNT | ARCH_OS2 );
2489 else if (strcsequal(p,"LM1.2X002"))
2490 arch &= ( ARCH_WINNT | ARCH_OS2 );
2491 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2493 else if (strcsequal(p,"XENIX CORE"))
2494 arch &= ( ARCH_WINNT | ARCH_OS2 );
2495 else if (strcsequal(p,"Samba")) {
2505 strcpy(remote_arch,"Samba");
2508 strcpy(remote_arch,"WfWg");
2511 strcpy(remote_arch,"Win95");
2514 strcpy(remote_arch,"WinNT");
2517 strcpy(remote_arch,"OS2");
2520 strcpy(remote_arch,"UNKNOWN");
2524 /* possibly reload - change of architecture */
2525 reload_services(True);
2527 /* a special case to stop password server loops */
2528 if (Index == 1 && strequal(remote_machine,myhostname) &&
2529 lp_security()==SEC_SERVER)
2530 exit_server("Password server loop!");
2532 /* Check for protocols, most desirable first */
2533 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2535 p = smb_buf(inbuf)+1;
2537 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2538 while (p < (smb_buf(inbuf) + bcc))
2540 if (strequal(p,supported_protocols[protocol].proto_name))
2549 SSVAL(outbuf,smb_vwv0,choice);
2551 extern fstring remote_proto;
2552 strcpy(remote_proto,supported_protocols[protocol].short_name);
2553 reload_services(True);
2554 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2555 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2558 DEBUG(0,("No protocol supported !\n"));
2560 SSVAL(outbuf,smb_vwv0,choice);
2562 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2568 /****************************************************************************
2569 parse a connect packet
2570 ****************************************************************************/
2571 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2573 char *p = smb_buf(buf) + 1;
2576 DEBUG(4,("parsing connect string %s\n",p));
2578 p2 = strrchr(p,'\\');
2582 strcpy(service,p2+1);
2587 *pwlen = strlen(password);
2594 p = strchr(service,'%');
2603 /****************************************************************************
2604 close all open files for a connection
2605 ****************************************************************************/
2606 static void close_open_files(int cnum)
2609 for (i=0;i<MAX_OPEN_FILES;i++)
2610 if( Files[i].cnum == cnum && Files[i].open) {
2617 /****************************************************************************
2619 ****************************************************************************/
2620 void close_cnum(int cnum, int uid)
2622 extern struct from_host Client_info;
2624 DirCacheFlush(SNUM(cnum));
2628 if (!OPEN_CNUM(cnum))
2630 DEBUG(0,("Can't close cnum %d\n",cnum));
2634 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2636 Client_info.name,Client_info.addr,
2637 lp_servicename(SNUM(cnum))));
2639 yield_connection(cnum,
2640 lp_servicename(SNUM(cnum)),
2641 lp_max_connections(SNUM(cnum)));
2643 if (lp_status(SNUM(cnum)))
2644 yield_connection(cnum,"STATUS.",MAXSTATUS);
2646 close_open_files(cnum);
2647 dptr_closecnum(cnum);
2649 /* execute any "postexec = " line */
2650 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2653 strcpy(cmd,lp_postexec(SNUM(cnum)));
2654 standard_sub(cnum,cmd);
2660 /* execute any "root postexec = " line */
2661 if (*lp_rootpostexec(SNUM(cnum)))
2664 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2665 standard_sub(cnum,cmd);
2669 Connections[cnum].open = False;
2670 num_connections_open--;
2671 if (Connections[cnum].ngroups && Connections[cnum].groups)
2673 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2674 free(Connections[cnum].groups);
2675 free(Connections[cnum].igroups);
2676 Connections[cnum].groups = NULL;
2677 Connections[cnum].igroups = NULL;
2678 Connections[cnum].ngroups = 0;
2681 string_set(&Connections[cnum].user,"");
2682 string_set(&Connections[cnum].dirpath,"");
2683 string_set(&Connections[cnum].connectpath,"");
2687 /****************************************************************************
2688 simple routines to do connection counting
2689 ****************************************************************************/
2690 BOOL yield_connection(int cnum,char *name,int max_connections)
2692 struct connect_record crec;
2695 int mypid = getpid();
2698 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2700 if (max_connections <= 0)
2703 bzero(&crec,sizeof(crec));
2705 strcpy(fname,lp_lockdir());
2706 standard_sub(cnum,fname);
2707 trim_string(fname,"","/");
2711 strcat(fname,".LCK");
2713 f = fopen(fname,"r+");
2716 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2720 fseek(f,0,SEEK_SET);
2722 /* find a free spot */
2723 for (i=0;i<max_connections;i++)
2725 if (fread(&crec,sizeof(crec),1,f) != 1)
2727 DEBUG(2,("Entry not found in lock file %s\n",fname));
2731 if (crec.pid == mypid && crec.cnum == cnum)
2735 if (crec.pid != mypid || crec.cnum != cnum)
2738 DEBUG(2,("Entry not found in lock file %s\n",fname));
2742 bzero((void *)&crec,sizeof(crec));
2744 /* remove our mark */
2745 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2746 fwrite(&crec,sizeof(crec),1,f) != 1)
2748 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
2753 DEBUG(3,("Yield successful\n"));
2760 /****************************************************************************
2761 simple routines to do connection counting
2762 ****************************************************************************/
2763 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
2765 struct connect_record crec;
2768 int snum = SNUM(cnum);
2772 if (max_connections <= 0)
2775 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
2777 strcpy(fname,lp_lockdir());
2778 standard_sub(cnum,fname);
2779 trim_string(fname,"","/");
2781 if (!directory_exist(fname,NULL))
2786 strcat(fname,".LCK");
2788 if (!file_exist(fname,NULL))
2790 f = fopen(fname,"w");
2794 total_recs = file_size(fname) / sizeof(crec);
2796 f = fopen(fname,"r+");
2800 DEBUG(1,("couldn't open lock file %s\n",fname));
2804 /* find a free spot */
2805 for (i=0;i<max_connections;i++)
2808 if (i>=total_recs ||
2809 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2810 fread(&crec,sizeof(crec),1,f) != 1)
2812 if (foundi < 0) foundi = i;
2816 if (Clear && crec.pid && !process_exists(crec.pid))
2818 fseek(f,i*sizeof(crec),SEEK_SET);
2819 bzero((void *)&crec,sizeof(crec));
2820 fwrite(&crec,sizeof(crec),1,f);
2821 if (foundi < 0) foundi = i;
2824 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2833 DEBUG(3,("no free locks in %s\n",fname));
2838 /* fill in the crec */
2839 bzero((void *)&crec,sizeof(crec));
2840 crec.magic = 0x280267;
2841 crec.pid = getpid();
2843 crec.uid = Connections[cnum].uid;
2844 crec.gid = Connections[cnum].gid;
2845 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2846 crec.start = time(NULL);
2849 extern struct from_host Client_info;
2850 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2851 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2855 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2856 fwrite(&crec,sizeof(crec),1,f) != 1)
2867 /*******************************************************************
2868 prepare to dump a core file - carefully!
2869 ********************************************************************/
2870 static BOOL dump_core(void)
2874 strcpy(dname,debugf);
2875 if ((p=strrchr(dname,'/'))) *p=0;
2876 strcat(dname,"/corefiles");
2878 sys_chown(dname,getuid(),getgid());
2880 if (chdir(dname)) return(False);
2883 #ifndef NO_GETRLIMIT
2887 getrlimit(RLIMIT_CORE, &rlp);
2888 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2889 setrlimit(RLIMIT_CORE, &rlp);
2890 getrlimit(RLIMIT_CORE, &rlp);
2891 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2897 DEBUG(0,("Dumping core in %s\n",dname));
2902 /****************************************************************************
2904 ****************************************************************************/
2905 void exit_server(char *reason)
2907 static int firsttime=1;
2910 if (!firsttime) exit(0);
2914 DEBUG(2,("Closing connections\n"));
2915 for (i=0;i<MAX_CONNECTIONS;i++)
2916 if (Connections[i].open)
2919 if (dcelogin_atmost_once)
2923 int oldlevel = DEBUGLEVEL;
2925 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2927 show_msg(last_inbuf);
2928 DEBUGLEVEL = oldlevel;
2929 DEBUG(0,("===============================================================\n"));
2931 if (dump_core()) return;
2934 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
2938 /****************************************************************************
2939 do some standard substitutions in a string
2940 ****************************************************************************/
2941 void standard_sub(int cnum,char *s)
2943 if (!strchr(s,'%')) return;
2945 if (VALID_CNUM(cnum))
2947 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2948 string_sub(s,"%P",Connections[cnum].connectpath);
2949 string_sub(s,"%u",Connections[cnum].user);
2950 if (strstr(s,"%H")) {
2951 char *home = get_home_dir(Connections[cnum].user);
2952 if (home) string_sub(s,"%H",home);
2954 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2956 standard_sub_basic(s);
2960 These flags determine some of the permissions required to do an operation
2962 Note that I don't set NEED_WRITE on some write operations because they
2963 are used by some brain-dead clients when printing, and I don't want to
2964 force write permissions on print services.
2966 #define AS_USER (1<<0)
2967 #define NEED_WRITE (1<<1)
2968 #define TIME_INIT (1<<2)
2969 #define CAN_IPC (1<<3)
2970 #define AS_GUEST (1<<5)
2974 define a list of possible SMB messages and their corresponding
2975 functions. Any message that has a NULL function is unimplemented -
2976 please feel free to contribute implementations!
2978 struct smb_message_struct
2992 {SMBnegprot,"SMBnegprot",reply_negprot,0},
2993 {SMBtcon,"SMBtcon",reply_tcon,0},
2994 {SMBtdis,"SMBtdis",reply_tdis,0},
2995 {SMBexit,"SMBexit",reply_exit,0},
2996 {SMBioctl,"SMBioctl",reply_ioctl,0},
2997 {SMBecho,"SMBecho",reply_echo,0},
2998 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
2999 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3000 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3001 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3002 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3003 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3004 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3005 {SMBopen,"SMBopen",reply_open,AS_USER},
3007 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3008 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3009 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3011 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3012 {SMBread,"SMBread",reply_read,AS_USER},
3013 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3014 {SMBclose,"SMBclose",reply_close,AS_USER},
3015 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3016 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3017 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3018 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3020 /* this is a Pathworks specific call, allowing the
3021 changing of the root path */
3022 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3024 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3025 {SMBflush,"SMBflush",reply_flush,AS_USER},
3026 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3027 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3028 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3029 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3030 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3031 {SMBlock,"SMBlock",reply_lock,AS_USER},
3032 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3034 /* CORE+ PROTOCOL FOLLOWS */
3036 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3037 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3038 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3039 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3040 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3042 /* LANMAN1.0 PROTOCOL FOLLOWS */
3044 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3045 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3046 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3047 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3048 {SMBwritec,"SMBwritec",NULL,AS_USER},
3049 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3050 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3051 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3052 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3053 {SMBioctls,"SMBioctls",NULL,AS_USER},
3054 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3055 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3057 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3058 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3059 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3060 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3062 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3063 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3064 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3066 /* LANMAN2.0 PROTOCOL FOLLOWS */
3067 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3068 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3069 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3070 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3072 /* messaging routines */
3073 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3074 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3075 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3076 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3078 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3080 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3081 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3082 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3083 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3086 /****************************************************************************
3087 return a string containing the function name of a SMB command
3088 ****************************************************************************/
3089 char *smb_fn_name(int type)
3091 static char *unknown_name = "SMBunknown";
3092 static int num_smb_messages =
3093 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3096 for (match=0;match<num_smb_messages;match++)
3097 if (smb_messages[match].code == type)
3100 if (match == num_smb_messages)
3101 return(unknown_name);
3103 return(smb_messages[match].name);
3107 /****************************************************************************
3108 do a switch on the message type, and return the response size
3109 ****************************************************************************/
3110 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3114 static int num_smb_messages =
3115 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3119 struct timeval msg_start_time;
3120 struct timeval msg_end_time;
3121 static unsigned long total_time = 0;
3123 GetTimeOfDay(&msg_start_time);
3130 last_message = type;
3132 /* make sure this is an SMB packet */
3133 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3135 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3139 for (match=0;match<num_smb_messages;match++)
3140 if (smb_messages[match].code == type)
3143 if (match == num_smb_messages)
3145 DEBUG(0,("Unknown message type %d!\n",type));
3146 outsize = reply_unknown(inbuf,outbuf);
3150 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3151 if (smb_messages[match].fn)
3153 int cnum = SVAL(inbuf,smb_tid);
3154 int flags = smb_messages[match].flags;
3155 int uid = SVAL(inbuf,smb_uid);
3157 /* does this protocol need to be run as root? */
3158 if (!(flags & AS_USER))
3161 /* does this protocol need to be run as the connected user? */
3162 if ((flags & AS_USER) && !become_user(cnum,uid))
3163 return(ERROR(ERRSRV,ERRinvnid));
3165 /* does it need write permission? */
3166 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3167 return(ERROR(ERRSRV,ERRaccess));
3169 /* ipc services are limited */
3170 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3171 return(ERROR(ERRSRV,ERRaccess));
3173 /* load service specific parameters */
3174 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3175 return(ERROR(ERRSRV,ERRaccess));
3177 /* does this protocol need to be run as guest? */
3178 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3179 return(ERROR(ERRSRV,ERRaccess));
3183 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3187 outsize = reply_unknown(inbuf,outbuf);
3192 GetTimeOfDay(&msg_end_time);
3193 if (!(smb_messages[match].flags & TIME_INIT))
3195 smb_messages[match].time = 0;
3196 smb_messages[match].flags |= TIME_INIT;
3199 unsigned long this_time =
3200 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3201 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3202 smb_messages[match].time += this_time;
3203 total_time += this_time;
3205 DEBUG(2,("TIME %s %d usecs %g pct\n",
3206 smb_fn_name(type),smb_messages[match].time,
3207 (100.0*smb_messages[match].time) / total_time));
3214 /****************************************************************************
3215 construct a chained reply and add it to the already made reply
3217 inbuf points to the original message start.
3218 inbuf2 points to the smb_wct part of the secondary message
3219 type is the type of the secondary message
3220 outbuf points to the original outbuffer
3221 outbuf2 points to the smb_wct field of the new outbuffer
3222 size is the total length of the incoming message (from inbuf1)
3223 bufsize is the total buffer size
3225 return how many bytes were added to the response
3226 ****************************************************************************/
3227 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3231 static BOOL in_chain = False;
3232 static char *last_outbuf=NULL;
3233 BOOL was_inchain = in_chain;
3234 int insize_remaining;
3235 static int insize_deleted;
3238 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3240 outbuf = last_outbuf;
3246 inbuf2 -= insize_deleted;
3247 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3248 insize_deleted += size - (insize_remaining + smb_wct);
3251 last_outbuf = outbuf;
3254 /* allocate some space for the in and out buffers of the chained message */
3255 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3256 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3260 DEBUG(0,("Out of memory in chain reply\n"));
3261 return(ERROR(ERRSRV,ERRnoresource));
3264 ibuf += SMB_ALIGNMENT;
3265 obuf += SMB_ALIGNMENT;
3267 /* create the in buffer */
3268 memcpy(ibuf,inbuf,smb_wct);
3269 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3270 CVAL(ibuf,smb_com) = type;
3272 /* create the out buffer */
3273 bzero(obuf,smb_size);
3275 set_message(obuf,0,0,True);
3276 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3278 memcpy(obuf+4,ibuf+4,4);
3279 CVAL(obuf,smb_rcls) = SUCCESS;
3280 CVAL(obuf,smb_reh) = 0;
3281 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3283 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3284 SSVAL(obuf,smb_err,SUCCESS);
3285 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3286 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3287 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3288 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3290 DEBUG(3,("Chained message\n"));
3293 /* process the request */
3294 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3295 bufsize-chain_size);
3297 /* copy the new reply header over the old one, but preserve
3298 the smb_com field */
3299 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3301 /* and copy the data from the reply to the right spot */
3302 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3304 /* free the allocated buffers */
3305 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3306 if (obuf) free(obuf-SMB_ALIGNMENT);
3308 in_chain = was_inchain;
3310 /* return how much extra has been added to the packet */
3311 return(outsize - smb_wct);
3316 /****************************************************************************
3317 construct a reply to the incoming packet
3318 ****************************************************************************/
3319 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3321 int type = CVAL(inbuf,smb_com);
3323 int msg_type = CVAL(inbuf,0);
3325 smb_last_time = time(NULL);
3329 bzero(outbuf,smb_size);
3332 return(reply_special(inbuf,outbuf));
3334 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3335 set_message(outbuf,0,0,True);
3337 memcpy(outbuf+4,inbuf+4,4);
3338 CVAL(outbuf,smb_rcls) = SUCCESS;
3339 CVAL(outbuf,smb_reh) = 0;
3340 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3342 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3343 SSVAL(outbuf,smb_err,SUCCESS);
3344 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3345 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3346 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3347 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3349 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3352 smb_setlen(outbuf,outsize - 4);
3357 /****************************************************************************
3358 process commands from the client
3359 ****************************************************************************/
3360 static void process(void)
3362 static int trans_num = 0;
3364 extern struct from_host Client_info;
3367 fromhost(Client,&Client_info);
3369 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3370 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3371 if ((InBuffer == NULL) || (OutBuffer == NULL))
3374 InBuffer += SMB_ALIGNMENT;
3375 OutBuffer += SMB_ALIGNMENT;
3378 DEBUG(3,("priming nmbd\n"));
3381 ip = *interpret_addr2("localhost");
3382 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3384 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3394 int deadtime = lp_deadtime()*60;
3396 int last_keepalive=0;
3399 deadtime = DEFAULT_SMBD_TIMEOUT;
3401 if (lp_readprediction())
3402 do_read_prediction();
3405 extern pstring share_del_pending;
3406 if (*share_del_pending) {
3408 if (!unlink(share_del_pending))
3409 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3411 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3412 share_del_pending[0] = 0;
3416 if (share_mode_pending) {
3418 check_share_modes();
3419 share_mode_pending=False;
3424 for (counter=SMBD_SELECT_LOOP;
3425 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3426 counter += SMBD_SELECT_LOOP)
3430 BOOL allidle = True;
3431 extern int keepalive;
3433 if (smb_read_error == READ_EOF) {
3434 DEBUG(3,("end of file from client\n"));
3438 if (smb_read_error == READ_ERROR) {
3439 DEBUG(3,("receive_smb error (%s) exiting\n",
3447 /* the following bit of code was added to combat smbd
3448 looping chewing lots of CPU time. It should never
3449 actually be needed, but it seems that some systems
3450 don't set error correctly, which is used to distinguish
3451 a select() timeout from a read error
3453 we exit if receive_smb() returns false 3 times in one second.
3455 static int error_count=0;
3456 static time_t error_time=0;
3457 if (error_count++==0) {
3459 } else if (error_time != t) {
3461 } else if (error_count > 2) {
3462 exit_server("looping in process()\n");
3467 /* become root again if waiting */
3470 /* check for smb.conf reload */
3471 if (!(counter%SMBD_RELOAD_CHECK))
3472 reload_services(True);
3474 /* check the share modes every 10 secs */
3475 if (!(counter%SHARE_MODES_CHECK))
3476 check_share_modes();
3478 /* clean the share modes every 5 minutes */
3479 if (!(counter%SHARE_MODES_CLEAN))
3480 clean_share_files();
3482 /* automatic timeout if all connections are closed */
3483 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3484 DEBUG(2,("%s Closing idle connection\n",timestring()));
3488 if (keepalive && (counter-last_keepalive)>keepalive) {
3489 extern int password_client;
3490 if (!send_keepalive(Client)) {
3491 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3494 /* also send a keepalive to the password server if its still
3496 if (password_client != -1)
3497 send_keepalive(password_client);
3498 last_keepalive = counter;
3501 /* check for connection timeouts */
3502 for (i=0;i<MAX_CONNECTIONS;i++)
3503 if (Connections[i].open)
3505 /* close dirptrs on connections that are idle */
3506 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3509 if (Connections[i].num_files_open > 0 ||
3510 (t-Connections[i].lastused)<deadtime)
3514 if (allidle && num_connections_open>0) {
3515 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3520 msg_type = CVAL(InBuffer,0);
3521 msg_flags = CVAL(InBuffer,1);
3522 type = CVAL(InBuffer,smb_com);
3524 len = smb_len(InBuffer);
3526 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3530 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3533 if(trans_num == 1 && VT_Check(InBuffer)) {
3543 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3546 if (CVAL(OutBuffer,0) == 0)
3547 show_msg(OutBuffer);
3549 if (nread != smb_len(OutBuffer) + 4)
3551 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3553 smb_len(OutBuffer)));
3556 send_smb(Client,OutBuffer);
3563 /****************************************************************************
3564 initialise connect, service and file structs
3565 ****************************************************************************/
3566 static void init_structs(void )
3569 get_myname(myhostname,NULL);
3571 for (i=0;i<MAX_CONNECTIONS;i++)
3573 Connections[i].open = False;
3574 Connections[i].num_files_open=0;
3575 Connections[i].lastused=0;
3576 Connections[i].used=False;
3577 string_init(&Connections[i].user,"");
3578 string_init(&Connections[i].dirpath,"");
3579 string_init(&Connections[i].connectpath,"");
3580 string_init(&Connections[i].origpath,"");
3583 for (i=0;i<MAX_OPEN_FILES;i++)
3585 Files[i].open = False;
3586 string_init(&Files[i].name,"");
3592 /****************************************************************************
3593 usage on the program
3594 ****************************************************************************/
3595 static void usage(char *pname)
3597 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3599 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3600 printf("Version %s\n",VERSION);
3601 printf("\t-D become a daemon\n");
3602 printf("\t-p port listen on the specified port\n");
3603 printf("\t-d debuglevel set the debuglevel\n");
3604 printf("\t-l log basename. Basename for log/debug files\n");
3605 printf("\t-s services file. Filename of services file\n");
3606 printf("\t-P passive only\n");
3607 printf("\t-a overwrite log file, don't append\n");
3612 /****************************************************************************
3614 ****************************************************************************/
3615 int main(int argc,char *argv[])
3617 extern BOOL append_log;
3618 /* shall I run as a daemon */
3619 BOOL is_daemon = False;
3620 int port = SMB_PORT;
3622 extern char *optarg;
3624 #ifdef NEED_AUTH_PARAMETERS
3625 set_auth_parameters(argc,argv);
3636 strcpy(debugf,SMBLOGFILE);
3638 setup_logging(argv[0],False);
3640 charset_initialise();
3642 /* make absolutely sure we run as root - to handle cases whre people
3643 are crazy enough to have it setuid */
3653 fault_setup(exit_server);
3655 umask(0777 & ~DEF_CREATE_MASK);
3659 /* this is for people who can't start the program correctly */
3660 while (argc > 1 && (*argv[1] != '-'))
3666 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3670 strcpy(user_socket_options,optarg);
3673 strcpy(scope,optarg);
3677 extern BOOL passive;
3682 strcpy(servicesf,optarg);
3685 strcpy(debugf,optarg);
3689 extern BOOL append_log;
3690 append_log = !append_log;
3700 DEBUGLEVEL = atoi(optarg);
3703 port = atoi(optarg);
3716 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3717 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3719 #ifndef NO_GETRLIMIT
3720 #ifdef RLIMIT_NOFILE
3723 getrlimit(RLIMIT_NOFILE, &rlp);
3724 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3725 setrlimit(RLIMIT_NOFILE, &rlp);
3726 getrlimit(RLIMIT_NOFILE, &rlp);
3727 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3733 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3734 getuid(),getgid(),geteuid(),getegid()));
3736 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3738 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3744 if (!reload_services(False))
3747 #ifndef NO_SIGNAL_TEST
3748 signal(SIGHUP,SIGNAL_CAST sig_hup);
3751 DEBUG(3,("%s loaded services\n",timestring()));
3753 if (!is_daemon && !is_a_socket(0))
3755 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3761 DEBUG(3,("%s becoming a daemon\n",timestring()));
3765 if (!open_sockets(is_daemon,port))
3768 /* possibly reload the services file. */
3769 reload_services(True);
3771 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3775 if (sys_chroot(lp_rootdir()) == 0)
3776 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3782 exit_server("normal exit");