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();
2630 if (lp_security()>=SEC_USER) secword |= 1;
2631 if (doencrypt) secword |= 2;
2633 set_message(outbuf,17,doencrypt?8:0,True);
2634 CVAL(outbuf,smb_vwv1) = secword;
2636 /* Create a token value and add it to the outgoing packet. */
2638 generate_next_challenge(smb_buf(outbuf));
2639 /* Tell the nt machine how long the challenge is. */
2640 SSVALS(outbuf,smb_vwv16+1,8);
2644 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2646 Protocol = PROTOCOL_NT1;
2648 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2649 DEBUG(3,("using password server validation\n"));
2651 if (doencrypt) set_challenge(smb_buf(outbuf));
2655 if (lp_readraw() && lp_writeraw())
2658 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2659 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2660 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2661 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2662 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2663 put_long_date(outbuf+smb_vwv11+1,time(NULL));
2664 SSVALS(outbuf,smb_vwv15+1,TimeDiff(time(NULL))/60);
2666 return (smb_len(outbuf)+4);
2670 /* these are the protocol lists used for auto architecture detection:
2673 protocol [PC NETWORK PROGRAM 1.0]
2674 protocol [XENIX CORE]
2675 protocol [MICROSOFT NETWORKS 1.03]
2676 protocol [LANMAN1.0]
2677 protocol [Windows for Workgroups 3.1a]
2678 protocol [LM1.2X002]
2679 protocol [LANMAN2.1]
2680 protocol [NT LM 0.12]
2683 protocol [PC NETWORK PROGRAM 1.0]
2684 protocol [XENIX CORE]
2685 protocol [MICROSOFT NETWORKS 1.03]
2686 protocol [LANMAN1.0]
2687 protocol [Windows for Workgroups 3.1a]
2688 protocol [LM1.2X002]
2689 protocol [LANMAN2.1]
2690 protocol [NT LM 0.12]
2693 protocol [PC NETWORK PROGRAM 1.0]
2694 protocol [XENIX CORE]
2695 protocol [LANMAN1.0]
2696 protocol [LM1.2X002]
2697 protocol [LANMAN2.1]
2701 * Modified to recognize the architecture of the remote machine better.
2703 * This appears to be the matrix of which protocol is used by which
2705 Protocol WfWg Win95 WinNT OS/2
2706 PC NETWORK PROGRAM 1.0 1 1 1 1
2708 MICROSOFT NETWORKS 3.0 2 2
2710 MICROSOFT NETWORKS 1.03 3
2713 Windows for Workgroups 3.1a 5 5 5
2718 * tim@fsg.com 09/29/95
2721 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2722 #define ARCH_WIN95 0x2
2723 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2724 #define ARCH_WINNT 0x8
2725 #define ARCH_SAMBA 0x10
2727 #define ARCH_ALL 0x1F
2729 /* List of supported protocols, most desired first */
2733 int (*proto_reply_fn)(char *);
2735 } supported_protocols[] = {
2736 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2737 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2738 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2739 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2740 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2741 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2742 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2743 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2744 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2749 /****************************************************************************
2751 ****************************************************************************/
2752 static int reply_negprot(char *inbuf,char *outbuf)
2754 extern fstring remote_arch;
2755 int outsize = set_message(outbuf,1,0,True);
2760 int bcc = SVAL(smb_buf(inbuf),-2);
2761 int arch = ARCH_ALL;
2763 p = smb_buf(inbuf)+1;
2764 while (p < (smb_buf(inbuf) + bcc))
2767 DEBUG(3,("Requested protocol [%s]\n",p));
2768 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2769 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2770 else if (strcsequal(p,"DOS LM1.2X002"))
2771 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2772 else if (strcsequal(p,"DOS LANMAN2.1"))
2773 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2774 else if (strcsequal(p,"NT LM 0.12"))
2775 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2776 else if (strcsequal(p,"LANMAN2.1"))
2777 arch &= ( ARCH_WINNT | ARCH_OS2 );
2778 else if (strcsequal(p,"LM1.2X002"))
2779 arch &= ( ARCH_WINNT | ARCH_OS2 );
2780 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2782 else if (strcsequal(p,"XENIX CORE"))
2783 arch &= ( ARCH_WINNT | ARCH_OS2 );
2784 else if (strcsequal(p,"Samba")) {
2794 strcpy(remote_arch,"Samba");
2797 strcpy(remote_arch,"WfWg");
2800 strcpy(remote_arch,"Win95");
2803 strcpy(remote_arch,"WinNT");
2806 strcpy(remote_arch,"OS2");
2809 strcpy(remote_arch,"UNKNOWN");
2813 /* possibly reload - change of architecture */
2814 reload_services(True);
2816 /* a special case to stop password server loops */
2817 if (Index == 1 && strequal(remote_machine,myhostname) &&
2818 lp_security()==SEC_SERVER)
2819 exit_server("Password server loop!");
2821 /* Check for protocols, most desirable first */
2822 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2824 p = smb_buf(inbuf)+1;
2826 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2827 while (p < (smb_buf(inbuf) + bcc))
2829 if (strequal(p,supported_protocols[protocol].proto_name))
2838 SSVAL(outbuf,smb_vwv0,choice);
2840 extern fstring remote_proto;
2841 strcpy(remote_proto,supported_protocols[protocol].short_name);
2842 reload_services(True);
2843 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2844 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2847 DEBUG(0,("No protocol supported !\n"));
2849 SSVAL(outbuf,smb_vwv0,choice);
2851 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2857 /****************************************************************************
2858 parse a connect packet
2859 ****************************************************************************/
2860 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2862 char *p = smb_buf(buf) + 1;
2865 DEBUG(4,("parsing connect string %s\n",p));
2867 p2 = strrchr(p,'\\');
2871 strcpy(service,p2+1);
2876 *pwlen = strlen(password);
2883 p = strchr(service,'%');
2892 /****************************************************************************
2893 close all open files for a connection
2894 ****************************************************************************/
2895 static void close_open_files(int cnum)
2898 for (i=0;i<MAX_OPEN_FILES;i++)
2899 if( Files[i].cnum == cnum && Files[i].open) {
2906 /****************************************************************************
2908 ****************************************************************************/
2909 void close_cnum(int cnum, int uid)
2911 extern struct from_host Client_info;
2913 DirCacheFlush(SNUM(cnum));
2917 if (!OPEN_CNUM(cnum))
2919 DEBUG(0,("Can't close cnum %d\n",cnum));
2923 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2925 Client_info.name,Client_info.addr,
2926 lp_servicename(SNUM(cnum))));
2928 yield_connection(cnum,
2929 lp_servicename(SNUM(cnum)),
2930 lp_max_connections(SNUM(cnum)));
2932 if (lp_status(SNUM(cnum)))
2933 yield_connection(cnum,"STATUS.",MAXSTATUS);
2935 close_open_files(cnum);
2936 dptr_closecnum(cnum);
2938 /* execute any "postexec = " line */
2939 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2942 strcpy(cmd,lp_postexec(SNUM(cnum)));
2943 standard_sub(cnum,cmd);
2949 /* execute any "root postexec = " line */
2950 if (*lp_rootpostexec(SNUM(cnum)))
2953 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2954 standard_sub(cnum,cmd);
2958 Connections[cnum].open = False;
2959 num_connections_open--;
2960 if (Connections[cnum].ngroups && Connections[cnum].groups)
2962 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2963 free(Connections[cnum].groups);
2964 free(Connections[cnum].igroups);
2965 Connections[cnum].groups = NULL;
2966 Connections[cnum].igroups = NULL;
2967 Connections[cnum].ngroups = 0;
2970 string_set(&Connections[cnum].user,"");
2971 string_set(&Connections[cnum].dirpath,"");
2972 string_set(&Connections[cnum].connectpath,"");
2976 /****************************************************************************
2977 simple routines to do connection counting
2978 ****************************************************************************/
2979 BOOL yield_connection(int cnum,char *name,int max_connections)
2981 struct connect_record crec;
2984 int mypid = getpid();
2987 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2989 if (max_connections <= 0)
2992 bzero(&crec,sizeof(crec));
2994 strcpy(fname,lp_lockdir());
2995 standard_sub(cnum,fname);
2996 trim_string(fname,"","/");
3000 strcat(fname,".LCK");
3002 f = fopen(fname,"r+");
3005 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3009 fseek(f,0,SEEK_SET);
3011 /* find a free spot */
3012 for (i=0;i<max_connections;i++)
3014 if (fread(&crec,sizeof(crec),1,f) != 1)
3016 DEBUG(2,("Entry not found in lock file %s\n",fname));
3020 if (crec.pid == mypid && crec.cnum == cnum)
3024 if (crec.pid != mypid || crec.cnum != cnum)
3027 DEBUG(2,("Entry not found in lock file %s\n",fname));
3031 bzero((void *)&crec,sizeof(crec));
3033 /* remove our mark */
3034 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3035 fwrite(&crec,sizeof(crec),1,f) != 1)
3037 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3042 DEBUG(3,("Yield successful\n"));
3049 /****************************************************************************
3050 simple routines to do connection counting
3051 ****************************************************************************/
3052 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3054 struct connect_record crec;
3057 int snum = SNUM(cnum);
3061 if (max_connections <= 0)
3064 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3066 strcpy(fname,lp_lockdir());
3067 standard_sub(cnum,fname);
3068 trim_string(fname,"","/");
3070 if (!directory_exist(fname,NULL))
3075 strcat(fname,".LCK");
3077 if (!file_exist(fname,NULL))
3079 f = fopen(fname,"w");
3083 total_recs = file_size(fname) / sizeof(crec);
3085 f = fopen(fname,"r+");
3089 DEBUG(1,("couldn't open lock file %s\n",fname));
3093 /* find a free spot */
3094 for (i=0;i<max_connections;i++)
3097 if (i>=total_recs ||
3098 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3099 fread(&crec,sizeof(crec),1,f) != 1)
3101 if (foundi < 0) foundi = i;
3105 if (Clear && crec.pid && !process_exists(crec.pid))
3107 fseek(f,i*sizeof(crec),SEEK_SET);
3108 bzero((void *)&crec,sizeof(crec));
3109 fwrite(&crec,sizeof(crec),1,f);
3110 if (foundi < 0) foundi = i;
3113 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3122 DEBUG(3,("no free locks in %s\n",fname));
3127 /* fill in the crec */
3128 bzero((void *)&crec,sizeof(crec));
3129 crec.magic = 0x280267;
3130 crec.pid = getpid();
3132 crec.uid = Connections[cnum].uid;
3133 crec.gid = Connections[cnum].gid;
3134 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3135 crec.start = time(NULL);
3138 extern struct from_host Client_info;
3139 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
3140 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
3144 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3145 fwrite(&crec,sizeof(crec),1,f) != 1)
3156 /*******************************************************************
3157 prepare to dump a core file - carefully!
3158 ********************************************************************/
3159 static BOOL dump_core(void)
3163 strcpy(dname,debugf);
3164 if ((p=strrchr(dname,'/'))) *p=0;
3165 strcat(dname,"/corefiles");
3167 sys_chown(dname,getuid(),getgid());
3169 if (chdir(dname)) return(False);
3172 #ifndef NO_GETRLIMIT
3176 getrlimit(RLIMIT_CORE, &rlp);
3177 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3178 setrlimit(RLIMIT_CORE, &rlp);
3179 getrlimit(RLIMIT_CORE, &rlp);
3180 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3186 DEBUG(0,("Dumping core in %s\n",dname));
3191 /****************************************************************************
3193 ****************************************************************************/
3194 void exit_server(char *reason)
3196 static int firsttime=1;
3199 if (!firsttime) exit(0);
3203 DEBUG(2,("Closing connections\n"));
3204 for (i=0;i<MAX_CONNECTIONS;i++)
3205 if (Connections[i].open)
3208 if (dcelogin_atmost_once)
3212 int oldlevel = DEBUGLEVEL;
3214 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3216 show_msg(last_inbuf);
3217 DEBUGLEVEL = oldlevel;
3218 DEBUG(0,("===============================================================\n"));
3220 if (dump_core()) return;
3223 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3227 /****************************************************************************
3228 do some standard substitutions in a string
3229 ****************************************************************************/
3230 void standard_sub(int cnum,char *s)
3232 if (!strchr(s,'%')) return;
3234 if (VALID_CNUM(cnum))
3236 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3237 string_sub(s,"%P",Connections[cnum].connectpath);
3238 string_sub(s,"%u",Connections[cnum].user);
3239 if (strstr(s,"%H")) {
3240 char *home = get_home_dir(Connections[cnum].user);
3241 if (home) string_sub(s,"%H",home);
3243 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3245 standard_sub_basic(s);
3249 These flags determine some of the permissions required to do an operation
3251 Note that I don't set NEED_WRITE on some write operations because they
3252 are used by some brain-dead clients when printing, and I don't want to
3253 force write permissions on print services.
3255 #define AS_USER (1<<0)
3256 #define NEED_WRITE (1<<1)
3257 #define TIME_INIT (1<<2)
3258 #define CAN_IPC (1<<3)
3259 #define AS_GUEST (1<<5)
3263 define a list of possible SMB messages and their corresponding
3264 functions. Any message that has a NULL function is unimplemented -
3265 please feel free to contribute implementations!
3267 struct smb_message_struct
3281 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3282 {SMBtcon,"SMBtcon",reply_tcon,0},
3283 {SMBtdis,"SMBtdis",reply_tdis,0},
3284 {SMBexit,"SMBexit",reply_exit,0},
3285 {SMBioctl,"SMBioctl",reply_ioctl,0},
3286 {SMBecho,"SMBecho",reply_echo,0},
3287 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3288 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3289 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3290 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3291 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3292 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3293 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3294 {SMBopen,"SMBopen",reply_open,AS_USER},
3296 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3297 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3298 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3300 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3301 {SMBread,"SMBread",reply_read,AS_USER},
3302 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3303 {SMBclose,"SMBclose",reply_close,AS_USER},
3304 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3305 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3306 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3307 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3309 /* this is a Pathworks specific call, allowing the
3310 changing of the root path */
3311 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3313 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3314 {SMBflush,"SMBflush",reply_flush,AS_USER},
3315 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3316 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3317 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3318 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3319 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3320 {SMBlock,"SMBlock",reply_lock,AS_USER},
3321 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3323 /* CORE+ PROTOCOL FOLLOWS */
3325 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3326 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3327 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3328 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3329 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3331 /* LANMAN1.0 PROTOCOL FOLLOWS */
3333 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3334 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3335 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3336 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3337 {SMBwritec,"SMBwritec",NULL,AS_USER},
3338 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3339 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3340 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3341 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3342 {SMBioctls,"SMBioctls",NULL,AS_USER},
3343 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3344 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3346 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3347 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3348 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3349 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3351 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3352 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3353 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3355 /* LANMAN2.0 PROTOCOL FOLLOWS */
3356 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3357 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3358 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3359 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3361 /* messaging routines */
3362 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3363 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3364 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3365 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3367 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3369 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3370 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3371 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3372 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3375 /****************************************************************************
3376 return a string containing the function name of a SMB command
3377 ****************************************************************************/
3378 char *smb_fn_name(int type)
3380 static char *unknown_name = "SMBunknown";
3381 static int num_smb_messages =
3382 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3385 for (match=0;match<num_smb_messages;match++)
3386 if (smb_messages[match].code == type)
3389 if (match == num_smb_messages)
3390 return(unknown_name);
3392 return(smb_messages[match].name);
3396 /****************************************************************************
3397 do a switch on the message type, and return the response size
3398 ****************************************************************************/
3399 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3403 static int num_smb_messages =
3404 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3408 struct timeval msg_start_time;
3409 struct timeval msg_end_time;
3410 static unsigned long total_time = 0;
3412 GetTimeOfDay(&msg_start_time);
3419 last_message = type;
3421 /* make sure this is an SMB packet */
3422 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3424 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3428 for (match=0;match<num_smb_messages;match++)
3429 if (smb_messages[match].code == type)
3432 if (match == num_smb_messages)
3434 DEBUG(0,("Unknown message type %d!\n",type));
3435 outsize = reply_unknown(inbuf,outbuf);
3439 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3440 if (smb_messages[match].fn)
3442 int cnum = SVAL(inbuf,smb_tid);
3443 int flags = smb_messages[match].flags;
3444 int uid = SVAL(inbuf,smb_uid);
3446 /* does this protocol need to be run as root? */
3447 if (!(flags & AS_USER))
3450 /* does this protocol need to be run as the connected user? */
3451 if ((flags & AS_USER) && !become_user(cnum,uid))
3452 return(ERROR(ERRSRV,ERRinvnid));
3454 /* does it need write permission? */
3455 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3456 return(ERROR(ERRSRV,ERRaccess));
3458 /* ipc services are limited */
3459 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3460 return(ERROR(ERRSRV,ERRaccess));
3462 /* load service specific parameters */
3463 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3464 return(ERROR(ERRSRV,ERRaccess));
3466 /* does this protocol need to be run as guest? */
3467 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3468 return(ERROR(ERRSRV,ERRaccess));
3472 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3476 outsize = reply_unknown(inbuf,outbuf);
3481 GetTimeOfDay(&msg_end_time);
3482 if (!(smb_messages[match].flags & TIME_INIT))
3484 smb_messages[match].time = 0;
3485 smb_messages[match].flags |= TIME_INIT;
3488 unsigned long this_time =
3489 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3490 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3491 smb_messages[match].time += this_time;
3492 total_time += this_time;
3494 DEBUG(2,("TIME %s %d usecs %g pct\n",
3495 smb_fn_name(type),smb_messages[match].time,
3496 (100.0*smb_messages[match].time) / total_time));
3503 /****************************************************************************
3504 construct a chained reply and add it to the already made reply
3506 inbuf points to the original message start.
3507 inbuf2 points to the smb_wct part of the secondary message
3508 type is the type of the secondary message
3509 outbuf points to the original outbuffer
3510 outbuf2 points to the smb_wct field of the new outbuffer
3511 size is the total length of the incoming message (from inbuf1)
3512 bufsize is the total buffer size
3514 return how many bytes were added to the response
3515 ****************************************************************************/
3516 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3520 static BOOL in_chain = False;
3521 static char *last_outbuf=NULL;
3522 BOOL was_inchain = in_chain;
3523 int insize_remaining;
3524 static int insize_deleted;
3527 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3529 outbuf = last_outbuf;
3535 inbuf2 -= insize_deleted;
3536 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3537 insize_deleted += size - (insize_remaining + smb_wct);
3540 last_outbuf = outbuf;
3543 /* allocate some space for the in and out buffers of the chained message */
3544 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3545 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3549 DEBUG(0,("Out of memory in chain reply\n"));
3550 return(ERROR(ERRSRV,ERRnoresource));
3553 ibuf += SMB_ALIGNMENT;
3554 obuf += SMB_ALIGNMENT;
3556 /* create the in buffer */
3557 memcpy(ibuf,inbuf,smb_wct);
3558 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3559 CVAL(ibuf,smb_com) = type;
3561 /* create the out buffer */
3562 bzero(obuf,smb_size);
3564 set_message(obuf,0,0,True);
3565 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3567 memcpy(obuf+4,ibuf+4,4);
3568 CVAL(obuf,smb_rcls) = SUCCESS;
3569 CVAL(obuf,smb_reh) = 0;
3570 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3572 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3573 SSVAL(obuf,smb_err,SUCCESS);
3574 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3575 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3576 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3577 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3579 DEBUG(3,("Chained message\n"));
3582 /* process the request */
3583 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3584 bufsize-chain_size);
3586 /* copy the new reply header over the old one, but preserve
3587 the smb_com field */
3588 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3590 /* and copy the data from the reply to the right spot */
3591 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3593 /* free the allocated buffers */
3594 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3595 if (obuf) free(obuf-SMB_ALIGNMENT);
3597 in_chain = was_inchain;
3599 /* return how much extra has been added to the packet */
3600 return(outsize - smb_wct);
3605 /****************************************************************************
3606 construct a reply to the incoming packet
3607 ****************************************************************************/
3608 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3610 int type = CVAL(inbuf,smb_com);
3612 int msg_type = CVAL(inbuf,0);
3614 smb_last_time = time(NULL);
3618 bzero(outbuf,smb_size);
3621 return(reply_special(inbuf,outbuf));
3623 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3624 set_message(outbuf,0,0,True);
3626 memcpy(outbuf+4,inbuf+4,4);
3627 CVAL(outbuf,smb_rcls) = SUCCESS;
3628 CVAL(outbuf,smb_reh) = 0;
3629 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3631 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3632 SSVAL(outbuf,smb_err,SUCCESS);
3633 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3634 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3635 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3636 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3638 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3641 smb_setlen(outbuf,outsize - 4);
3646 /****************************************************************************
3647 process commands from the client
3648 ****************************************************************************/
3651 static int trans_num = 0;
3653 extern struct from_host Client_info;
3656 fromhost(Client,&Client_info);
3658 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3659 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3660 if ((InBuffer == NULL) || (OutBuffer == NULL))
3663 InBuffer += SMB_ALIGNMENT;
3664 OutBuffer += SMB_ALIGNMENT;
3667 DEBUG(3,("priming nmbd\n"));
3670 ip = *interpret_addr2("localhost");
3671 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3673 send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM);
3677 last_user.cnum = -1;
3685 int deadtime = lp_deadtime()*60;
3687 int last_keepalive=0;
3690 deadtime = DEFAULT_SMBD_TIMEOUT;
3692 if (lp_readprediction())
3693 do_read_prediction();
3696 extern pstring share_del_pending;
3697 if (*share_del_pending) {
3699 if (!unlink(share_del_pending))
3700 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3702 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3703 share_del_pending[0] = 0;
3707 if (share_mode_pending) {
3709 check_share_modes();
3710 share_mode_pending=False;
3715 for (counter=SMBD_SELECT_LOOP;
3716 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3717 counter += SMBD_SELECT_LOOP)
3721 BOOL allidle = True;
3722 extern int keepalive;
3724 /* check for socket failure */
3726 DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno)));
3732 /* become root again if waiting */
3735 /* check for smb.conf reload */
3736 if (!(counter%SMBD_RELOAD_CHECK))
3737 reload_services(True);
3739 /* check the share modes every 10 secs */
3740 if (!(counter%SHARE_MODES_CHECK))
3741 check_share_modes();
3743 /* clean the share modes every 5 minutes */
3744 if (!(counter%SHARE_MODES_CLEAN))
3745 clean_share_files();
3747 /* automatic timeout if all connections are closed */
3748 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3749 DEBUG(2,("%s Closing idle connection\n",timestring()));
3753 if (keepalive && (counter-last_keepalive)>keepalive) {
3754 extern int password_client;
3755 if (!send_keepalive(Client)) {
3756 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3759 /* also send a keepalive to the password server if its still
3761 if (password_client != -1)
3762 send_keepalive(password_client);
3763 last_keepalive = counter;
3766 /* check for connection timeouts */
3767 for (i=0;i<MAX_CONNECTIONS;i++)
3768 if (Connections[i].open)
3770 /* close dirptrs on connections that are idle */
3771 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3774 if (Connections[i].num_files_open > 0 ||
3775 (t-Connections[i].lastused)<deadtime)
3779 if (allidle && num_connections_open>0) {
3780 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3785 msg_type = CVAL(InBuffer,0);
3786 msg_flags = CVAL(InBuffer,1);
3787 type = CVAL(InBuffer,smb_com);
3789 len = smb_len(InBuffer);
3791 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3795 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3798 if(trans_num == 1 && VT_Check(InBuffer)) {
3808 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3811 if (CVAL(OutBuffer,0) == 0)
3812 show_msg(OutBuffer);
3814 if (nread != smb_len(OutBuffer) + 4)
3816 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3818 smb_len(OutBuffer)));
3821 send_smb(Client,OutBuffer);
3828 /****************************************************************************
3829 initialise connect, service and file structs
3830 ****************************************************************************/
3831 static void init_structs(void )
3834 get_myname(myhostname,&myip);
3836 for (i=0;i<MAX_CONNECTIONS;i++)
3838 Connections[i].open = False;
3839 Connections[i].num_files_open=0;
3840 Connections[i].lastused=0;
3841 Connections[i].used=False;
3842 string_init(&Connections[i].user,"");
3843 string_init(&Connections[i].dirpath,"");
3844 string_init(&Connections[i].connectpath,"");
3845 string_init(&Connections[i].origpath,"");
3848 for (i=0;i<MAX_OPEN_FILES;i++)
3850 Files[i].open = False;
3851 string_init(&Files[i].name,"");
3857 /****************************************************************************
3858 usage on the program
3859 ****************************************************************************/
3860 void usage(char *pname)
3862 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3864 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3865 printf("Version %s\n",VERSION);
3866 printf("\t-D become a daemon\n");
3867 printf("\t-p port listen on the specified port\n");
3868 printf("\t-d debuglevel set the debuglevel\n");
3869 printf("\t-l log basename. Basename for log/debug files\n");
3870 printf("\t-s services file. Filename of services file\n");
3871 printf("\t-P passive only\n");
3872 printf("\t-a overwrite log file, don't append\n");
3877 /****************************************************************************
3879 ****************************************************************************/
3880 int main(int argc,char *argv[])
3882 extern BOOL append_log;
3883 /* shall I run as a daemon */
3884 BOOL is_daemon = False;
3887 extern char *optarg;
3889 #ifdef NEED_AUTH_PARAMETERS
3890 set_auth_parameters(argc,argv);
3901 strcpy(debugf,SMBLOGFILE);
3903 setup_logging(argv[0],False);
3905 charset_initialise();
3907 /* make absolutely sure we run as root - to handle cases whre people
3908 are crazy enough to have it setuid */
3918 fault_setup(exit_server);
3920 umask(0777 & ~DEF_CREATE_MASK);
3922 initial_uid = geteuid();
3923 initial_gid = getegid();
3925 if (initial_gid != 0 && initial_uid == 0)
3935 initial_uid = geteuid();
3936 initial_gid = getegid();
3939 /* this is for people who can't start the program correctly */
3940 while (argc > 1 && (*argv[1] != '-'))
3946 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3950 strcpy(user_socket_options,optarg);
3953 strcpy(scope,optarg);
3957 extern BOOL passive;
3962 strcpy(servicesf,optarg);
3965 strcpy(debugf,optarg);
3969 extern BOOL append_log;
3970 append_log = !append_log;
3980 DEBUGLEVEL = atoi(optarg);
3983 port = atoi(optarg);
3996 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3997 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4001 #ifndef NO_GETRLIMIT
4002 #ifdef RLIMIT_NOFILE
4005 getrlimit(RLIMIT_NOFILE, &rlp);
4006 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4007 setrlimit(RLIMIT_NOFILE, &rlp);
4008 getrlimit(RLIMIT_NOFILE, &rlp);
4009 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4015 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4016 getuid(),getgid(),geteuid(),getegid()));
4018 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4020 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4026 if (!reload_services(False))
4029 #ifndef NO_SIGNAL_TEST
4030 signal(SIGHUP,SIGNAL_CAST sig_hup);
4033 DEBUG(3,("%s loaded services\n",timestring()));
4035 if (!is_daemon && !is_a_socket(0))
4037 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4043 DEBUG(3,("%s becoming a daemon\n",timestring()));
4047 if (!open_sockets(is_daemon,port))
4050 /* possibly reload the services file. */
4051 reload_services(True);
4053 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4057 if (sys_chroot(lp_rootdir()) == 0)
4058 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4064 exit_server("normal exit");