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.
28 pstring servicesf = CONFIGFILE;
29 pstring OriginalDir ="/";
30 extern pstring debugf;
31 extern pstring sesssetup_user;
33 char *InBuffer = NULL;
34 char *OutBuffer = NULL;
35 char *last_inbuf = NULL;
40 BOOL share_mode_pending = False;
42 /* have I done a become_user? */
47 /* the last message the was processed */
48 int last_message = -1;
50 /* a useful macro to debug the last message processed */
51 #define LAST_MESSAGE() smb_fn_name(last_message)
54 extern int DEBUGLEVEL;
55 extern int case_default;
56 extern BOOL case_sensitive;
57 extern BOOL case_preserve;
58 extern BOOL use_mangled_map;
59 extern BOOL short_case_preserve;
60 extern BOOL case_mangle;
61 extern time_t smb_last_time;
63 extern pstring user_socket_options;
65 connection_struct Connections[MAX_CONNECTIONS];
66 files_struct Files[MAX_OPEN_FILES];
70 int maxxmit = BUFFER_SIZE;
74 /* a fnum to use when chaining */
77 /* number of open connections */
78 static int num_connections_open = 0;
80 extern fstring remote_machine;
83 /* these can be set by some functions to override the error codes */
84 int unix_ERR_class=SUCCESS;
88 extern int extra_time_offset;
90 extern pstring myhostname;
91 extern struct in_addr myip;
94 static int find_free_connection(int hash);
97 extern void generate_next_challenge(char *challenge);
98 extern void set_challenge(char *challenge);
101 /* for readability... */
102 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
103 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
104 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
105 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
106 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
110 /****************************************************************************
111 change a dos mode to a unix mode
112 base permission for files:
113 everybody gets read bit set
114 dos readonly is represented in unix by removing everyone's write bit
115 dos archive is represented in unix by the user's execute bit
116 dos system is represented in unix by the group's execute bit
117 dos hidden is represented in unix by the other's execute bit
118 base permission for directories:
119 dos directory is represented in unix by unix's dir bit and the exec bit
120 ****************************************************************************/
121 mode_t unix_mode(int cnum,int dosmode)
123 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
125 if ( !IS_DOS_READONLY(dosmode) )
126 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
128 if (IS_DOS_DIR(dosmode))
129 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
131 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
134 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
137 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
140 result &= CREATE_MODE(cnum);
145 /****************************************************************************
146 change a unix mode to a dos mode
147 ****************************************************************************/
148 int dos_mode(int cnum,char *path,struct stat *sbuf)
153 if (!CAN_WRITE(cnum) || !((sbuf->st_mode & S_IWOTH) ||
154 Connections[cnum].admin_user ||
155 ((sbuf->st_mode & S_IWUSR) &&
156 Connections[cnum].uid==sbuf->st_uid) ||
157 ((sbuf->st_mode & S_IWGRP) &&
158 in_group(sbuf->st_gid,Connections[cnum].gid,
159 Connections[cnum].ngroups,
160 Connections[cnum].igroups))))
163 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
164 if (!((sbuf->st_mode & S_IWOTH) ||
165 Connections[cnum].admin_user ||
166 ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid==sbuf->st_uid) ||
167 ((sbuf->st_mode & S_IWGRP) &&
168 in_group(sbuf->st_gid,Connections[cnum].gid,
169 Connections[cnum].ngroups,Connections[cnum].igroups))))
172 if ((sbuf->st_mode & S_IWUSR) == 0)
177 if ((sbuf->st_mode & S_IXUSR) != 0)
180 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
183 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
186 if (S_ISDIR(sbuf->st_mode))
187 result = aDIR | (result & aRONLY);
190 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
194 /* hide files with a name starting with a . */
195 if (lp_hide_dot_files(SNUM(cnum)))
197 char *p = strrchr(path,'/');
203 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
211 /*******************************************************************
212 chmod a file - but preserve some bits
213 ********************************************************************/
214 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
223 if (sys_stat(fname,st)) return(-1);
226 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
228 if (dos_mode(cnum,fname,st) == dosmode) return(0);
230 unixmode = unix_mode(cnum,dosmode);
232 /* preserve the s bits */
233 mask |= (S_ISUID | S_ISGID);
235 /* preserve the t bit */
240 /* possibly preserve the x bits */
241 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
242 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
243 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
245 unixmode |= (st->st_mode & mask);
247 /* if we previously had any r bits set then leave them alone */
248 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
249 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
253 /* if we previously had any w bits set then leave them alone
254 if the new mode is not rdonly */
255 if (!IS_DOS_READONLY(dosmode) &&
256 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
257 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
261 return(chmod(fname,unixmode));
265 /****************************************************************************
266 check if two filenames are equal
268 this needs to be careful about whether we are case sensitive
269 ****************************************************************************/
270 static BOOL fname_equal(char *name1, char *name2)
272 int l1 = strlen(name1);
273 int l2 = strlen(name2);
275 /* handle filenames ending in a single dot */
276 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
280 ret = fname_equal(name1,name2);
285 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
289 ret = fname_equal(name1,name2);
294 /* now normal filename handling */
296 return(strcmp(name1,name2) == 0);
298 return(strequal(name1,name2));
302 /****************************************************************************
303 mangle the 2nd name and check if it is then equal to the first name
304 ****************************************************************************/
305 static BOOL mangled_equal(char *name1, char *name2)
312 strcpy(tmpname,name2);
313 mangle_name_83(tmpname);
315 return(strequal(name1,tmpname));
319 /****************************************************************************
320 scan a directory to find a filename, matching without case sensitivity
322 If the name looks like a mangled name then try via the mangling functions
323 ****************************************************************************/
324 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
331 mangled = is_mangled(name);
333 /* handle null paths */
337 if (docache && (dname = DirCacheCheck(path,name,snum))) {
343 check_mangled_stack(name);
345 /* open the directory */
346 if (!(cur_dir = OpenDir(path)))
348 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
352 /* now scan for matching names */
353 while ((dname = ReadDirName(cur_dir)))
356 (strequal(dname,".") || strequal(dname,"..")))
360 if (!name_map_mangle(name2,False,snum)) continue;
362 if ((mangled && mangled_equal(name,name2))
363 || fname_equal(name, name2))
365 /* we've found the file, change it's name and return */
366 if (docache) DirCacheAdd(path,name,dname,snum);
377 /****************************************************************************
378 This routine is called to convert names from the dos namespace to unix
379 namespace. It needs to handle any case conversions, mangling, format
382 We assume that we have already done a chdir() to the right "root" directory
385 The function will return False if some part of the name except for the last
386 part cannot be resolved
387 ****************************************************************************/
388 BOOL unix_convert(char *name,int cnum)
396 /* convert to basic unix format - removing \ chars and cleaning it up */
398 unix_clean_name(name);
400 if (!case_sensitive &&
401 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
404 /* names must be relative to the root of the service - trim any leading /.
405 also trim trailing /'s */
406 trim_string(name,"/","/");
408 /* check if it's a printer file */
409 if (Connections[cnum].printer)
411 if ((! *name) || strchr(name,'/') || !is_8_3(name))
415 sprintf(name2,"%.6s.XXXXXX",remote_machine);
416 /* sanitise the name */
417 for (s=name2 ; *s ; s++)
418 if (!issafe(*s)) *s = '_';
419 strcpy(name,(char *)mktemp(name2));
424 /* stat the name - if it exists then we are all done! */
425 if (sys_stat(name,&st) == 0)
428 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
430 /* a special case - if we don't have any mangling chars and are case
431 sensitive then searching won't help */
432 if (case_sensitive && !is_mangled(name) &&
433 !lp_strip_dot() && !use_mangled_map)
436 /* now we need to recursively match the name against the real
437 directory structure */
440 while (strncmp(start,"./",2) == 0)
443 /* now match each part of the path name separately, trying the names
444 as is first, then trying to scan the directory for matching names */
445 for (;start;start = (end?end+1:(char *)NULL))
447 /* pinpoint the end of this section of the filename */
448 end = strchr(start, '/');
450 /* chop the name at this point */
453 /* check if the name exists up to this point */
454 if (sys_stat(name, &st) == 0)
456 /* it exists. it must either be a directory or this must be
457 the last part of the path for it to be OK */
458 if (end && !(st.st_mode & S_IFDIR))
460 /* an intermediate part of the name isn't a directory */
461 DEBUG(5,("Not a dir %s\n",start));
472 /* remember the rest of the pathname so it can be restored
474 if (end) strcpy(rest,end+1);
477 /* try to find this part of the path in the directory */
478 if (strchr(start,'?') || strchr(start,'*') ||
479 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
483 /* an intermediate part of the name can't be found */
484 DEBUG(5,("Intermediate not found %s\n",start));
489 /* just the last part of the name doesn't exist */
490 /* we may need to strupper() or strlower() it in case
491 this conversion is being used for file creation
493 /* if the filename is of mixed case then don't normalise it */
494 if (!case_preserve &&
495 (!strhasupper(start) || !strhaslower(start)))
498 /* check on the mangled stack to see if we can recover the
499 base of the filename */
500 if (is_mangled(start))
501 check_mangled_stack(start);
503 DEBUG(5,("New file %s\n",start));
507 /* restore the rest of the string */
510 strcpy(start+strlen(start)+1,rest);
511 end = start + strlen(start);
515 /* add to the dirpath that we have resolved so far */
516 if (*dirpath) strcat(dirpath,"/");
517 strcat(dirpath,start);
519 /* restore the / that we wiped out earlier */
523 /* the name has been resolved */
524 DEBUG(5,("conversion finished %s\n",name));
529 /****************************************************************************
530 normalise for DOS usage
531 ****************************************************************************/
532 static void disk_norm(int *bsize,int *dfree,int *dsize)
534 /* check if the disk is beyond the max disk size */
535 int maxdisksize = lp_maxdisksize();
537 /* convert to blocks - and don't overflow */
538 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
539 if (*dsize > maxdisksize) *dsize = maxdisksize;
540 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
545 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
550 if (*bsize > WORDMAX )
553 if (*dsize > WORDMAX)
555 if (*dfree > WORDMAX)
562 /****************************************************************************
563 return number of 1K blocks available on a path and total number
564 ****************************************************************************/
565 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
567 char *df_command = lp_dfree_command();
581 if (disk_quotas(path, bsize, dfree, dsize))
583 disk_norm(bsize,dfree,dsize);
584 return(((*bsize)/1024)*(*dfree));
589 /* possibly use system() to get the result */
590 if (df_command && *df_command)
596 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
597 sprintf(syscmd,"%s %s",df_command,path);
598 standard_sub_basic(syscmd);
600 ret = smbrun(syscmd,outfile);
601 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
604 FILE *f = fopen(outfile,"r");
610 fscanf(f,"%d %d %d",dsize,dfree,bsize);
614 DEBUG(0,("Can't open %s\n",outfile));
618 disk_norm(bsize,dfree,dsize);
619 return(((*bsize)/1024)*(*dfree));
623 DEBUG(1,("Warning - no statfs function\n"));
627 if (statfs(path,&fs,sizeof(fs),0) != 0)
630 if (statvfs(path, &fs))
633 if (statfs(path,&fs,sizeof(fs)) == -1)
635 if (statfs(path,&fs) == -1)
637 #endif /* USE_STATVFS */
640 DEBUG(3,("dfree call failed code errno=%d\n",errno));
644 return(((*bsize)/1024)*(*dfree));
649 *dfree = fs.fd_req.bfree;
650 *dsize = fs.fd_req.btot;
653 *bsize = fs.f_frsize;
656 /* eg: osf1 has f_fsize = fundamental filesystem block size,
657 f_bsize = optimal transfer block size (MX: 94-04-19) */
662 #endif /* USE_STATVFS */
667 *dfree = fs.f_bavail;
669 *dsize = fs.f_blocks;
672 #if defined(SCO) || defined(ISC) || defined(MIPS)
676 /* handle rediculous bsize values - some OSes are broken */
677 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
679 disk_norm(bsize,dfree,dsize);
685 DEBUG(0,("dfree seems to be broken on your system\n"));
686 *dsize = 20*1024*1024/(*bsize);
687 *dfree = MAX(1,*dfree);
689 return(((*bsize)/1024)*(*dfree));
694 /****************************************************************************
695 wrap it to get filenames right
696 ****************************************************************************/
697 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
699 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
704 /****************************************************************************
705 check a filename - possibly caling reducename
707 This is called by every routine before it allows an operation on a filename.
708 It does any final confirmation necessary to ensure that the filename is
709 a valid one for the user to access.
710 ****************************************************************************/
711 BOOL check_name(char *name,int cnum)
717 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
719 DEBUG(5,("check_name on %s failed\n",name));
724 /****************************************************************************
725 check a filename - possibly caling reducename
726 ****************************************************************************/
727 static void check_for_pipe(char *fname)
729 /* special case of pipe opens */
733 if (strstr(s,"pipe/"))
735 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
736 unix_ERR_class = ERRSRV;
737 unix_ERR_code = ERRaccess;
742 /****************************************************************************
744 ****************************************************************************/
745 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
749 Files[fnum].open = False;
753 strcpy(fname,fname1);
755 /* check permissions */
756 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
758 DEBUG(3,("Permission denied opening %s\n",fname));
759 check_for_pipe(fname);
763 /* this handles a bug in Win95 - it doesn't say to create the file when it
765 if (Connections[cnum].printer)
769 if (flags == O_WRONLY)
770 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
774 /* XXXX - is this OK?? */
775 /* this works around a utime bug but can cause other problems */
776 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
781 Files[fnum].fd = sys_open(fname,flags,mode);
783 if ((Files[fnum].fd>=0) &&
784 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
789 p = strrchr(dname,'/');
791 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
792 lp_minprintspace(SNUM(cnum))) {
793 close(Files[fnum].fd);
802 /* Fix for files ending in '.' */
803 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
804 (strchr(fname,'.')==NULL))
807 Files[fnum].fd = sys_open(fname,flags,mode);
810 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
811 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
814 char *p = strrchr(fname, '/');
816 if (p == fname) /* name is "/xxx" */
818 max_len = pathconf("/", _PC_NAME_MAX);
821 else if ((p == NULL) || (p == fname))
824 max_len = pathconf(".", _PC_NAME_MAX);
829 max_len = pathconf(fname, _PC_NAME_MAX);
833 if (strlen(p) > max_len)
835 char tmp = p[max_len];
838 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
844 if (Files[fnum].fd < 0)
846 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
847 fname,strerror(errno),flags));
848 check_for_pipe(fname);
852 if (Files[fnum].fd >= 0)
855 Connections[cnum].num_files_open++;
856 fstat(Files[fnum].fd,&st);
857 Files[fnum].mode = st.st_mode;
858 Files[fnum].open_time = time(NULL);
859 Files[fnum].size = 0;
860 Files[fnum].pos = -1;
861 Files[fnum].open = True;
862 Files[fnum].mmap_ptr = NULL;
863 Files[fnum].mmap_size = 0;
864 Files[fnum].can_lock = True;
865 Files[fnum].can_read = ((flags & O_WRONLY)==0);
866 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
867 Files[fnum].share_mode = 0;
868 Files[fnum].share_pending = False;
869 Files[fnum].print_file = Connections[cnum].printer;
870 Files[fnum].modified = False;
871 Files[fnum].cnum = cnum;
872 string_set(&Files[fnum].name,fname);
873 Files[fnum].wbmpx_ptr = NULL;
876 * If the printer is marked as postscript output a leading
877 * file identifier to ensure the file is treated as a raw
879 * This has a similar effect as CtrlD=0 in WIN.INI file.
880 * tim@fsg.com 09/06/94
882 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
883 Files[fnum].can_write)
885 DEBUG(3,("Writing postscript line\n"));
886 write_file(fnum,"%!\n",3);
889 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
890 timestring(),Connections[cnum].user,fname,
891 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
892 Connections[cnum].num_files_open,fnum));
897 /* mmap it if read-only */
898 if (!Files[fnum].can_write)
900 Files[fnum].mmap_size = file_size(fname);
901 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
902 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
904 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
906 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
907 Files[fnum].mmap_ptr = NULL;
913 /*******************************************************************
915 ********************************************************************/
916 void sync_file(int fnum)
919 fsync(Files[fnum].fd);
923 /****************************************************************************
924 run a file if it is a magic script
925 ****************************************************************************/
926 static void check_magic(int fnum,int cnum)
928 if (!*lp_magicscript(SNUM(cnum)))
931 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
935 if (!(p = strrchr(Files[fnum].name,'/')))
936 p = Files[fnum].name;
940 if (!strequal(lp_magicscript(SNUM(cnum)),p))
946 pstring magic_output;
948 strcpy(fname,Files[fnum].name);
950 if (*lp_magicoutput(SNUM(cnum)))
951 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
953 sprintf(magic_output,"%s.out",fname);
956 ret = smbrun(fname,magic_output);
957 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
963 /****************************************************************************
964 close a file - possibly invalidating the read prediction
965 ****************************************************************************/
966 void close_file(int fnum)
968 int cnum = Files[fnum].cnum;
969 invalidate_read_prediction(Files[fnum].fd);
970 Files[fnum].open = False;
971 Connections[cnum].num_files_open--;
972 if(Files[fnum].wbmpx_ptr)
974 free((char *)Files[fnum].wbmpx_ptr);
975 Files[fnum].wbmpx_ptr = NULL;
979 if(Files[fnum].mmap_ptr)
981 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
982 Files[fnum].mmap_ptr = NULL;
986 if (lp_share_modes(SNUM(cnum)))
987 del_share_mode(fnum);
989 close(Files[fnum].fd);
991 /* NT uses smbclose to start a print - weird */
992 if (Files[fnum].print_file)
995 /* check for magic scripts */
996 check_magic(fnum,cnum);
998 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
999 timestring(),Connections[cnum].user,Files[fnum].name,
1000 Connections[cnum].num_files_open));
1003 enum {AFAIL,AREAD,AWRITE,AALL};
1005 /*******************************************************************
1006 reproduce the share mode access table
1007 ********************************************************************/
1008 static int access_table(int new_deny,int old_deny,int old_mode,
1009 int share_pid,char *fname)
1011 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1013 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1014 if (old_deny == new_deny && share_pid == getpid())
1017 if (old_mode == 0) return(AREAD);
1019 /* the new smbpub.zip spec says that if the file extension is
1020 .com, .dll, .exe or .sym then allow the open. I will force
1021 it to read-only as this seems sensible although the spec is
1022 a little unclear on this. */
1023 if ((fname = strrchr(fname,'.'))) {
1024 if (strequal(fname,".com") ||
1025 strequal(fname,".dll") ||
1026 strequal(fname,".exe") ||
1027 strequal(fname,".sym"))
1037 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1038 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1039 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1042 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1043 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1044 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1047 if (old_deny==DENY_WRITE) return(AREAD);
1048 if (old_deny==DENY_READ) return(AWRITE);
1049 if (old_deny==DENY_NONE) return(AALL);
1055 /*******************************************************************
1056 check if the share mode on a file allows it to be deleted or unlinked
1057 return True if sharing doesn't prevent the operation
1058 ********************************************************************/
1059 BOOL check_file_sharing(int cnum,char *fname)
1062 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1064 if (!pid || !share_mode) return(True);
1066 if (share_mode == DENY_DOS)
1067 return(pid == getpid());
1069 /* XXXX exactly what share mode combinations should be allowed for
1070 deleting/renaming? */
1074 /****************************************************************************
1076 Helper for open_file_shared.
1077 Truncate a file after checking locking; close file if locked.
1078 **************************************************************************/
1079 static void truncate_unless_locked(int fnum, int cnum)
1081 if (Files[fnum].can_write){
1082 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1085 unix_ERR_class = ERRDOS;
1086 unix_ERR_code = ERRlock;
1089 ftruncate(Files[fnum].fd,0);
1094 /****************************************************************************
1095 open a file with a share mode
1096 ****************************************************************************/
1097 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1098 int mode,int *Access,int *action)
1102 int deny_mode = (share_mode>>4)&7;
1104 BOOL file_existed = file_exist(fname,&sbuf);
1105 BOOL fcbopen = False;
1108 Files[fnum].open = False;
1109 Files[fnum].fd = -1;
1111 /* this is for OS/2 EAs - try and say we don't support them */
1112 if (strstr(fname,".+,;=[].")) {
1113 unix_ERR_class = ERRDOS;
1114 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1118 if ((ofun & 0x3) == 0 && file_existed) {
1125 if ((ofun & 0x3) == 2)
1128 /* note that we ignore the append flag as
1129 append does not mean the same thing under dos and unix */
1131 switch (share_mode&0xF)
1148 if (flags != O_RDONLY && file_existed &&
1149 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1157 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1158 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1163 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1165 if (lp_share_modes(SNUM(cnum))) {
1169 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1172 /* someone else has a share lock on it, check to see
1174 int old_open_mode = old_share&0xF;
1175 int old_deny_mode = (old_share>>4)&7;
1177 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1178 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1179 deny_mode,old_deny_mode,old_open_mode,fname));
1181 unix_ERR_class = ERRDOS;
1182 unix_ERR_code = ERRbadshare;
1187 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1190 if ((access_allowed == AFAIL) ||
1191 (access_allowed == AREAD && flags == O_WRONLY) ||
1192 (access_allowed == AWRITE && flags == O_RDONLY)) {
1193 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1194 deny_mode,old_deny_mode,old_open_mode,
1198 unix_ERR_class = ERRDOS;
1199 unix_ERR_code = ERRbadshare;
1203 if (access_allowed == AREAD)
1206 if (access_allowed == AWRITE)
1212 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1213 flags,flags2,mode));
1215 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1216 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1218 open_file(fnum,cnum,fname,flags,mode);
1221 if (Files[fnum].open) {
1235 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1236 Files[fnum].share_pending = True;
1239 (*Access) = open_mode;
1243 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1244 if (!file_existed) *action = 2;
1245 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1249 share_mode_pending = True;
1251 if ((flags2&O_TRUNC) && file_existed)
1252 truncate_unless_locked(fnum,cnum);
1258 /*******************************************************************
1259 check for files that we should now set our share modes on
1260 ********************************************************************/
1261 static void check_share_modes(void)
1264 for (i=0;i<MAX_OPEN_FILES;i++)
1265 if(Files[i].open && Files[i].share_pending) {
1266 if (lp_share_modes(SNUM(Files[i].cnum))) {
1268 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1270 set_share_mode(i,Files[i].share_mode);
1271 Files[i].share_pending = False;
1274 Files[i].share_pending = False;
1280 /****************************************************************************
1281 seek a file. Try to avoid the seek if possible
1282 ****************************************************************************/
1283 int seek_file(int fnum,int pos)
1286 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1289 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1290 return(Files[fnum].pos);
1293 /****************************************************************************
1295 ****************************************************************************/
1296 int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
1300 if (!Files[fnum].can_write)
1302 ret = read_predict(Files[fnum].fd,
1310 mincnt = MAX(mincnt-ret,0);
1315 if (Files[fnum].mmap_ptr)
1317 int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1320 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1324 mincnt = MAX(mincnt-num,0);
1333 if (seek_file(fnum,pos) != pos)
1335 DEBUG(3,("Failed to seek to %d\n",pos));
1340 ret += read_with_timeout(Files[fnum].fd,
1351 /****************************************************************************
1353 ****************************************************************************/
1354 int write_file(int fnum,char *data,int n)
1356 if (!Files[fnum].can_write) {
1361 if (!Files[fnum].modified) {
1363 Files[fnum].modified = True;
1364 if (fstat(Files[fnum].fd,&st) == 0) {
1365 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1366 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1367 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1372 return(write_data(Files[fnum].fd,data,n));
1376 static int old_umask = 022;
1378 /****************************************************************************
1379 load parameters specific to a connection/service
1380 ****************************************************************************/
1381 BOOL become_service(int cnum,BOOL do_chdir)
1383 extern char magic_char;
1384 static int last_cnum = -1;
1387 if (!OPEN_CNUM(cnum))
1393 Connections[cnum].lastused = smb_last_time;
1398 ChDir(Connections[cnum].connectpath) != 0 &&
1399 ChDir(Connections[cnum].origpath) != 0)
1401 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1402 Connections[cnum].connectpath,cnum));
1406 if (cnum == last_cnum)
1411 case_default = lp_defaultcase(snum);
1412 case_preserve = lp_preservecase(snum);
1413 short_case_preserve = lp_shortpreservecase(snum);
1414 case_mangle = lp_casemangle(snum);
1415 case_sensitive = lp_casesensitive(snum);
1416 magic_char = lp_magicchar(snum);
1417 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1422 /****************************************************************************
1423 become the specified uid
1424 ****************************************************************************/
1425 static BOOL become_uid(int uid)
1427 if (initial_uid != 0)
1432 /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
1435 priv.pv_priv[0] = 0;
1436 priv.pv_priv[1] = 0;
1437 if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
1438 &priv, sizeof(priv_t)) < 0 ||
1439 setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 ||
1440 seteuid((uid_t)uid) < 0)
1441 DEBUG(1,("Can't set uid (AIX3)"));
1446 if (setresuid(-1,uid,-1) != 0)
1448 if ((seteuid(uid) != 0) &&
1452 DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
1453 uid,getuid(), geteuid()));
1455 DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
1459 if (((uid == -1) || (uid == 65535)) && geteuid() != uid)
1461 DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
1469 /****************************************************************************
1470 become the specified gid
1471 ****************************************************************************/
1472 static BOOL become_gid(int gid)
1474 if (initial_uid != 0)
1478 if (setresgid(-1,gid,-1) != 0)
1480 if (setgid(gid) != 0)
1483 DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
1484 gid,getgid(),getegid()));
1486 DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
1494 /****************************************************************************
1495 become the specified uid and gid
1496 ****************************************************************************/
1497 static BOOL become_id(int uid,int gid)
1499 return(become_gid(gid) && become_uid(uid));
1502 /****************************************************************************
1503 become the guest user
1504 ****************************************************************************/
1505 static BOOL become_guest(void)
1508 static struct passwd *pass=NULL;
1510 if (initial_uid != 0)
1514 pass = Get_Pwnam(lp_guestaccount(-1),True);
1515 if (!pass) return(False);
1517 ret = become_id(pass->pw_uid,pass->pw_gid);
1520 DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
1522 last_user.cnum = -2;
1527 /*******************************************************************
1528 check if a username is OK
1529 ********************************************************************/
1530 static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
1533 for (i=0;i<Connections[cnum].uid_cache.entries;i++)
1534 if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True);
1536 if (!user_ok(vuser->name,snum)) return(False);
1538 i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
1539 Connections[cnum].uid_cache.list[i] = vuser->uid;
1541 if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
1542 Connections[cnum].uid_cache.entries++;
1548 /****************************************************************************
1549 become the user of a connection number
1550 ****************************************************************************/
1551 BOOL become_user(int cnum, int uid)
1559 if (last_user.cnum == cnum && last_user.uid == uid) {
1560 DEBUG(4,("Skipping become_user - already user\n"));
1566 if (!OPEN_CNUM(cnum)) {
1567 DEBUG(2,("Connection %d not open\n",cnum));
1571 snum = Connections[cnum].service;
1573 if (Connections[cnum].force_user ||
1574 lp_security() == SEC_SHARE ||
1575 !(vuser = get_valid_user_struct(uid)) ||
1576 !check_user_ok(cnum,vuser,snum)) {
1577 uid = Connections[cnum].uid;
1578 gid = Connections[cnum].gid;
1579 groups = Connections[cnum].groups;
1580 ngroups = Connections[cnum].ngroups;
1583 DEBUG(2,("Invalid vuid used %d\n",uid));
1587 if(!*lp_force_group(snum))
1590 gid = Connections[cnum].gid;
1591 groups = vuser->user_groups;
1592 ngroups = vuser->user_ngroups;
1595 if (initial_uid == 0)
1597 if (!become_gid(gid)) return(False);
1599 #ifndef NO_SETGROUPS
1600 if (!IS_IPC(cnum)) {
1601 /* groups stuff added by ih/wreu */
1603 if (setgroups(ngroups,groups)<0)
1604 DEBUG(0,("setgroups call failed!\n"));
1608 if (!Connections[cnum].admin_user && !become_uid(uid))
1612 new_umask = 0777 & ~CREATE_MODE(cnum);
1613 old_umask = umask(new_umask);
1615 last_user.cnum = cnum;
1616 last_user.uid = uid;
1618 DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
1619 getuid(),geteuid(),getgid(),getegid(),new_umask));
1624 /****************************************************************************
1625 unbecome the user of a connection number
1626 ****************************************************************************/
1627 BOOL unbecome_user(void )
1629 if (last_user.cnum == -1)
1636 if (initial_uid == 0)
1639 setresuid(-1,getuid(),-1);
1640 setresgid(-1,getgid(),-1);
1642 if (seteuid(initial_uid) != 0)
1643 setuid(initial_uid);
1644 setgid(initial_gid);
1648 if (initial_uid == 0)
1649 DEBUG(2,("Running with no EID\n"));
1650 initial_uid = getuid();
1651 initial_gid = getgid();
1653 if (geteuid() != initial_uid)
1655 DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
1656 initial_uid = geteuid();
1658 if (getegid() != initial_gid)
1660 DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
1661 initial_gid = getegid();
1665 if (ChDir(OriginalDir) != 0)
1666 DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
1667 timestring(),OriginalDir));
1669 DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
1670 getuid(),geteuid(),getgid(),getegid()));
1672 last_user.cnum = -1;
1677 /****************************************************************************
1678 find a service entry
1679 ****************************************************************************/
1680 int find_service(char *service)
1684 string_sub(service,"\\","/");
1686 iService = lp_servicenumber(service);
1688 /* now handle the special case of a home directory */
1691 char *phome_dir = get_home_dir(service);
1692 DEBUG(3,("checking for home directory %s gave %s\n",service,
1693 phome_dir?phome_dir:"(NULL)"));
1697 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1699 lp_add_home(service,iHomeService,phome_dir);
1700 iService = lp_servicenumber(service);
1705 /* If we still don't have a service, attempt to add it as a printer. */
1708 int iPrinterService;
1710 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1714 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1716 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1718 DEBUG(3,("%s is a valid printer name\n", service));
1719 DEBUG(3,("adding %s as a printer service\n", service));
1720 lp_add_printer(service,iPrinterService);
1721 iService = lp_servicenumber(service);
1723 DEBUG(0,("failed to add %s as a printer service!\n", service));
1726 DEBUG(3,("%s is not a valid printer name\n", service));
1730 /* just possibly it's a default service? */
1733 char *defservice = lp_defaultservice();
1734 if (defservice && *defservice && !strequal(defservice,service)) {
1735 iService = find_service(defservice);
1736 if (iService >= 0) {
1737 string_sub(service,"_","/");
1738 iService = lp_add_service(service,iService);
1744 if (!VALID_SNUM(iService))
1746 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1751 DEBUG(3,("find_service() failed to find service %s\n", service));
1757 /****************************************************************************
1758 create an error packet from a cached error.
1759 ****************************************************************************/
1760 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1762 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1764 int32 eclass = wbmpx->wr_errclass;
1765 int32 err = wbmpx->wr_error;
1767 /* We can now delete the auxiliary struct */
1768 free((char *)wbmpx);
1769 Files[fnum].wbmpx_ptr = NULL;
1770 return error_packet(inbuf,outbuf,eclass,err,line);
1779 } unix_smb_errmap[] =
1781 {EPERM,ERRDOS,ERRnoaccess},
1782 {EACCES,ERRDOS,ERRnoaccess},
1783 {ENOENT,ERRDOS,ERRbadfile},
1784 {EIO,ERRHRD,ERRgeneral},
1785 {EBADF,ERRSRV,ERRsrverror},
1786 {EINVAL,ERRSRV,ERRsrverror},
1787 {EEXIST,ERRDOS,ERRfilexists},
1788 {ENFILE,ERRDOS,ERRnofids},
1789 {EMFILE,ERRDOS,ERRnofids},
1790 {ENOSPC,ERRHRD,ERRdiskfull},
1792 {EDQUOT,ERRHRD,ERRdiskfull},
1795 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1798 {EXDEV,ERRDOS,ERRdiffdevice},
1800 {EROFS,ERRHRD,ERRnowrite},
1805 /****************************************************************************
1806 create an error packet from errno
1807 ****************************************************************************/
1808 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1810 int eclass=def_class;
1814 if (unix_ERR_class != SUCCESS)
1816 eclass = unix_ERR_class;
1817 ecode = unix_ERR_code;
1818 unix_ERR_class = SUCCESS;
1823 while (unix_smb_errmap[i].smbclass != 0)
1825 if (unix_smb_errmap[i].unixerror == errno)
1827 eclass = unix_smb_errmap[i].smbclass;
1828 ecode = unix_smb_errmap[i].smbcode;
1835 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1839 /****************************************************************************
1840 create an error packet. Normally called using the ERROR() macro
1841 ****************************************************************************/
1842 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1844 int outsize = set_message(outbuf,0,0,True);
1846 cmd = CVAL(inbuf,smb_com);
1848 CVAL(outbuf,smb_rcls) = error_class;
1849 SSVAL(outbuf,smb_err,error_code);
1851 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1854 (int)CVAL(inbuf,smb_com),
1855 smb_fn_name(CVAL(inbuf,smb_com)),
1860 DEBUG(3,("error string = %s\n",strerror(errno)));
1866 #ifndef SIGCLD_IGNORE
1867 /****************************************************************************
1868 this prevents zombie child processes
1869 ****************************************************************************/
1870 static int sig_cld()
1872 static int depth = 0;
1875 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1882 DEBUG(5,("got SIGCLD\n"));
1885 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1889 /* Stevens, Adv. Unix Prog. says that on system V you must call
1890 wait before reinstalling the signal handler, because the kernel
1891 calls the handler from within the signal-call when there is a
1892 child that has exited. This would lead to an infinite recursion
1893 if done vice versa. */
1895 #ifndef DONT_REINSTALL_SIG
1896 #ifdef SIGCLD_IGNORE
1897 signal(SIGCLD, SIG_IGN);
1899 signal(SIGCLD, SIGNAL_CAST sig_cld);
1904 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1907 BlockSignals(False);
1912 /****************************************************************************
1913 this is called when the client exits abruptly
1914 **************************************************************************/
1915 static int sig_pipe()
1917 exit_server("Got sigpipe\n");
1921 /****************************************************************************
1922 open the socket communication
1923 ****************************************************************************/
1924 static BOOL open_sockets(BOOL is_daemon,int port)
1931 struct sockaddr addr;
1932 int in_addrlen = sizeof(addr);
1935 #ifdef SIGCLD_IGNORE
1936 signal(SIGCLD, SIG_IGN);
1938 signal(SIGCLD, SIGNAL_CAST sig_cld);
1941 /* open an incoming socket */
1942 s = open_socket_in(SOCK_STREAM, port, 0);
1946 /* ready to listen */
1947 if (listen(s, 5) == -1)
1949 DEBUG(0,("listen: %s",strerror(errno)));
1954 /* now accept incoming connections - forking a new process
1955 for each incoming connection */
1956 DEBUG(2,("waiting for a connection\n"));
1959 Client = accept(s,&addr,&in_addrlen);
1961 if (Client == -1 && errno == EINTR)
1966 DEBUG(0,("accept: %s",strerror(errno)));
1970 #ifdef NO_FORK_DEBUG
1971 #ifndef NO_SIGNAL_TEST
1972 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1973 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1977 if (Client != -1 && fork()==0)
1979 #ifndef NO_SIGNAL_TEST
1980 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1981 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1983 /* close the listening socket */
1986 /* close our standard file descriptors */
1989 set_socket_options(Client,"SO_KEEPALIVE");
1990 set_socket_options(Client,user_socket_options);
1994 close(Client); /* The parent doesn't need this socket */
2000 /* We will abort gracefully when the client or remote system
2002 #ifndef NO_SIGNAL_TEST
2003 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2007 /* close our standard file descriptors */
2010 set_socket_options(Client,"SO_KEEPALIVE");
2011 set_socket_options(Client,user_socket_options);
2018 /****************************************************************************
2019 check if a snum is in use
2020 ****************************************************************************/
2021 BOOL snum_used(int snum)
2024 for (i=0;i<MAX_CONNECTIONS;i++)
2025 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2030 /****************************************************************************
2031 reload the services file
2032 **************************************************************************/
2033 BOOL reload_services(BOOL test)
2040 strcpy(fname,lp_configfile());
2041 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2043 strcpy(servicesf,fname);
2050 if (test && !lp_file_list_changed())
2053 lp_killunused(snum_used);
2055 ret = lp_load(servicesf,False);
2057 /* perhaps the config filename is now set */
2059 reload_services(True);
2066 set_socket_options(Client,"SO_KEEPALIVE");
2067 set_socket_options(Client,user_socket_options);
2071 create_mangled_stack(lp_mangledstack());
2073 /* this forces service parameters to be flushed */
2074 become_service(-1,True);
2081 /****************************************************************************
2082 this prevents zombie child processes
2083 ****************************************************************************/
2084 static int sig_hup()
2087 DEBUG(0,("Got SIGHUP\n"));
2088 reload_services(False);
2089 #ifndef DONT_REINSTALL_SIG
2090 signal(SIGHUP,SIGNAL_CAST sig_hup);
2092 BlockSignals(False);
2096 /****************************************************************************
2097 Setup the groups a user belongs to.
2098 ****************************************************************************/
2099 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2100 int **p_igroups, gid_t **p_groups)
2102 if (-1 == initgroups(user,gid))
2106 DEBUG(0,("Unable to initgroups!\n"));
2107 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2108 DEBUG(0,("This is probably a problem with the account %s\n",user));
2116 ngroups = getgroups(0,&grp);
2119 igroups = (int *)malloc(sizeof(int)*ngroups);
2120 for (i=0;i<ngroups;i++)
2121 igroups[i] = 0x42424242;
2122 ngroups = getgroups(ngroups,(gid_t *)igroups);
2124 if (igroups[0] == 0x42424242)
2127 *p_ngroups = ngroups;
2129 /* The following bit of code is very strange. It is due to the
2130 fact that some OSes use int* and some use gid_t* for
2131 getgroups, and some (like SunOS) use both, one in prototypes,
2132 and one in man pages and the actual code. Thus we detect it
2133 dynamically using some very ugly code */
2136 /* does getgroups return ints or gid_t ?? */
2137 static BOOL groups_use_ints = True;
2139 if (groups_use_ints &&
2141 SVAL(igroups,2) == 0x4242)
2142 groups_use_ints = False;
2144 for (i=0;groups_use_ints && i<ngroups;i++)
2145 if (igroups[i] == 0x42424242)
2146 groups_use_ints = False;
2148 if (groups_use_ints)
2150 *p_igroups = igroups;
2151 *p_groups = (gid_t *)igroups;
2155 gid_t *groups = (gid_t *)igroups;
2156 igroups = (int *)malloc(sizeof(int)*ngroups);
2157 for (i=0;i<ngroups;i++)
2158 igroups[i] = groups[i];
2159 *p_igroups = igroups;
2160 *p_groups = (gid_t *)groups;
2163 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2164 for (i=0;i<ngroups;i++)
2165 DEBUG(3,("%d ",igroups[i]));
2171 /****************************************************************************
2172 make a connection to a service
2173 ****************************************************************************/
2174 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
2178 struct passwd *pass = NULL;
2179 connection_struct *pcon;
2182 static BOOL first_connection = True;
2186 snum = find_service(service);
2189 if (strequal(service,"IPC$"))
2191 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2195 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2199 if (strequal(service,HOMES_NAME))
2201 if (*user && Get_Pwnam(user,True))
2202 return(make_connection(user,user,password,pwlen,dev,vuid));
2204 if (validated_username(vuid))
2206 strcpy(user,validated_username(vuid));
2207 return(make_connection(user,user,password,pwlen,dev,vuid));
2211 if (!lp_snum_ok(snum) || !check_access(snum)) {
2215 /* you can only connect to the IPC$ service as an ipc device */
2216 if (strequal(service,"IPC$"))
2219 if (*dev == '?' || !*dev)
2221 if (lp_print_ok(snum))
2222 strcpy(dev,"LPT1:");
2227 /* if the request is as a printer and you can't print then refuse */
2229 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2230 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2234 /* lowercase the user name */
2237 /* add it as a possible user name */
2238 add_session_user(service);
2240 /* shall we let them in? */
2241 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2243 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2247 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2250 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2254 pcon = &Connections[cnum];
2255 bzero((char *)pcon,sizeof(*pcon));
2257 /* find out some info about the user */
2258 pass = Get_Pwnam(user,True);
2262 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2266 pcon->read_only = lp_readonly(snum);
2270 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2271 string_sub(list,"%S",service);
2273 if (user_in_list(user,list))
2274 pcon->read_only = True;
2276 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2277 string_sub(list,"%S",service);
2279 if (user_in_list(user,list))
2280 pcon->read_only = False;
2283 /* admin user check */
2284 if (user_in_list(user,lp_admin_users(snum)) &&
2287 pcon->admin_user = True;
2288 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2291 pcon->admin_user = False;
2293 pcon->force_user = force;
2294 pcon->uid = pass->pw_uid;
2295 pcon->gid = pass->pw_gid;
2296 pcon->num_files_open = 0;
2297 pcon->lastused = time(NULL);
2298 pcon->service = snum;
2300 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2301 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2302 pcon->dirptr = NULL;
2303 string_set(&pcon->dirpath,"");
2304 string_set(&pcon->user,user);
2307 if (*lp_force_group(snum))
2309 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2312 pcon->gid = gptr->gr_gid;
2313 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2316 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2320 if (*lp_force_user(snum))
2322 struct passwd *pass2;
2324 strcpy(fuser,lp_force_user(snum));
2325 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2328 pcon->uid = pass2->pw_uid;
2329 string_set(&pcon->user,fuser);
2331 pcon->force_user = True;
2332 DEBUG(3,("Forced user %s\n",fuser));
2335 DEBUG(1,("Couldn't find user %s\n",fuser));
2340 strcpy(s,lp_pathname(snum));
2341 standard_sub(cnum,s);
2342 string_set(&pcon->connectpath,s);
2343 DEBUG(3,("Connect path is %s\n",s));
2346 /* groups stuff added by ih */
2348 pcon->groups = NULL;
2352 /* Find all the groups this uid is in and store them. Used by become_user() */
2353 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2355 /* check number of connections */
2356 if (!claim_connection(cnum,
2357 lp_servicename(SNUM(cnum)),
2358 lp_max_connections(SNUM(cnum)),False))
2360 DEBUG(1,("too many connections - rejected\n"));
2364 if (lp_status(SNUM(cnum)))
2365 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2367 first_connection = False;
2372 /* execute any "root preexec = " line */
2373 if (*lp_rootpreexec(SNUM(cnum)))
2376 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2377 standard_sub(cnum,cmd);
2378 DEBUG(5,("cmd=%s\n",cmd));
2382 if (!become_user(cnum,pcon->uid))
2384 DEBUG(0,("Can't become connected user!\n"));
2386 if (!IS_IPC(cnum)) {
2387 yield_connection(cnum,
2388 lp_servicename(SNUM(cnum)),
2389 lp_max_connections(SNUM(cnum)));
2390 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2395 if (ChDir(pcon->connectpath) != 0)
2397 DEBUG(0,("Can't change directory to %s (%s)\n",
2398 pcon->connectpath,strerror(errno)));
2401 if (!IS_IPC(cnum)) {
2402 yield_connection(cnum,
2403 lp_servicename(SNUM(cnum)),
2404 lp_max_connections(SNUM(cnum)));
2405 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2410 string_set(&pcon->origpath,pcon->connectpath);
2412 #if SOFTLINK_OPTIMISATION
2413 /* resolve any soft links early */
2416 strcpy(s,pcon->connectpath);
2418 string_set(&pcon->connectpath,s);
2419 ChDir(pcon->connectpath);
2423 num_connections_open++;
2424 add_session_user(user);
2426 /* execute any "preexec = " line */
2427 if (*lp_preexec(SNUM(cnum)))
2430 strcpy(cmd,lp_preexec(SNUM(cnum)));
2431 standard_sub(cnum,cmd);
2435 /* we've finished with the sensitive stuff */
2439 extern struct from_host Client_info;
2440 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2442 Client_info.name,Client_info.addr,
2443 lp_servicename(SNUM(cnum)),user,
2453 /****************************************************************************
2454 find first available file slot
2455 ****************************************************************************/
2456 int find_free_file(void )
2459 for (i=1;i<MAX_OPEN_FILES;i++)
2462 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2466 /****************************************************************************
2467 find first available connection slot, starting from a random position.
2468 The randomisation stops problems with the server dieing and clients
2469 thinking the server is still available.
2470 ****************************************************************************/
2471 static int find_free_connection(int hash )
2475 hash = (hash % (MAX_CONNECTIONS-2))+1;
2479 for (i=hash+1;i!=hash;)
2481 if (!Connections[i].open && Connections[i].used == used)
2483 DEBUG(3,("found free connection number %d\n",i));
2487 if (i == MAX_CONNECTIONS)
2497 DEBUG(1,("ERROR! Out of connection structures\n"));
2502 /****************************************************************************
2503 reply for the core protocol
2504 ****************************************************************************/
2505 int reply_corep(char *outbuf)
2507 int outsize = set_message(outbuf,1,0,True);
2509 Protocol = PROTOCOL_CORE;
2515 /****************************************************************************
2516 reply for the coreplus protocol
2517 ****************************************************************************/
2518 int reply_coreplus(char *outbuf)
2520 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2521 int outsize = set_message(outbuf,13,0,True);
2522 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2523 readbraw and writebraw (possibly) */
2524 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2525 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2527 Protocol = PROTOCOL_COREPLUS;
2533 /****************************************************************************
2534 reply for the lanman 1.0 protocol
2535 ****************************************************************************/
2536 int reply_lanman1(char *outbuf)
2538 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2540 BOOL doencrypt = SMBENCRYPT();
2541 time_t t = time(NULL);
2543 if (lp_security()>=SEC_USER) secword |= 1;
2544 if (doencrypt) secword |= 2;
2546 set_message(outbuf,13,doencrypt?8:0,True);
2547 SSVAL(outbuf,smb_vwv1,secword);
2549 /* Create a token value and add it to the outgoing packet. */
2551 generate_next_challenge(smb_buf(outbuf));
2554 Protocol = PROTOCOL_LANMAN1;
2556 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2557 DEBUG(3,("using password server validation\n"));
2559 if (doencrypt) set_challenge(smb_buf(outbuf));
2563 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2564 SSVAL(outbuf,smb_vwv2,maxxmit);
2565 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2566 SSVAL(outbuf,smb_vwv4,1);
2567 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2568 readbraw writebraw (possibly) */
2569 SIVAL(outbuf,smb_vwv6,getpid());
2570 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2572 put_dos_date(outbuf,smb_vwv8,t);
2574 return (smb_len(outbuf)+4);
2578 /****************************************************************************
2579 reply for the lanman 2.0 protocol
2580 ****************************************************************************/
2581 int reply_lanman2(char *outbuf)
2583 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2585 BOOL doencrypt = SMBENCRYPT();
2586 time_t t = time(NULL);
2588 if (lp_security()>=SEC_USER) secword |= 1;
2589 if (doencrypt) secword |= 2;
2591 set_message(outbuf,13,doencrypt?8:0,True);
2592 SSVAL(outbuf,smb_vwv1,secword);
2594 /* Create a token value and add it to the outgoing packet. */
2596 generate_next_challenge(smb_buf(outbuf));
2599 SIVAL(outbuf,smb_vwv6,getpid());
2601 Protocol = PROTOCOL_LANMAN2;
2603 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2604 DEBUG(3,("using password server validation\n"));
2606 if (doencrypt) set_challenge(smb_buf(outbuf));
2610 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2611 SSVAL(outbuf,smb_vwv2,maxxmit);
2612 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2613 SSVAL(outbuf,smb_vwv4,1);
2614 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2615 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2616 put_dos_date(outbuf,smb_vwv8,t);
2618 return (smb_len(outbuf)+4);
2621 /****************************************************************************
2622 reply for the nt protocol
2623 ****************************************************************************/
2624 int reply_nt1(char *outbuf)
2626 int capabilities=0x300; /* has dual names + lock_and_read */
2628 BOOL doencrypt = SMBENCRYPT();
2629 time_t t = time(NULL);
2631 if (lp_security()>=SEC_USER) secword |= 1;
2632 if (doencrypt) secword |= 2;
2634 set_message(outbuf,17,doencrypt?8:0,True);
2635 CVAL(outbuf,smb_vwv1) = secword;
2637 /* Create a token value and add it to the outgoing packet. */
2639 generate_next_challenge(smb_buf(outbuf));
2640 /* Tell the nt machine how long the challenge is. */
2641 SSVALS(outbuf,smb_vwv16+1,8);
2645 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2647 Protocol = PROTOCOL_NT1;
2649 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2650 DEBUG(3,("using password server validation\n"));
2652 if (doencrypt) set_challenge(smb_buf(outbuf));
2656 if (lp_readraw() && lp_writeraw())
2659 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2660 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2661 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2662 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2663 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2664 put_long_date(outbuf+smb_vwv11+1,t);
2665 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2667 return (smb_len(outbuf)+4);
2671 /* these are the protocol lists used for auto architecture detection:
2674 protocol [PC NETWORK PROGRAM 1.0]
2675 protocol [XENIX CORE]
2676 protocol [MICROSOFT NETWORKS 1.03]
2677 protocol [LANMAN1.0]
2678 protocol [Windows for Workgroups 3.1a]
2679 protocol [LM1.2X002]
2680 protocol [LANMAN2.1]
2681 protocol [NT LM 0.12]
2684 protocol [PC NETWORK PROGRAM 1.0]
2685 protocol [XENIX CORE]
2686 protocol [MICROSOFT NETWORKS 1.03]
2687 protocol [LANMAN1.0]
2688 protocol [Windows for Workgroups 3.1a]
2689 protocol [LM1.2X002]
2690 protocol [LANMAN2.1]
2691 protocol [NT LM 0.12]
2694 protocol [PC NETWORK PROGRAM 1.0]
2695 protocol [XENIX CORE]
2696 protocol [LANMAN1.0]
2697 protocol [LM1.2X002]
2698 protocol [LANMAN2.1]
2702 * Modified to recognize the architecture of the remote machine better.
2704 * This appears to be the matrix of which protocol is used by which
2706 Protocol WfWg Win95 WinNT OS/2
2707 PC NETWORK PROGRAM 1.0 1 1 1 1
2709 MICROSOFT NETWORKS 3.0 2 2
2711 MICROSOFT NETWORKS 1.03 3
2714 Windows for Workgroups 3.1a 5 5 5
2719 * tim@fsg.com 09/29/95
2722 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2723 #define ARCH_WIN95 0x2
2724 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2725 #define ARCH_WINNT 0x8
2726 #define ARCH_SAMBA 0x10
2728 #define ARCH_ALL 0x1F
2730 /* List of supported protocols, most desired first */
2734 int (*proto_reply_fn)(char *);
2736 } supported_protocols[] = {
2737 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2738 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2739 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2740 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2741 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2742 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2743 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2744 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2745 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2750 /****************************************************************************
2752 ****************************************************************************/
2753 static int reply_negprot(char *inbuf,char *outbuf)
2755 extern fstring remote_arch;
2756 int outsize = set_message(outbuf,1,0,True);
2761 int bcc = SVAL(smb_buf(inbuf),-2);
2762 int arch = ARCH_ALL;
2764 p = smb_buf(inbuf)+1;
2765 while (p < (smb_buf(inbuf) + bcc))
2768 DEBUG(3,("Requested protocol [%s]\n",p));
2769 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2770 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2771 else if (strcsequal(p,"DOS LM1.2X002"))
2772 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2773 else if (strcsequal(p,"DOS LANMAN2.1"))
2774 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2775 else if (strcsequal(p,"NT LM 0.12"))
2776 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2777 else if (strcsequal(p,"LANMAN2.1"))
2778 arch &= ( ARCH_WINNT | ARCH_OS2 );
2779 else if (strcsequal(p,"LM1.2X002"))
2780 arch &= ( ARCH_WINNT | ARCH_OS2 );
2781 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2783 else if (strcsequal(p,"XENIX CORE"))
2784 arch &= ( ARCH_WINNT | ARCH_OS2 );
2785 else if (strcsequal(p,"Samba")) {
2795 strcpy(remote_arch,"Samba");
2798 strcpy(remote_arch,"WfWg");
2801 strcpy(remote_arch,"Win95");
2804 strcpy(remote_arch,"WinNT");
2807 strcpy(remote_arch,"OS2");
2810 strcpy(remote_arch,"UNKNOWN");
2814 /* possibly reload - change of architecture */
2815 reload_services(True);
2817 /* a special case to stop password server loops */
2818 if (Index == 1 && strequal(remote_machine,myhostname) &&
2819 lp_security()==SEC_SERVER)
2820 exit_server("Password server loop!");
2822 /* Check for protocols, most desirable first */
2823 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2825 p = smb_buf(inbuf)+1;
2827 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2828 while (p < (smb_buf(inbuf) + bcc))
2830 if (strequal(p,supported_protocols[protocol].proto_name))
2839 SSVAL(outbuf,smb_vwv0,choice);
2841 extern fstring remote_proto;
2842 strcpy(remote_proto,supported_protocols[protocol].short_name);
2843 reload_services(True);
2844 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2845 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2848 DEBUG(0,("No protocol supported !\n"));
2850 SSVAL(outbuf,smb_vwv0,choice);
2852 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2858 /****************************************************************************
2859 parse a connect packet
2860 ****************************************************************************/
2861 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2863 char *p = smb_buf(buf) + 1;
2866 DEBUG(4,("parsing connect string %s\n",p));
2868 p2 = strrchr(p,'\\');
2872 strcpy(service,p2+1);
2877 *pwlen = strlen(password);
2884 p = strchr(service,'%');
2893 /****************************************************************************
2894 close all open files for a connection
2895 ****************************************************************************/
2896 static void close_open_files(int cnum)
2899 for (i=0;i<MAX_OPEN_FILES;i++)
2900 if( Files[i].cnum == cnum && Files[i].open) {
2907 /****************************************************************************
2909 ****************************************************************************/
2910 void close_cnum(int cnum, int uid)
2912 extern struct from_host Client_info;
2914 DirCacheFlush(SNUM(cnum));
2918 if (!OPEN_CNUM(cnum))
2920 DEBUG(0,("Can't close cnum %d\n",cnum));
2924 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2926 Client_info.name,Client_info.addr,
2927 lp_servicename(SNUM(cnum))));
2929 yield_connection(cnum,
2930 lp_servicename(SNUM(cnum)),
2931 lp_max_connections(SNUM(cnum)));
2933 if (lp_status(SNUM(cnum)))
2934 yield_connection(cnum,"STATUS.",MAXSTATUS);
2936 close_open_files(cnum);
2937 dptr_closecnum(cnum);
2939 /* execute any "postexec = " line */
2940 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2943 strcpy(cmd,lp_postexec(SNUM(cnum)));
2944 standard_sub(cnum,cmd);
2950 /* execute any "root postexec = " line */
2951 if (*lp_rootpostexec(SNUM(cnum)))
2954 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2955 standard_sub(cnum,cmd);
2959 Connections[cnum].open = False;
2960 num_connections_open--;
2961 if (Connections[cnum].ngroups && Connections[cnum].groups)
2963 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2964 free(Connections[cnum].groups);
2965 free(Connections[cnum].igroups);
2966 Connections[cnum].groups = NULL;
2967 Connections[cnum].igroups = NULL;
2968 Connections[cnum].ngroups = 0;
2971 string_set(&Connections[cnum].user,"");
2972 string_set(&Connections[cnum].dirpath,"");
2973 string_set(&Connections[cnum].connectpath,"");
2977 /****************************************************************************
2978 simple routines to do connection counting
2979 ****************************************************************************/
2980 BOOL yield_connection(int cnum,char *name,int max_connections)
2982 struct connect_record crec;
2985 int mypid = getpid();
2988 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2990 if (max_connections <= 0)
2993 bzero(&crec,sizeof(crec));
2995 strcpy(fname,lp_lockdir());
2996 standard_sub(cnum,fname);
2997 trim_string(fname,"","/");
3001 strcat(fname,".LCK");
3003 f = fopen(fname,"r+");
3006 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3010 fseek(f,0,SEEK_SET);
3012 /* find a free spot */
3013 for (i=0;i<max_connections;i++)
3015 if (fread(&crec,sizeof(crec),1,f) != 1)
3017 DEBUG(2,("Entry not found in lock file %s\n",fname));
3021 if (crec.pid == mypid && crec.cnum == cnum)
3025 if (crec.pid != mypid || crec.cnum != cnum)
3028 DEBUG(2,("Entry not found in lock file %s\n",fname));
3032 bzero((void *)&crec,sizeof(crec));
3034 /* remove our mark */
3035 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3036 fwrite(&crec,sizeof(crec),1,f) != 1)
3038 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3043 DEBUG(3,("Yield successful\n"));
3050 /****************************************************************************
3051 simple routines to do connection counting
3052 ****************************************************************************/
3053 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3055 struct connect_record crec;
3058 int snum = SNUM(cnum);
3062 if (max_connections <= 0)
3065 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3067 strcpy(fname,lp_lockdir());
3068 standard_sub(cnum,fname);
3069 trim_string(fname,"","/");
3071 if (!directory_exist(fname,NULL))
3076 strcat(fname,".LCK");
3078 if (!file_exist(fname,NULL))
3080 f = fopen(fname,"w");
3084 total_recs = file_size(fname) / sizeof(crec);
3086 f = fopen(fname,"r+");
3090 DEBUG(1,("couldn't open lock file %s\n",fname));
3094 /* find a free spot */
3095 for (i=0;i<max_connections;i++)
3098 if (i>=total_recs ||
3099 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3100 fread(&crec,sizeof(crec),1,f) != 1)
3102 if (foundi < 0) foundi = i;
3106 if (Clear && crec.pid && !process_exists(crec.pid))
3108 fseek(f,i*sizeof(crec),SEEK_SET);
3109 bzero((void *)&crec,sizeof(crec));
3110 fwrite(&crec,sizeof(crec),1,f);
3111 if (foundi < 0) foundi = i;
3114 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3123 DEBUG(3,("no free locks in %s\n",fname));
3128 /* fill in the crec */
3129 bzero((void *)&crec,sizeof(crec));
3130 crec.magic = 0x280267;
3131 crec.pid = getpid();
3133 crec.uid = Connections[cnum].uid;
3134 crec.gid = Connections[cnum].gid;
3135 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3136 crec.start = time(NULL);
3139 extern struct from_host Client_info;
3140 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
3141 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
3145 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3146 fwrite(&crec,sizeof(crec),1,f) != 1)
3157 /*******************************************************************
3158 prepare to dump a core file - carefully!
3159 ********************************************************************/
3160 static BOOL dump_core(void)
3164 strcpy(dname,debugf);
3165 if ((p=strrchr(dname,'/'))) *p=0;
3166 strcat(dname,"/corefiles");
3168 sys_chown(dname,getuid(),getgid());
3170 if (chdir(dname)) return(False);
3173 #ifndef NO_GETRLIMIT
3177 getrlimit(RLIMIT_CORE, &rlp);
3178 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3179 setrlimit(RLIMIT_CORE, &rlp);
3180 getrlimit(RLIMIT_CORE, &rlp);
3181 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3187 DEBUG(0,("Dumping core in %s\n",dname));
3192 /****************************************************************************
3194 ****************************************************************************/
3195 void exit_server(char *reason)
3197 static int firsttime=1;
3200 if (!firsttime) exit(0);
3204 DEBUG(2,("Closing connections\n"));
3205 for (i=0;i<MAX_CONNECTIONS;i++)
3206 if (Connections[i].open)
3209 if (dcelogin_atmost_once)
3213 int oldlevel = DEBUGLEVEL;
3215 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3217 show_msg(last_inbuf);
3218 DEBUGLEVEL = oldlevel;
3219 DEBUG(0,("===============================================================\n"));
3221 if (dump_core()) return;
3224 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3228 /****************************************************************************
3229 do some standard substitutions in a string
3230 ****************************************************************************/
3231 void standard_sub(int cnum,char *s)
3233 if (!strchr(s,'%')) return;
3235 if (VALID_CNUM(cnum))
3237 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3238 string_sub(s,"%P",Connections[cnum].connectpath);
3239 string_sub(s,"%u",Connections[cnum].user);
3240 if (strstr(s,"%H")) {
3241 char *home = get_home_dir(Connections[cnum].user);
3242 if (home) string_sub(s,"%H",home);
3244 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3246 standard_sub_basic(s);
3250 These flags determine some of the permissions required to do an operation
3252 Note that I don't set NEED_WRITE on some write operations because they
3253 are used by some brain-dead clients when printing, and I don't want to
3254 force write permissions on print services.
3256 #define AS_USER (1<<0)
3257 #define NEED_WRITE (1<<1)
3258 #define TIME_INIT (1<<2)
3259 #define CAN_IPC (1<<3)
3260 #define AS_GUEST (1<<5)
3264 define a list of possible SMB messages and their corresponding
3265 functions. Any message that has a NULL function is unimplemented -
3266 please feel free to contribute implementations!
3268 struct smb_message_struct
3282 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3283 {SMBtcon,"SMBtcon",reply_tcon,0},
3284 {SMBtdis,"SMBtdis",reply_tdis,0},
3285 {SMBexit,"SMBexit",reply_exit,0},
3286 {SMBioctl,"SMBioctl",reply_ioctl,0},
3287 {SMBecho,"SMBecho",reply_echo,0},
3288 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3289 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3290 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3291 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3292 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3293 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3294 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3295 {SMBopen,"SMBopen",reply_open,AS_USER},
3297 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3298 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3299 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3301 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3302 {SMBread,"SMBread",reply_read,AS_USER},
3303 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3304 {SMBclose,"SMBclose",reply_close,AS_USER},
3305 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3306 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3307 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3308 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3310 /* this is a Pathworks specific call, allowing the
3311 changing of the root path */
3312 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3314 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3315 {SMBflush,"SMBflush",reply_flush,AS_USER},
3316 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3317 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3318 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3319 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3320 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3321 {SMBlock,"SMBlock",reply_lock,AS_USER},
3322 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3324 /* CORE+ PROTOCOL FOLLOWS */
3326 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3327 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3328 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3329 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3330 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3332 /* LANMAN1.0 PROTOCOL FOLLOWS */
3334 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3335 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3336 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3337 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3338 {SMBwritec,"SMBwritec",NULL,AS_USER},
3339 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3340 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3341 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3342 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3343 {SMBioctls,"SMBioctls",NULL,AS_USER},
3344 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3345 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3347 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3348 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3349 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3350 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3352 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3353 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3354 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3356 /* LANMAN2.0 PROTOCOL FOLLOWS */
3357 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3358 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3359 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3360 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3362 /* messaging routines */
3363 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3364 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3365 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3366 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3368 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3370 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3371 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3372 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3373 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3376 /****************************************************************************
3377 return a string containing the function name of a SMB command
3378 ****************************************************************************/
3379 char *smb_fn_name(int type)
3381 static char *unknown_name = "SMBunknown";
3382 static int num_smb_messages =
3383 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3386 for (match=0;match<num_smb_messages;match++)
3387 if (smb_messages[match].code == type)
3390 if (match == num_smb_messages)
3391 return(unknown_name);
3393 return(smb_messages[match].name);
3397 /****************************************************************************
3398 do a switch on the message type, and return the response size
3399 ****************************************************************************/
3400 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3404 static int num_smb_messages =
3405 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3409 struct timeval msg_start_time;
3410 struct timeval msg_end_time;
3411 static unsigned long total_time = 0;
3413 GetTimeOfDay(&msg_start_time);
3420 last_message = type;
3422 /* make sure this is an SMB packet */
3423 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3425 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3429 for (match=0;match<num_smb_messages;match++)
3430 if (smb_messages[match].code == type)
3433 if (match == num_smb_messages)
3435 DEBUG(0,("Unknown message type %d!\n",type));
3436 outsize = reply_unknown(inbuf,outbuf);
3440 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3441 if (smb_messages[match].fn)
3443 int cnum = SVAL(inbuf,smb_tid);
3444 int flags = smb_messages[match].flags;
3445 int uid = SVAL(inbuf,smb_uid);
3447 /* does this protocol need to be run as root? */
3448 if (!(flags & AS_USER))
3451 /* does this protocol need to be run as the connected user? */
3452 if ((flags & AS_USER) && !become_user(cnum,uid))
3453 return(ERROR(ERRSRV,ERRinvnid));
3455 /* does it need write permission? */
3456 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3457 return(ERROR(ERRSRV,ERRaccess));
3459 /* ipc services are limited */
3460 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3461 return(ERROR(ERRSRV,ERRaccess));
3463 /* load service specific parameters */
3464 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3465 return(ERROR(ERRSRV,ERRaccess));
3467 /* does this protocol need to be run as guest? */
3468 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3469 return(ERROR(ERRSRV,ERRaccess));
3473 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3477 outsize = reply_unknown(inbuf,outbuf);
3482 GetTimeOfDay(&msg_end_time);
3483 if (!(smb_messages[match].flags & TIME_INIT))
3485 smb_messages[match].time = 0;
3486 smb_messages[match].flags |= TIME_INIT;
3489 unsigned long this_time =
3490 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3491 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3492 smb_messages[match].time += this_time;
3493 total_time += this_time;
3495 DEBUG(2,("TIME %s %d usecs %g pct\n",
3496 smb_fn_name(type),smb_messages[match].time,
3497 (100.0*smb_messages[match].time) / total_time));
3504 /****************************************************************************
3505 construct a chained reply and add it to the already made reply
3507 inbuf points to the original message start.
3508 inbuf2 points to the smb_wct part of the secondary message
3509 type is the type of the secondary message
3510 outbuf points to the original outbuffer
3511 outbuf2 points to the smb_wct field of the new outbuffer
3512 size is the total length of the incoming message (from inbuf1)
3513 bufsize is the total buffer size
3515 return how many bytes were added to the response
3516 ****************************************************************************/
3517 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3521 static BOOL in_chain = False;
3522 static char *last_outbuf=NULL;
3523 BOOL was_inchain = in_chain;
3524 int insize_remaining;
3525 static int insize_deleted;
3528 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3530 outbuf = last_outbuf;
3536 inbuf2 -= insize_deleted;
3537 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3538 insize_deleted += size - (insize_remaining + smb_wct);
3541 last_outbuf = outbuf;
3544 /* allocate some space for the in and out buffers of the chained message */
3545 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3546 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3550 DEBUG(0,("Out of memory in chain reply\n"));
3551 return(ERROR(ERRSRV,ERRnoresource));
3554 ibuf += SMB_ALIGNMENT;
3555 obuf += SMB_ALIGNMENT;
3557 /* create the in buffer */
3558 memcpy(ibuf,inbuf,smb_wct);
3559 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3560 CVAL(ibuf,smb_com) = type;
3562 /* create the out buffer */
3563 bzero(obuf,smb_size);
3565 set_message(obuf,0,0,True);
3566 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3568 memcpy(obuf+4,ibuf+4,4);
3569 CVAL(obuf,smb_rcls) = SUCCESS;
3570 CVAL(obuf,smb_reh) = 0;
3571 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3573 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3574 SSVAL(obuf,smb_err,SUCCESS);
3575 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3576 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3577 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3578 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3580 DEBUG(3,("Chained message\n"));
3583 /* process the request */
3584 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3585 bufsize-chain_size);
3587 /* copy the new reply header over the old one, but preserve
3588 the smb_com field */
3589 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3591 /* and copy the data from the reply to the right spot */
3592 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3594 /* free the allocated buffers */
3595 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3596 if (obuf) free(obuf-SMB_ALIGNMENT);
3598 in_chain = was_inchain;
3600 /* return how much extra has been added to the packet */
3601 return(outsize - smb_wct);
3606 /****************************************************************************
3607 construct a reply to the incoming packet
3608 ****************************************************************************/
3609 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3611 int type = CVAL(inbuf,smb_com);
3613 int msg_type = CVAL(inbuf,0);
3615 smb_last_time = time(NULL);
3619 bzero(outbuf,smb_size);
3622 return(reply_special(inbuf,outbuf));
3624 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3625 set_message(outbuf,0,0,True);
3627 memcpy(outbuf+4,inbuf+4,4);
3628 CVAL(outbuf,smb_rcls) = SUCCESS;
3629 CVAL(outbuf,smb_reh) = 0;
3630 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3632 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3633 SSVAL(outbuf,smb_err,SUCCESS);
3634 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3635 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3636 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3637 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3639 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3642 smb_setlen(outbuf,outsize - 4);
3647 /****************************************************************************
3648 process commands from the client
3649 ****************************************************************************/
3652 static int trans_num = 0;
3654 extern struct from_host Client_info;
3657 fromhost(Client,&Client_info);
3659 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3660 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3661 if ((InBuffer == NULL) || (OutBuffer == NULL))
3664 InBuffer += SMB_ALIGNMENT;
3665 OutBuffer += SMB_ALIGNMENT;
3668 DEBUG(3,("priming nmbd\n"));
3671 ip = *interpret_addr2("localhost");
3672 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3674 send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM);
3678 last_user.cnum = -1;
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 /* check for socket failure */
3727 DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno)));
3733 /* become root again if waiting */
3736 /* check for smb.conf reload */
3737 if (!(counter%SMBD_RELOAD_CHECK))
3738 reload_services(True);
3740 /* check the share modes every 10 secs */
3741 if (!(counter%SHARE_MODES_CHECK))
3742 check_share_modes();
3744 /* clean the share modes every 5 minutes */
3745 if (!(counter%SHARE_MODES_CLEAN))
3746 clean_share_files();
3748 /* automatic timeout if all connections are closed */
3749 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3750 DEBUG(2,("%s Closing idle connection\n",timestring()));
3754 if (keepalive && (counter-last_keepalive)>keepalive) {
3755 extern int password_client;
3756 if (!send_keepalive(Client)) {
3757 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3760 /* also send a keepalive to the password server if its still
3762 if (password_client != -1)
3763 send_keepalive(password_client);
3764 last_keepalive = counter;
3767 /* check for connection timeouts */
3768 for (i=0;i<MAX_CONNECTIONS;i++)
3769 if (Connections[i].open)
3771 /* close dirptrs on connections that are idle */
3772 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3775 if (Connections[i].num_files_open > 0 ||
3776 (t-Connections[i].lastused)<deadtime)