2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
33 BOOL share_mode_pending = False;
35 /* the last message the was processed */
36 int last_message = -1;
38 /* a useful macro to debug the last message processed */
39 #define LAST_MESSAGE() smb_fn_name(last_message)
42 extern int DEBUGLEVEL;
43 extern int case_default;
44 extern BOOL case_sensitive;
45 extern BOOL case_preserve;
46 extern BOOL use_mangled_map;
47 extern BOOL short_case_preserve;
48 extern BOOL case_mangle;
49 extern time_t smb_last_time;
51 extern pstring user_socket_options;
53 connection_struct Connections[MAX_CONNECTIONS];
54 files_struct Files[MAX_OPEN_FILES];
58 int maxxmit = BUFFER_SIZE;
62 /* a fnum to use when chaining */
65 /* number of open connections */
66 static int num_connections_open = 0;
68 extern fstring remote_machine;
71 /* these can be set by some functions to override the error codes */
72 int unix_ERR_class=SUCCESS;
76 extern int extra_time_offset;
78 extern pstring myhostname;
80 static int find_free_connection(int hash);
82 /* for readability... */
83 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
84 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
85 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
86 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
87 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
91 /****************************************************************************
92 change a dos mode to a unix mode
93 base permission for files:
94 everybody gets read bit set
95 dos readonly is represented in unix by removing everyone's write bit
96 dos archive is represented in unix by the user's execute bit
97 dos system is represented in unix by the group's execute bit
98 dos hidden is represented in unix by the other's execute bit
99 base permission for directories:
100 dos directory is represented in unix by unix's dir bit and the exec bit
101 ****************************************************************************/
102 mode_t unix_mode(int cnum,int dosmode)
104 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
106 if ( !IS_DOS_READONLY(dosmode) )
107 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
109 if (IS_DOS_DIR(dosmode))
110 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
112 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
115 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
118 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
121 result &= CREATE_MODE(cnum);
126 /****************************************************************************
127 change a unix mode to a dos mode
128 ****************************************************************************/
129 int dos_mode(int cnum,char *path,struct stat *sbuf)
132 extern struct current_user current_user;
134 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
135 if (!((sbuf->st_mode & S_IWOTH) ||
136 Connections[cnum].admin_user ||
137 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
138 ((sbuf->st_mode & S_IWGRP) &&
139 in_group(sbuf->st_gid,current_user.gid,
140 current_user.ngroups,current_user.igroups))))
143 if ((sbuf->st_mode & S_IWUSR) == 0)
147 if ((sbuf->st_mode & S_IXUSR) != 0)
150 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
153 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
156 if (S_ISDIR(sbuf->st_mode))
157 result = aDIR | (result & aRONLY);
160 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
164 /* hide files with a name starting with a . */
165 if (lp_hide_dot_files(SNUM(cnum)))
167 char *p = strrchr(path,'/');
173 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
181 /*******************************************************************
182 chmod a file - but preserve some bits
183 ********************************************************************/
184 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
193 if (sys_stat(fname,st)) return(-1);
196 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
198 if (dos_mode(cnum,fname,st) == dosmode) return(0);
200 unixmode = unix_mode(cnum,dosmode);
202 /* preserve the s bits */
203 mask |= (S_ISUID | S_ISGID);
205 /* preserve the t bit */
210 /* possibly preserve the x bits */
211 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
212 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
213 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
215 unixmode |= (st->st_mode & mask);
217 /* if we previously had any r bits set then leave them alone */
218 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
219 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
223 /* if we previously had any w bits set then leave them alone
224 if the new mode is not rdonly */
225 if (!IS_DOS_READONLY(dosmode) &&
226 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
227 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
231 return(chmod(fname,unixmode));
235 /****************************************************************************
236 check if two filenames are equal
238 this needs to be careful about whether we are case sensitive
239 ****************************************************************************/
240 static BOOL fname_equal(char *name1, char *name2)
242 int l1 = strlen(name1);
243 int l2 = strlen(name2);
245 /* handle filenames ending in a single dot */
246 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
250 ret = fname_equal(name1,name2);
255 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
259 ret = fname_equal(name1,name2);
264 /* now normal filename handling */
266 return(strcmp(name1,name2) == 0);
268 return(strequal(name1,name2));
272 /****************************************************************************
273 mangle the 2nd name and check if it is then equal to the first name
274 ****************************************************************************/
275 static BOOL mangled_equal(char *name1, char *name2)
282 strcpy(tmpname,name2);
283 mangle_name_83(tmpname);
285 return(strequal(name1,tmpname));
289 /****************************************************************************
290 scan a directory to find a filename, matching without case sensitivity
292 If the name looks like a mangled name then try via the mangling functions
293 ****************************************************************************/
294 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
301 mangled = is_mangled(name);
303 /* handle null paths */
307 if (docache && (dname = DirCacheCheck(path,name,snum))) {
313 check_mangled_stack(name);
315 /* open the directory */
316 if (!(cur_dir = OpenDir(path)))
318 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
322 /* now scan for matching names */
323 while ((dname = ReadDirName(cur_dir)))
326 (strequal(dname,".") || strequal(dname,"..")))
330 if (!name_map_mangle(name2,False,snum)) continue;
332 if ((mangled && mangled_equal(name,name2))
333 || fname_equal(name, name2))
335 /* we've found the file, change it's name and return */
336 if (docache) DirCacheAdd(path,name,dname,snum);
347 /****************************************************************************
348 This routine is called to convert names from the dos namespace to unix
349 namespace. It needs to handle any case conversions, mangling, format
352 We assume that we have already done a chdir() to the right "root" directory
355 The function will return False if some part of the name except for the last
356 part cannot be resolved
357 ****************************************************************************/
358 BOOL unix_convert(char *name,int cnum)
366 /* convert to basic unix format - removing \ chars and cleaning it up */
368 unix_clean_name(name);
370 if (!case_sensitive &&
371 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
374 /* names must be relative to the root of the service - trim any leading /.
375 also trim trailing /'s */
376 trim_string(name,"/","/");
378 /* check if it's a printer file */
379 if (Connections[cnum].printer)
381 if ((! *name) || strchr(name,'/') || !is_8_3(name))
385 sprintf(name2,"%.6s.XXXXXX",remote_machine);
386 /* sanitise the name */
387 for (s=name2 ; *s ; s++)
388 if (!issafe(*s)) *s = '_';
389 strcpy(name,(char *)mktemp(name2));
394 /* stat the name - if it exists then we are all done! */
395 if (sys_stat(name,&st) == 0)
398 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
400 /* a special case - if we don't have any mangling chars and are case
401 sensitive then searching won't help */
402 if (case_sensitive && !is_mangled(name) &&
403 !lp_strip_dot() && !use_mangled_map)
406 /* now we need to recursively match the name against the real
407 directory structure */
410 while (strncmp(start,"./",2) == 0)
413 /* now match each part of the path name separately, trying the names
414 as is first, then trying to scan the directory for matching names */
415 for (;start;start = (end?end+1:(char *)NULL))
417 /* pinpoint the end of this section of the filename */
418 end = strchr(start, '/');
420 /* chop the name at this point */
423 /* check if the name exists up to this point */
424 if (sys_stat(name, &st) == 0)
426 /* it exists. it must either be a directory or this must be
427 the last part of the path for it to be OK */
428 if (end && !(st.st_mode & S_IFDIR))
430 /* an intermediate part of the name isn't a directory */
431 DEBUG(5,("Not a dir %s\n",start));
442 /* remember the rest of the pathname so it can be restored
444 if (end) strcpy(rest,end+1);
447 /* try to find this part of the path in the directory */
448 if (strchr(start,'?') || strchr(start,'*') ||
449 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
453 /* an intermediate part of the name can't be found */
454 DEBUG(5,("Intermediate not found %s\n",start));
459 /* just the last part of the name doesn't exist */
460 /* we may need to strupper() or strlower() it in case
461 this conversion is being used for file creation
463 /* if the filename is of mixed case then don't normalise it */
464 if (!case_preserve &&
465 (!strhasupper(start) || !strhaslower(start)))
468 /* check on the mangled stack to see if we can recover the
469 base of the filename */
470 if (is_mangled(start))
471 check_mangled_stack(start);
473 DEBUG(5,("New file %s\n",start));
477 /* restore the rest of the string */
480 strcpy(start+strlen(start)+1,rest);
481 end = start + strlen(start);
485 /* add to the dirpath that we have resolved so far */
486 if (*dirpath) strcat(dirpath,"/");
487 strcat(dirpath,start);
489 /* restore the / that we wiped out earlier */
493 /* the name has been resolved */
494 DEBUG(5,("conversion finished %s\n",name));
499 /****************************************************************************
500 normalise for DOS usage
501 ****************************************************************************/
502 static void disk_norm(int *bsize,int *dfree,int *dsize)
504 /* check if the disk is beyond the max disk size */
505 int maxdisksize = lp_maxdisksize();
507 /* convert to blocks - and don't overflow */
508 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
509 if (*dsize > maxdisksize) *dsize = maxdisksize;
510 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
515 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
520 if (*bsize > WORDMAX )
523 if (*dsize > WORDMAX)
525 if (*dfree > WORDMAX)
532 /****************************************************************************
533 return number of 1K blocks available on a path and total number
534 ****************************************************************************/
535 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
537 char *df_command = lp_dfree_command();
551 if (disk_quotas(path, bsize, dfree, dsize))
553 disk_norm(bsize,dfree,dsize);
554 return(((*bsize)/1024)*(*dfree));
559 /* possibly use system() to get the result */
560 if (df_command && *df_command)
566 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
567 sprintf(syscmd,"%s %s",df_command,path);
568 standard_sub_basic(syscmd);
570 ret = smbrun(syscmd,outfile);
571 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
574 FILE *f = fopen(outfile,"r");
580 fscanf(f,"%d %d %d",dsize,dfree,bsize);
584 DEBUG(0,("Can't open %s\n",outfile));
588 disk_norm(bsize,dfree,dsize);
589 return(((*bsize)/1024)*(*dfree));
593 DEBUG(1,("Warning - no statfs function\n"));
597 if (statfs(path,&fs,sizeof(fs),0) != 0)
600 if (statvfs(path, &fs))
603 if (statfs(path,&fs,sizeof(fs)) == -1)
605 if (statfs(path,&fs) == -1)
607 #endif /* USE_STATVFS */
610 DEBUG(3,("dfree call failed code errno=%d\n",errno));
614 return(((*bsize)/1024)*(*dfree));
619 *dfree = fs.fd_req.bfree;
620 *dsize = fs.fd_req.btot;
623 *bsize = fs.f_frsize;
626 /* eg: osf1 has f_fsize = fundamental filesystem block size,
627 f_bsize = optimal transfer block size (MX: 94-04-19) */
632 #endif /* USE_STATVFS */
637 *dfree = fs.f_bavail;
639 *dsize = fs.f_blocks;
642 #if defined(SCO) || defined(ISC) || defined(MIPS)
646 /* handle rediculous bsize values - some OSes are broken */
647 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
649 disk_norm(bsize,dfree,dsize);
655 DEBUG(0,("dfree seems to be broken on your system\n"));
656 *dsize = 20*1024*1024/(*bsize);
657 *dfree = MAX(1,*dfree);
659 return(((*bsize)/1024)*(*dfree));
664 /****************************************************************************
665 wrap it to get filenames right
666 ****************************************************************************/
667 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
669 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
674 /****************************************************************************
675 check a filename - possibly caling reducename
677 This is called by every routine before it allows an operation on a filename.
678 It does any final confirmation necessary to ensure that the filename is
679 a valid one for the user to access.
680 ****************************************************************************/
681 BOOL check_name(char *name,int cnum)
687 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
689 DEBUG(5,("check_name on %s failed\n",name));
694 /****************************************************************************
695 check a filename - possibly caling reducename
696 ****************************************************************************/
697 static void check_for_pipe(char *fname)
699 /* special case of pipe opens */
703 if (strstr(s,"pipe/"))
705 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
706 unix_ERR_class = ERRSRV;
707 unix_ERR_code = ERRaccess;
712 /****************************************************************************
714 ****************************************************************************/
715 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
719 Files[fnum].open = False;
723 strcpy(fname,fname1);
725 /* check permissions */
726 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
728 DEBUG(3,("Permission denied opening %s\n",fname));
729 check_for_pipe(fname);
733 /* this handles a bug in Win95 - it doesn't say to create the file when it
735 if (Connections[cnum].printer)
739 if (flags == O_WRONLY)
740 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
744 /* XXXX - is this OK?? */
745 /* this works around a utime bug but can cause other problems */
746 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
751 Files[fnum].fd = sys_open(fname,flags,mode);
753 if ((Files[fnum].fd>=0) &&
754 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
759 p = strrchr(dname,'/');
761 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
762 lp_minprintspace(SNUM(cnum))) {
763 close(Files[fnum].fd);
772 /* Fix for files ending in '.' */
773 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
774 (strchr(fname,'.')==NULL))
777 Files[fnum].fd = sys_open(fname,flags,mode);
780 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
781 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
784 char *p = strrchr(fname, '/');
786 if (p == fname) /* name is "/xxx" */
788 max_len = pathconf("/", _PC_NAME_MAX);
791 else if ((p == NULL) || (p == fname))
794 max_len = pathconf(".", _PC_NAME_MAX);
799 max_len = pathconf(fname, _PC_NAME_MAX);
803 if (strlen(p) > max_len)
805 char tmp = p[max_len];
808 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
814 if (Files[fnum].fd < 0)
816 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
817 fname,strerror(errno),flags));
818 check_for_pipe(fname);
822 if (Files[fnum].fd >= 0)
825 Connections[cnum].num_files_open++;
826 fstat(Files[fnum].fd,&st);
827 Files[fnum].mode = st.st_mode;
828 Files[fnum].open_time = time(NULL);
829 Files[fnum].size = 0;
830 Files[fnum].pos = -1;
831 Files[fnum].open = True;
832 Files[fnum].mmap_ptr = NULL;
833 Files[fnum].mmap_size = 0;
834 Files[fnum].can_lock = True;
835 Files[fnum].can_read = ((flags & O_WRONLY)==0);
836 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
837 Files[fnum].share_mode = 0;
838 Files[fnum].share_pending = False;
839 Files[fnum].print_file = Connections[cnum].printer;
840 Files[fnum].modified = False;
841 Files[fnum].cnum = cnum;
842 string_set(&Files[fnum].name,fname);
843 Files[fnum].wbmpx_ptr = NULL;
846 * If the printer is marked as postscript output a leading
847 * file identifier to ensure the file is treated as a raw
849 * This has a similar effect as CtrlD=0 in WIN.INI file.
850 * tim@fsg.com 09/06/94
852 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
853 Files[fnum].can_write)
855 DEBUG(3,("Writing postscript line\n"));
856 write_file(fnum,"%!\n",3);
859 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
860 timestring(),Connections[cnum].user,fname,
861 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
862 Connections[cnum].num_files_open,fnum));
867 /* mmap it if read-only */
868 if (!Files[fnum].can_write)
870 Files[fnum].mmap_size = file_size(fname);
871 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
872 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
874 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
876 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
877 Files[fnum].mmap_ptr = NULL;
883 /*******************************************************************
885 ********************************************************************/
886 void sync_file(int fnum)
889 fsync(Files[fnum].fd);
893 /****************************************************************************
894 run a file if it is a magic script
895 ****************************************************************************/
896 static void check_magic(int fnum,int cnum)
898 if (!*lp_magicscript(SNUM(cnum)))
901 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
905 if (!(p = strrchr(Files[fnum].name,'/')))
906 p = Files[fnum].name;
910 if (!strequal(lp_magicscript(SNUM(cnum)),p))
916 pstring magic_output;
918 strcpy(fname,Files[fnum].name);
920 if (*lp_magicoutput(SNUM(cnum)))
921 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
923 sprintf(magic_output,"%s.out",fname);
926 ret = smbrun(fname,magic_output);
927 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
933 /****************************************************************************
934 close a file - possibly invalidating the read prediction
935 ****************************************************************************/
936 void close_file(int fnum)
938 int cnum = Files[fnum].cnum;
939 invalidate_read_prediction(Files[fnum].fd);
940 Files[fnum].open = False;
941 Connections[cnum].num_files_open--;
942 if(Files[fnum].wbmpx_ptr)
944 free((char *)Files[fnum].wbmpx_ptr);
945 Files[fnum].wbmpx_ptr = NULL;
949 if(Files[fnum].mmap_ptr)
951 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
952 Files[fnum].mmap_ptr = NULL;
956 if (lp_share_modes(SNUM(cnum)))
957 del_share_mode(fnum);
959 close(Files[fnum].fd);
961 /* NT uses smbclose to start a print - weird */
962 if (Files[fnum].print_file)
965 /* check for magic scripts */
966 check_magic(fnum,cnum);
968 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
969 timestring(),Connections[cnum].user,Files[fnum].name,
970 Connections[cnum].num_files_open));
973 enum {AFAIL,AREAD,AWRITE,AALL};
975 /*******************************************************************
976 reproduce the share mode access table
977 ********************************************************************/
978 static int access_table(int new_deny,int old_deny,int old_mode,
979 int share_pid,char *fname)
981 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
983 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
984 if (old_deny == new_deny && share_pid == getpid())
987 if (old_mode == 0) return(AREAD);
989 /* the new smbpub.zip spec says that if the file extension is
990 .com, .dll, .exe or .sym then allow the open. I will force
991 it to read-only as this seems sensible although the spec is
992 a little unclear on this. */
993 if ((fname = strrchr(fname,'.'))) {
994 if (strequal(fname,".com") ||
995 strequal(fname,".dll") ||
996 strequal(fname,".exe") ||
997 strequal(fname,".sym"))
1007 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1008 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1009 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1012 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1013 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1014 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1017 if (old_deny==DENY_WRITE) return(AREAD);
1018 if (old_deny==DENY_READ) return(AWRITE);
1019 if (old_deny==DENY_NONE) return(AALL);
1025 /*******************************************************************
1026 check if the share mode on a file allows it to be deleted or unlinked
1027 return True if sharing doesn't prevent the operation
1028 ********************************************************************/
1029 BOOL check_file_sharing(int cnum,char *fname)
1032 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1034 if (!pid || !share_mode) return(True);
1036 if (share_mode == DENY_DOS)
1037 return(pid == getpid());
1039 /* XXXX exactly what share mode combinations should be allowed for
1040 deleting/renaming? */
1044 /****************************************************************************
1046 Helper for open_file_shared.
1047 Truncate a file after checking locking; close file if locked.
1048 **************************************************************************/
1049 static void truncate_unless_locked(int fnum, int cnum)
1051 if (Files[fnum].can_write){
1052 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1055 unix_ERR_class = ERRDOS;
1056 unix_ERR_code = ERRlock;
1059 ftruncate(Files[fnum].fd,0);
1064 /****************************************************************************
1065 open a file with a share mode
1066 ****************************************************************************/
1067 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1068 int mode,int *Access,int *action)
1072 int deny_mode = (share_mode>>4)&7;
1074 BOOL file_existed = file_exist(fname,&sbuf);
1075 BOOL fcbopen = False;
1078 Files[fnum].open = False;
1079 Files[fnum].fd = -1;
1081 /* this is for OS/2 EAs - try and say we don't support them */
1082 if (strstr(fname,".+,;=[].")) {
1083 unix_ERR_class = ERRDOS;
1084 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1088 if ((ofun & 0x3) == 0 && file_existed) {
1095 if ((ofun & 0x3) == 2)
1098 /* note that we ignore the append flag as
1099 append does not mean the same thing under dos and unix */
1101 switch (share_mode&0xF)
1118 if (flags != O_RDONLY && file_existed &&
1119 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1127 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1128 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1133 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1135 if (lp_share_modes(SNUM(cnum))) {
1139 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1142 /* someone else has a share lock on it, check to see
1144 int old_open_mode = old_share&0xF;
1145 int old_deny_mode = (old_share>>4)&7;
1147 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1148 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1149 deny_mode,old_deny_mode,old_open_mode,fname));
1151 unix_ERR_class = ERRDOS;
1152 unix_ERR_code = ERRbadshare;
1157 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1160 if ((access_allowed == AFAIL) ||
1161 (access_allowed == AREAD && flags == O_WRONLY) ||
1162 (access_allowed == AWRITE && flags == O_RDONLY)) {
1163 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1164 deny_mode,old_deny_mode,old_open_mode,
1168 unix_ERR_class = ERRDOS;
1169 unix_ERR_code = ERRbadshare;
1173 if (access_allowed == AREAD)
1176 if (access_allowed == AWRITE)
1182 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1183 flags,flags2,mode));
1185 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1186 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1188 open_file(fnum,cnum,fname,flags,mode);
1191 if (Files[fnum].open) {
1205 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1206 Files[fnum].share_pending = True;
1209 (*Access) = open_mode;
1213 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1214 if (!file_existed) *action = 2;
1215 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1219 share_mode_pending = True;
1221 if ((flags2&O_TRUNC) && file_existed)
1222 truncate_unless_locked(fnum,cnum);
1228 /*******************************************************************
1229 check for files that we should now set our share modes on
1230 ********************************************************************/
1231 static void check_share_modes(void)
1234 for (i=0;i<MAX_OPEN_FILES;i++)
1235 if(Files[i].open && Files[i].share_pending) {
1236 if (lp_share_modes(SNUM(Files[i].cnum))) {
1238 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1240 set_share_mode(i,Files[i].share_mode);
1241 Files[i].share_pending = False;
1244 Files[i].share_pending = False;
1250 /****************************************************************************
1251 seek a file. Try to avoid the seek if possible
1252 ****************************************************************************/
1253 int seek_file(int fnum,int pos)
1256 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1259 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1260 return(Files[fnum].pos);
1263 /****************************************************************************
1265 ****************************************************************************/
1266 int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
1270 if (!Files[fnum].can_write)
1272 ret = read_predict(Files[fnum].fd,
1280 mincnt = MAX(mincnt-ret,0);
1285 if (Files[fnum].mmap_ptr)
1287 int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1290 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1294 mincnt = MAX(mincnt-num,0);
1303 if (seek_file(fnum,pos) != pos)
1305 DEBUG(3,("Failed to seek to %d\n",pos));
1310 ret += read_with_timeout(Files[fnum].fd,
1321 /****************************************************************************
1323 ****************************************************************************/
1324 int write_file(int fnum,char *data,int n)
1326 if (!Files[fnum].can_write) {
1331 if (!Files[fnum].modified) {
1333 Files[fnum].modified = True;
1334 if (fstat(Files[fnum].fd,&st) == 0) {
1335 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1336 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1337 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1342 return(write_data(Files[fnum].fd,data,n));
1346 /****************************************************************************
1347 load parameters specific to a connection/service
1348 ****************************************************************************/
1349 BOOL become_service(int cnum,BOOL do_chdir)
1351 extern char magic_char;
1352 static int last_cnum = -1;
1355 if (!OPEN_CNUM(cnum))
1361 Connections[cnum].lastused = smb_last_time;
1366 ChDir(Connections[cnum].connectpath) != 0 &&
1367 ChDir(Connections[cnum].origpath) != 0)
1369 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1370 Connections[cnum].connectpath,cnum));
1374 if (cnum == last_cnum)
1379 case_default = lp_defaultcase(snum);
1380 case_preserve = lp_preservecase(snum);
1381 short_case_preserve = lp_shortpreservecase(snum);
1382 case_mangle = lp_casemangle(snum);
1383 case_sensitive = lp_casesensitive(snum);
1384 magic_char = lp_magicchar(snum);
1385 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1390 /****************************************************************************
1391 find a service entry
1392 ****************************************************************************/
1393 int find_service(char *service)
1397 string_sub(service,"\\","/");
1399 iService = lp_servicenumber(service);
1401 /* now handle the special case of a home directory */
1404 char *phome_dir = get_home_dir(service);
1405 DEBUG(3,("checking for home directory %s gave %s\n",service,
1406 phome_dir?phome_dir:"(NULL)"));
1410 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1412 lp_add_home(service,iHomeService,phome_dir);
1413 iService = lp_servicenumber(service);
1418 /* If we still don't have a service, attempt to add it as a printer. */
1421 int iPrinterService;
1423 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1427 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1429 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1431 DEBUG(3,("%s is a valid printer name\n", service));
1432 DEBUG(3,("adding %s as a printer service\n", service));
1433 lp_add_printer(service,iPrinterService);
1434 iService = lp_servicenumber(service);
1436 DEBUG(0,("failed to add %s as a printer service!\n", service));
1439 DEBUG(3,("%s is not a valid printer name\n", service));
1443 /* just possibly it's a default service? */
1446 char *defservice = lp_defaultservice();
1447 if (defservice && *defservice && !strequal(defservice,service)) {
1448 iService = find_service(defservice);
1449 if (iService >= 0) {
1450 string_sub(service,"_","/");
1451 iService = lp_add_service(service,iService);
1457 if (!VALID_SNUM(iService))
1459 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1464 DEBUG(3,("find_service() failed to find service %s\n", service));
1470 /****************************************************************************
1471 create an error packet from a cached error.
1472 ****************************************************************************/
1473 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1475 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1477 int32 eclass = wbmpx->wr_errclass;
1478 int32 err = wbmpx->wr_error;
1480 /* We can now delete the auxiliary struct */
1481 free((char *)wbmpx);
1482 Files[fnum].wbmpx_ptr = NULL;
1483 return error_packet(inbuf,outbuf,eclass,err,line);
1492 } unix_smb_errmap[] =
1494 {EPERM,ERRDOS,ERRnoaccess},
1495 {EACCES,ERRDOS,ERRnoaccess},
1496 {ENOENT,ERRDOS,ERRbadfile},
1497 {EIO,ERRHRD,ERRgeneral},
1498 {EBADF,ERRSRV,ERRsrverror},
1499 {EINVAL,ERRSRV,ERRsrverror},
1500 {EEXIST,ERRDOS,ERRfilexists},
1501 {ENFILE,ERRDOS,ERRnofids},
1502 {EMFILE,ERRDOS,ERRnofids},
1503 {ENOSPC,ERRHRD,ERRdiskfull},
1505 {EDQUOT,ERRHRD,ERRdiskfull},
1508 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1511 {EXDEV,ERRDOS,ERRdiffdevice},
1513 {EROFS,ERRHRD,ERRnowrite},
1518 /****************************************************************************
1519 create an error packet from errno
1520 ****************************************************************************/
1521 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1523 int eclass=def_class;
1527 if (unix_ERR_class != SUCCESS)
1529 eclass = unix_ERR_class;
1530 ecode = unix_ERR_code;
1531 unix_ERR_class = SUCCESS;
1536 while (unix_smb_errmap[i].smbclass != 0)
1538 if (unix_smb_errmap[i].unixerror == errno)
1540 eclass = unix_smb_errmap[i].smbclass;
1541 ecode = unix_smb_errmap[i].smbcode;
1548 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1552 /****************************************************************************
1553 create an error packet. Normally called using the ERROR() macro
1554 ****************************************************************************/
1555 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1557 int outsize = set_message(outbuf,0,0,True);
1559 cmd = CVAL(inbuf,smb_com);
1561 CVAL(outbuf,smb_rcls) = error_class;
1562 SSVAL(outbuf,smb_err,error_code);
1564 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1567 (int)CVAL(inbuf,smb_com),
1568 smb_fn_name(CVAL(inbuf,smb_com)),
1573 DEBUG(3,("error string = %s\n",strerror(errno)));
1579 #ifndef SIGCLD_IGNORE
1580 /****************************************************************************
1581 this prevents zombie child processes
1582 ****************************************************************************/
1583 static int sig_cld()
1585 static int depth = 0;
1588 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1595 DEBUG(5,("got SIGCLD\n"));
1598 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1602 /* Stevens, Adv. Unix Prog. says that on system V you must call
1603 wait before reinstalling the signal handler, because the kernel
1604 calls the handler from within the signal-call when there is a
1605 child that has exited. This would lead to an infinite recursion
1606 if done vice versa. */
1608 #ifndef DONT_REINSTALL_SIG
1609 #ifdef SIGCLD_IGNORE
1610 signal(SIGCLD, SIG_IGN);
1612 signal(SIGCLD, SIGNAL_CAST sig_cld);
1617 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1620 BlockSignals(False);
1625 /****************************************************************************
1626 this is called when the client exits abruptly
1627 **************************************************************************/
1628 static int sig_pipe()
1630 exit_server("Got sigpipe\n");
1634 /****************************************************************************
1635 open the socket communication
1636 ****************************************************************************/
1637 static BOOL open_sockets(BOOL is_daemon,int port)
1644 struct sockaddr addr;
1645 int in_addrlen = sizeof(addr);
1648 #ifdef SIGCLD_IGNORE
1649 signal(SIGCLD, SIG_IGN);
1651 signal(SIGCLD, SIGNAL_CAST sig_cld);
1654 /* open an incoming socket */
1655 s = open_socket_in(SOCK_STREAM, port, 0);
1659 /* ready to listen */
1660 if (listen(s, 5) == -1)
1662 DEBUG(0,("listen: %s",strerror(errno)));
1667 /* now accept incoming connections - forking a new process
1668 for each incoming connection */
1669 DEBUG(2,("waiting for a connection\n"));
1672 Client = accept(s,&addr,&in_addrlen);
1674 if (Client == -1 && errno == EINTR)
1679 DEBUG(0,("accept: %s",strerror(errno)));
1683 #ifdef NO_FORK_DEBUG
1684 #ifndef NO_SIGNAL_TEST
1685 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1686 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1690 if (Client != -1 && fork()==0)
1692 #ifndef NO_SIGNAL_TEST
1693 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1694 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1696 /* close the listening socket */
1699 /* close our standard file descriptors */
1702 set_socket_options(Client,"SO_KEEPALIVE");
1703 set_socket_options(Client,user_socket_options);
1707 close(Client); /* The parent doesn't need this socket */
1713 /* We will abort gracefully when the client or remote system
1715 #ifndef NO_SIGNAL_TEST
1716 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1720 /* close our standard file descriptors */
1723 set_socket_options(Client,"SO_KEEPALIVE");
1724 set_socket_options(Client,user_socket_options);
1731 /****************************************************************************
1732 check if a snum is in use
1733 ****************************************************************************/
1734 BOOL snum_used(int snum)
1737 for (i=0;i<MAX_CONNECTIONS;i++)
1738 if (OPEN_CNUM(i) && (SNUM(i) == snum))
1743 /****************************************************************************
1744 reload the services file
1745 **************************************************************************/
1746 BOOL reload_services(BOOL test)
1753 strcpy(fname,lp_configfile());
1754 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
1756 strcpy(servicesf,fname);
1763 if (test && !lp_file_list_changed())
1766 lp_killunused(snum_used);
1768 ret = lp_load(servicesf,False);
1770 /* perhaps the config filename is now set */
1772 reload_services(True);
1781 set_socket_options(Client,"SO_KEEPALIVE");
1782 set_socket_options(Client,user_socket_options);
1786 create_mangled_stack(lp_mangledstack());
1788 /* this forces service parameters to be flushed */
1789 become_service(-1,True);
1796 /****************************************************************************
1797 this prevents zombie child processes
1798 ****************************************************************************/
1799 static int sig_hup()
1802 DEBUG(0,("Got SIGHUP\n"));
1803 reload_services(False);
1804 #ifndef DONT_REINSTALL_SIG
1805 signal(SIGHUP,SIGNAL_CAST sig_hup);
1807 BlockSignals(False);
1811 /****************************************************************************
1812 Setup the groups a user belongs to.
1813 ****************************************************************************/
1814 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
1815 int **p_igroups, gid_t **p_groups)
1817 if (-1 == initgroups(user,gid))
1821 DEBUG(0,("Unable to initgroups!\n"));
1822 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
1823 DEBUG(0,("This is probably a problem with the account %s\n",user));
1831 ngroups = getgroups(0,&grp);
1834 igroups = (int *)malloc(sizeof(int)*ngroups);
1835 for (i=0;i<ngroups;i++)
1836 igroups[i] = 0x42424242;
1837 ngroups = getgroups(ngroups,(gid_t *)igroups);
1839 if (igroups[0] == 0x42424242)
1842 *p_ngroups = ngroups;
1844 /* The following bit of code is very strange. It is due to the
1845 fact that some OSes use int* and some use gid_t* for
1846 getgroups, and some (like SunOS) use both, one in prototypes,
1847 and one in man pages and the actual code. Thus we detect it
1848 dynamically using some very ugly code */
1851 /* does getgroups return ints or gid_t ?? */
1852 static BOOL groups_use_ints = True;
1854 if (groups_use_ints &&
1856 SVAL(igroups,2) == 0x4242)
1857 groups_use_ints = False;
1859 for (i=0;groups_use_ints && i<ngroups;i++)
1860 if (igroups[i] == 0x42424242)
1861 groups_use_ints = False;
1863 if (groups_use_ints)
1865 *p_igroups = igroups;
1866 *p_groups = (gid_t *)igroups;
1870 gid_t *groups = (gid_t *)igroups;
1871 igroups = (int *)malloc(sizeof(int)*ngroups);
1872 for (i=0;i<ngroups;i++)
1873 igroups[i] = groups[i];
1874 *p_igroups = igroups;
1875 *p_groups = (gid_t *)groups;
1878 DEBUG(3,("%s is in %d groups\n",user,ngroups));
1879 for (i=0;i<ngroups;i++)
1880 DEBUG(3,("%d ",igroups[i]));
1886 /****************************************************************************
1887 make a connection to a service
1888 ****************************************************************************/
1889 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
1893 struct passwd *pass = NULL;
1894 connection_struct *pcon;
1897 static BOOL first_connection = True;
1901 snum = find_service(service);
1904 if (strequal(service,"IPC$"))
1906 DEBUG(3,("%s refusing IPC connection\n",timestring()));
1910 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
1914 if (strequal(service,HOMES_NAME))
1916 if (*user && Get_Pwnam(user,True))
1917 return(make_connection(user,user,password,pwlen,dev,vuid));
1919 if (validated_username(vuid))
1921 strcpy(user,validated_username(vuid));
1922 return(make_connection(user,user,password,pwlen,dev,vuid));
1926 if (!lp_snum_ok(snum) || !check_access(snum)) {
1930 /* you can only connect to the IPC$ service as an ipc device */
1931 if (strequal(service,"IPC$"))
1934 if (*dev == '?' || !*dev)
1936 if (lp_print_ok(snum))
1937 strcpy(dev,"LPT1:");
1942 /* if the request is as a printer and you can't print then refuse */
1944 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
1945 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
1949 /* lowercase the user name */
1952 /* add it as a possible user name */
1953 add_session_user(service);
1955 /* shall we let them in? */
1956 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
1958 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
1962 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
1965 DEBUG(0,("%s couldn't find free connection\n",timestring()));
1969 pcon = &Connections[cnum];
1970 bzero((char *)pcon,sizeof(*pcon));
1972 /* find out some info about the user */
1973 pass = Get_Pwnam(user,True);
1977 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
1981 pcon->read_only = lp_readonly(snum);
1985 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
1986 string_sub(list,"%S",service);
1988 if (user_in_list(user,list))
1989 pcon->read_only = True;
1991 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
1992 string_sub(list,"%S",service);
1994 if (user_in_list(user,list))
1995 pcon->read_only = False;
1998 /* admin user check */
1999 if (user_in_list(user,lp_admin_users(snum)) &&
2002 pcon->admin_user = True;
2003 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2006 pcon->admin_user = False;
2008 pcon->force_user = force;
2009 pcon->uid = pass->pw_uid;
2010 pcon->gid = pass->pw_gid;
2011 pcon->num_files_open = 0;
2012 pcon->lastused = time(NULL);
2013 pcon->service = snum;
2015 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2016 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2017 pcon->dirptr = NULL;
2018 string_set(&pcon->dirpath,"");
2019 string_set(&pcon->user,user);
2022 if (*lp_force_group(snum))
2024 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2027 pcon->gid = gptr->gr_gid;
2028 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2031 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2035 if (*lp_force_user(snum))
2037 struct passwd *pass2;
2039 strcpy(fuser,lp_force_user(snum));
2040 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2043 pcon->uid = pass2->pw_uid;
2044 string_set(&pcon->user,fuser);
2046 pcon->force_user = True;
2047 DEBUG(3,("Forced user %s\n",fuser));
2050 DEBUG(1,("Couldn't find user %s\n",fuser));
2055 strcpy(s,lp_pathname(snum));
2056 standard_sub(cnum,s);
2057 string_set(&pcon->connectpath,s);
2058 DEBUG(3,("Connect path is %s\n",s));
2061 /* groups stuff added by ih */
2063 pcon->groups = NULL;
2067 /* Find all the groups this uid is in and store them. Used by become_user() */
2068 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2070 /* check number of connections */
2071 if (!claim_connection(cnum,
2072 lp_servicename(SNUM(cnum)),
2073 lp_max_connections(SNUM(cnum)),False))
2075 DEBUG(1,("too many connections - rejected\n"));
2079 if (lp_status(SNUM(cnum)))
2080 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2082 first_connection = False;
2087 /* execute any "root preexec = " line */
2088 if (*lp_rootpreexec(SNUM(cnum)))
2091 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2092 standard_sub(cnum,cmd);
2093 DEBUG(5,("cmd=%s\n",cmd));
2097 if (!become_user(cnum,pcon->uid))
2099 DEBUG(0,("Can't become connected user!\n"));
2101 if (!IS_IPC(cnum)) {
2102 yield_connection(cnum,
2103 lp_servicename(SNUM(cnum)),
2104 lp_max_connections(SNUM(cnum)));
2105 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2110 if (ChDir(pcon->connectpath) != 0)
2112 DEBUG(0,("Can't change directory to %s (%s)\n",
2113 pcon->connectpath,strerror(errno)));
2116 if (!IS_IPC(cnum)) {
2117 yield_connection(cnum,
2118 lp_servicename(SNUM(cnum)),
2119 lp_max_connections(SNUM(cnum)));
2120 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2125 string_set(&pcon->origpath,pcon->connectpath);
2127 #if SOFTLINK_OPTIMISATION
2128 /* resolve any soft links early */
2131 strcpy(s,pcon->connectpath);
2133 string_set(&pcon->connectpath,s);
2134 ChDir(pcon->connectpath);
2138 num_connections_open++;
2139 add_session_user(user);
2141 /* execute any "preexec = " line */
2142 if (*lp_preexec(SNUM(cnum)))
2145 strcpy(cmd,lp_preexec(SNUM(cnum)));
2146 standard_sub(cnum,cmd);
2150 /* we've finished with the sensitive stuff */
2154 extern struct from_host Client_info;
2155 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2157 Client_info.name,Client_info.addr,
2158 lp_servicename(SNUM(cnum)),user,
2168 /****************************************************************************
2169 find first available file slot
2170 ****************************************************************************/
2171 int find_free_file(void )
2174 /* we start at 1 here for an obscure reason I can't now remember,
2175 but I think is important :-) */
2176 for (i=1;i<MAX_OPEN_FILES;i++)
2179 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2183 /****************************************************************************
2184 find first available connection slot, starting from a random position.
2185 The randomisation stops problems with the server dieing and clients
2186 thinking the server is still available.
2187 ****************************************************************************/
2188 static int find_free_connection(int hash )
2192 hash = (hash % (MAX_CONNECTIONS-2))+1;
2196 for (i=hash+1;i!=hash;)
2198 if (!Connections[i].open && Connections[i].used == used)
2200 DEBUG(3,("found free connection number %d\n",i));
2204 if (i == MAX_CONNECTIONS)
2214 DEBUG(1,("ERROR! Out of connection structures\n"));
2219 /****************************************************************************
2220 reply for the core protocol
2221 ****************************************************************************/
2222 int reply_corep(char *outbuf)
2224 int outsize = set_message(outbuf,1,0,True);
2226 Protocol = PROTOCOL_CORE;
2232 /****************************************************************************
2233 reply for the coreplus protocol
2234 ****************************************************************************/
2235 int reply_coreplus(char *outbuf)
2237 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2238 int outsize = set_message(outbuf,13,0,True);
2239 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2240 readbraw and writebraw (possibly) */
2241 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2242 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2244 Protocol = PROTOCOL_COREPLUS;
2250 /****************************************************************************
2251 reply for the lanman 1.0 protocol
2252 ****************************************************************************/
2253 int reply_lanman1(char *outbuf)
2255 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2257 BOOL doencrypt = SMBENCRYPT();
2258 time_t t = time(NULL);
2260 if (lp_security()>=SEC_USER) secword |= 1;
2261 if (doencrypt) secword |= 2;
2263 set_message(outbuf,13,doencrypt?8:0,True);
2264 SSVAL(outbuf,smb_vwv1,secword);
2266 /* Create a token value and add it to the outgoing packet. */
2268 generate_next_challenge(smb_buf(outbuf));
2271 Protocol = PROTOCOL_LANMAN1;
2273 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2274 DEBUG(3,("using password server validation\n"));
2276 if (doencrypt) set_challenge(smb_buf(outbuf));
2280 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2281 SSVAL(outbuf,smb_vwv2,maxxmit);
2282 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2283 SSVAL(outbuf,smb_vwv4,1);
2284 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2285 readbraw writebraw (possibly) */
2286 SIVAL(outbuf,smb_vwv6,getpid());
2287 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2289 put_dos_date(outbuf,smb_vwv8,t);
2291 return (smb_len(outbuf)+4);
2295 /****************************************************************************
2296 reply for the lanman 2.0 protocol
2297 ****************************************************************************/
2298 int reply_lanman2(char *outbuf)
2300 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2302 BOOL doencrypt = SMBENCRYPT();
2303 time_t t = time(NULL);
2305 if (lp_security()>=SEC_USER) secword |= 1;
2306 if (doencrypt) secword |= 2;
2308 set_message(outbuf,13,doencrypt?8:0,True);
2309 SSVAL(outbuf,smb_vwv1,secword);
2311 /* Create a token value and add it to the outgoing packet. */
2313 generate_next_challenge(smb_buf(outbuf));
2316 SIVAL(outbuf,smb_vwv6,getpid());
2318 Protocol = PROTOCOL_LANMAN2;
2320 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2321 DEBUG(3,("using password server validation\n"));
2323 if (doencrypt) set_challenge(smb_buf(outbuf));
2327 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2328 SSVAL(outbuf,smb_vwv2,maxxmit);
2329 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2330 SSVAL(outbuf,smb_vwv4,1);
2331 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2332 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2333 put_dos_date(outbuf,smb_vwv8,t);
2335 return (smb_len(outbuf)+4);
2338 /****************************************************************************
2339 reply for the nt protocol
2340 ****************************************************************************/
2341 int reply_nt1(char *outbuf)
2343 int capabilities=0x300; /* has dual names + lock_and_read */
2345 BOOL doencrypt = SMBENCRYPT();
2346 time_t t = time(NULL);
2348 if (lp_security()>=SEC_USER) secword |= 1;
2349 if (doencrypt) secword |= 2;
2351 set_message(outbuf,17,doencrypt?8:0,True);
2352 CVAL(outbuf,smb_vwv1) = secword;
2354 /* Create a token value and add it to the outgoing packet. */
2356 generate_next_challenge(smb_buf(outbuf));
2357 /* Tell the nt machine how long the challenge is. */
2358 SSVALS(outbuf,smb_vwv16+1,8);
2362 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2364 Protocol = PROTOCOL_NT1;
2366 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2367 DEBUG(3,("using password server validation\n"));
2369 if (doencrypt) set_challenge(smb_buf(outbuf));
2373 if (lp_readraw() && lp_writeraw())
2376 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2377 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2378 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2379 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2380 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2381 put_long_date(outbuf+smb_vwv11+1,t);
2382 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2384 return (smb_len(outbuf)+4);
2388 /* these are the protocol lists used for auto architecture detection:
2391 protocol [PC NETWORK PROGRAM 1.0]
2392 protocol [XENIX CORE]
2393 protocol [MICROSOFT NETWORKS 1.03]
2394 protocol [LANMAN1.0]
2395 protocol [Windows for Workgroups 3.1a]
2396 protocol [LM1.2X002]
2397 protocol [LANMAN2.1]
2398 protocol [NT LM 0.12]
2401 protocol [PC NETWORK PROGRAM 1.0]
2402 protocol [XENIX CORE]
2403 protocol [MICROSOFT NETWORKS 1.03]
2404 protocol [LANMAN1.0]
2405 protocol [Windows for Workgroups 3.1a]
2406 protocol [LM1.2X002]
2407 protocol [LANMAN2.1]
2408 protocol [NT LM 0.12]
2411 protocol [PC NETWORK PROGRAM 1.0]
2412 protocol [XENIX CORE]
2413 protocol [LANMAN1.0]
2414 protocol [LM1.2X002]
2415 protocol [LANMAN2.1]
2419 * Modified to recognize the architecture of the remote machine better.
2421 * This appears to be the matrix of which protocol is used by which
2423 Protocol WfWg Win95 WinNT OS/2
2424 PC NETWORK PROGRAM 1.0 1 1 1 1
2426 MICROSOFT NETWORKS 3.0 2 2
2428 MICROSOFT NETWORKS 1.03 3
2431 Windows for Workgroups 3.1a 5 5 5
2436 * tim@fsg.com 09/29/95
2439 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2440 #define ARCH_WIN95 0x2
2441 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2442 #define ARCH_WINNT 0x8
2443 #define ARCH_SAMBA 0x10
2445 #define ARCH_ALL 0x1F
2447 /* List of supported protocols, most desired first */
2451 int (*proto_reply_fn)(char *);
2453 } supported_protocols[] = {
2454 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2455 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2456 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2457 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2458 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2459 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2460 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2461 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2462 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2467 /****************************************************************************
2469 ****************************************************************************/
2470 static int reply_negprot(char *inbuf,char *outbuf)
2472 extern fstring remote_arch;
2473 int outsize = set_message(outbuf,1,0,True);
2478 int bcc = SVAL(smb_buf(inbuf),-2);
2479 int arch = ARCH_ALL;
2481 p = smb_buf(inbuf)+1;
2482 while (p < (smb_buf(inbuf) + bcc))
2485 DEBUG(3,("Requested protocol [%s]\n",p));
2486 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2487 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2488 else if (strcsequal(p,"DOS LM1.2X002"))
2489 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2490 else if (strcsequal(p,"DOS LANMAN2.1"))
2491 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2492 else if (strcsequal(p,"NT LM 0.12"))
2493 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2494 else if (strcsequal(p,"LANMAN2.1"))
2495 arch &= ( ARCH_WINNT | ARCH_OS2 );
2496 else if (strcsequal(p,"LM1.2X002"))
2497 arch &= ( ARCH_WINNT | ARCH_OS2 );
2498 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2500 else if (strcsequal(p,"XENIX CORE"))
2501 arch &= ( ARCH_WINNT | ARCH_OS2 );
2502 else if (strcsequal(p,"Samba")) {
2512 strcpy(remote_arch,"Samba");
2515 strcpy(remote_arch,"WfWg");
2518 strcpy(remote_arch,"Win95");
2521 strcpy(remote_arch,"WinNT");
2524 strcpy(remote_arch,"OS2");
2527 strcpy(remote_arch,"UNKNOWN");
2531 /* possibly reload - change of architecture */
2532 reload_services(True);
2534 /* a special case to stop password server loops */
2535 if (Index == 1 && strequal(remote_machine,myhostname) &&
2536 lp_security()==SEC_SERVER)
2537 exit_server("Password server loop!");
2539 /* Check for protocols, most desirable first */
2540 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2542 p = smb_buf(inbuf)+1;
2544 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2545 while (p < (smb_buf(inbuf) + bcc))
2547 if (strequal(p,supported_protocols[protocol].proto_name))
2556 SSVAL(outbuf,smb_vwv0,choice);
2558 extern fstring remote_proto;
2559 strcpy(remote_proto,supported_protocols[protocol].short_name);
2560 reload_services(True);
2561 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2562 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2565 DEBUG(0,("No protocol supported !\n"));
2567 SSVAL(outbuf,smb_vwv0,choice);
2569 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2575 /****************************************************************************
2576 parse a connect packet
2577 ****************************************************************************/
2578 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2580 char *p = smb_buf(buf) + 1;
2583 DEBUG(4,("parsing connect string %s\n",p));
2585 p2 = strrchr(p,'\\');
2589 strcpy(service,p2+1);
2594 *pwlen = strlen(password);
2601 p = strchr(service,'%');
2610 /****************************************************************************
2611 close all open files for a connection
2612 ****************************************************************************/
2613 static void close_open_files(int cnum)
2616 for (i=0;i<MAX_OPEN_FILES;i++)
2617 if( Files[i].cnum == cnum && Files[i].open) {
2624 /****************************************************************************
2626 ****************************************************************************/
2627 void close_cnum(int cnum, int uid)
2629 extern struct from_host Client_info;
2631 DirCacheFlush(SNUM(cnum));
2635 if (!OPEN_CNUM(cnum))
2637 DEBUG(0,("Can't close cnum %d\n",cnum));
2641 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2643 Client_info.name,Client_info.addr,
2644 lp_servicename(SNUM(cnum))));
2646 yield_connection(cnum,
2647 lp_servicename(SNUM(cnum)),
2648 lp_max_connections(SNUM(cnum)));
2650 if (lp_status(SNUM(cnum)))
2651 yield_connection(cnum,"STATUS.",MAXSTATUS);
2653 close_open_files(cnum);
2654 dptr_closecnum(cnum);
2656 /* execute any "postexec = " line */
2657 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2660 strcpy(cmd,lp_postexec(SNUM(cnum)));
2661 standard_sub(cnum,cmd);
2667 /* execute any "root postexec = " line */
2668 if (*lp_rootpostexec(SNUM(cnum)))
2671 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2672 standard_sub(cnum,cmd);
2676 Connections[cnum].open = False;
2677 num_connections_open--;
2678 if (Connections[cnum].ngroups && Connections[cnum].groups)
2680 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2681 free(Connections[cnum].groups);
2682 free(Connections[cnum].igroups);
2683 Connections[cnum].groups = NULL;
2684 Connections[cnum].igroups = NULL;
2685 Connections[cnum].ngroups = 0;
2688 string_set(&Connections[cnum].user,"");
2689 string_set(&Connections[cnum].dirpath,"");
2690 string_set(&Connections[cnum].connectpath,"");
2694 /****************************************************************************
2695 simple routines to do connection counting
2696 ****************************************************************************/
2697 BOOL yield_connection(int cnum,char *name,int max_connections)
2699 struct connect_record crec;
2702 int mypid = getpid();
2705 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2707 if (max_connections <= 0)
2710 bzero(&crec,sizeof(crec));
2712 strcpy(fname,lp_lockdir());
2713 standard_sub(cnum,fname);
2714 trim_string(fname,"","/");
2718 strcat(fname,".LCK");
2720 f = fopen(fname,"r+");
2723 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2727 fseek(f,0,SEEK_SET);
2729 /* find a free spot */
2730 for (i=0;i<max_connections;i++)
2732 if (fread(&crec,sizeof(crec),1,f) != 1)
2734 DEBUG(2,("Entry not found in lock file %s\n",fname));
2738 if (crec.pid == mypid && crec.cnum == cnum)
2742 if (crec.pid != mypid || crec.cnum != cnum)
2745 DEBUG(2,("Entry not found in lock file %s\n",fname));
2749 bzero((void *)&crec,sizeof(crec));
2751 /* remove our mark */
2752 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2753 fwrite(&crec,sizeof(crec),1,f) != 1)
2755 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
2760 DEBUG(3,("Yield successful\n"));
2767 /****************************************************************************
2768 simple routines to do connection counting
2769 ****************************************************************************/
2770 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
2772 struct connect_record crec;
2775 int snum = SNUM(cnum);
2779 if (max_connections <= 0)
2782 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
2784 strcpy(fname,lp_lockdir());
2785 standard_sub(cnum,fname);
2786 trim_string(fname,"","/");
2788 if (!directory_exist(fname,NULL))
2793 strcat(fname,".LCK");
2795 if (!file_exist(fname,NULL))
2797 f = fopen(fname,"w");
2801 total_recs = file_size(fname) / sizeof(crec);
2803 f = fopen(fname,"r+");
2807 DEBUG(1,("couldn't open lock file %s\n",fname));
2811 /* find a free spot */
2812 for (i=0;i<max_connections;i++)
2815 if (i>=total_recs ||
2816 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2817 fread(&crec,sizeof(crec),1,f) != 1)
2819 if (foundi < 0) foundi = i;
2823 if (Clear && crec.pid && !process_exists(crec.pid))
2825 fseek(f,i*sizeof(crec),SEEK_SET);
2826 bzero((void *)&crec,sizeof(crec));
2827 fwrite(&crec,sizeof(crec),1,f);
2828 if (foundi < 0) foundi = i;
2831 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2840 DEBUG(3,("no free locks in %s\n",fname));
2845 /* fill in the crec */
2846 bzero((void *)&crec,sizeof(crec));
2847 crec.magic = 0x280267;
2848 crec.pid = getpid();
2850 crec.uid = Connections[cnum].uid;
2851 crec.gid = Connections[cnum].gid;
2852 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2853 crec.start = time(NULL);
2856 extern struct from_host Client_info;
2857 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2858 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2862 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2863 fwrite(&crec,sizeof(crec),1,f) != 1)
2874 /*******************************************************************
2875 prepare to dump a core file - carefully!
2876 ********************************************************************/
2877 static BOOL dump_core(void)
2881 strcpy(dname,debugf);
2882 if ((p=strrchr(dname,'/'))) *p=0;
2883 strcat(dname,"/corefiles");
2885 sys_chown(dname,getuid(),getgid());
2887 if (chdir(dname)) return(False);
2890 #ifndef NO_GETRLIMIT
2894 getrlimit(RLIMIT_CORE, &rlp);
2895 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2896 setrlimit(RLIMIT_CORE, &rlp);
2897 getrlimit(RLIMIT_CORE, &rlp);
2898 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2904 DEBUG(0,("Dumping core in %s\n",dname));
2909 /****************************************************************************
2911 ****************************************************************************/
2912 void exit_server(char *reason)
2914 static int firsttime=1;
2917 if (!firsttime) exit(0);
2921 DEBUG(2,("Closing connections\n"));
2922 for (i=0;i<MAX_CONNECTIONS;i++)
2923 if (Connections[i].open)
2926 if (dcelogin_atmost_once)
2930 int oldlevel = DEBUGLEVEL;
2932 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2934 show_msg(last_inbuf);
2935 DEBUGLEVEL = oldlevel;
2936 DEBUG(0,("===============================================================\n"));
2938 if (dump_core()) return;
2941 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
2945 /****************************************************************************
2946 do some standard substitutions in a string
2947 ****************************************************************************/
2948 void standard_sub(int cnum,char *s)
2950 if (!strchr(s,'%')) return;
2952 if (VALID_CNUM(cnum))
2954 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2955 string_sub(s,"%P",Connections[cnum].connectpath);
2956 string_sub(s,"%u",Connections[cnum].user);
2957 if (strstr(s,"%H")) {
2958 char *home = get_home_dir(Connections[cnum].user);
2959 if (home) string_sub(s,"%H",home);
2961 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2963 standard_sub_basic(s);
2967 These flags determine some of the permissions required to do an operation
2969 Note that I don't set NEED_WRITE on some write operations because they
2970 are used by some brain-dead clients when printing, and I don't want to
2971 force write permissions on print services.
2973 #define AS_USER (1<<0)
2974 #define NEED_WRITE (1<<1)
2975 #define TIME_INIT (1<<2)
2976 #define CAN_IPC (1<<3)
2977 #define AS_GUEST (1<<5)
2981 define a list of possible SMB messages and their corresponding
2982 functions. Any message that has a NULL function is unimplemented -
2983 please feel free to contribute implementations!
2985 struct smb_message_struct
2999 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3000 {SMBtcon,"SMBtcon",reply_tcon,0},
3001 {SMBtdis,"SMBtdis",reply_tdis,0},
3002 {SMBexit,"SMBexit",reply_exit,0},
3003 {SMBioctl,"SMBioctl",reply_ioctl,0},
3004 {SMBecho,"SMBecho",reply_echo,0},
3005 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3006 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3007 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3008 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3009 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3010 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3011 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3012 {SMBopen,"SMBopen",reply_open,AS_USER},
3014 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3015 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3016 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3018 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3019 {SMBread,"SMBread",reply_read,AS_USER},
3020 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3021 {SMBclose,"SMBclose",reply_close,AS_USER},
3022 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3023 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3024 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3025 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3027 /* this is a Pathworks specific call, allowing the
3028 changing of the root path */
3029 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3031 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3032 {SMBflush,"SMBflush",reply_flush,AS_USER},
3033 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3034 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3035 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3036 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3037 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3038 {SMBlock,"SMBlock",reply_lock,AS_USER},
3039 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3041 /* CORE+ PROTOCOL FOLLOWS */
3043 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3044 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3045 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3046 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3047 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3049 /* LANMAN1.0 PROTOCOL FOLLOWS */
3051 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3052 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3053 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3054 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3055 {SMBwritec,"SMBwritec",NULL,AS_USER},
3056 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3057 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3058 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3059 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3060 {SMBioctls,"SMBioctls",NULL,AS_USER},
3061 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3062 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3064 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3065 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3066 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3067 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3069 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3070 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3071 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3073 /* LANMAN2.0 PROTOCOL FOLLOWS */
3074 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3075 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3076 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3077 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3079 /* messaging routines */
3080 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3081 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3082 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3083 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3085 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3087 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3088 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3089 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3090 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3093 /****************************************************************************
3094 return a string containing the function name of a SMB command
3095 ****************************************************************************/
3096 char *smb_fn_name(int type)
3098 static char *unknown_name = "SMBunknown";
3099 static int num_smb_messages =
3100 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3103 for (match=0;match<num_smb_messages;match++)
3104 if (smb_messages[match].code == type)
3107 if (match == num_smb_messages)
3108 return(unknown_name);
3110 return(smb_messages[match].name);
3114 /****************************************************************************
3115 do a switch on the message type, and return the response size
3116 ****************************************************************************/
3117 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3121 static int num_smb_messages =
3122 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3126 struct timeval msg_start_time;
3127 struct timeval msg_end_time;
3128 static unsigned long total_time = 0;
3130 GetTimeOfDay(&msg_start_time);
3137 last_message = type;
3139 /* make sure this is an SMB packet */
3140 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3142 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3146 for (match=0;match<num_smb_messages;match++)
3147 if (smb_messages[match].code == type)
3150 if (match == num_smb_messages)
3152 DEBUG(0,("Unknown message type %d!\n",type));
3153 outsize = reply_unknown(inbuf,outbuf);
3157 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3158 if (smb_messages[match].fn)
3160 int cnum = SVAL(inbuf,smb_tid);
3161 int flags = smb_messages[match].flags;
3162 int uid = SVAL(inbuf,smb_uid);
3164 /* does this protocol need to be run as root? */
3165 if (!(flags & AS_USER))
3168 /* does this protocol need to be run as the connected user? */
3169 if ((flags & AS_USER) && !become_user(cnum,uid))
3170 return(ERROR(ERRSRV,ERRinvnid));
3172 /* does it need write permission? */
3173 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3174 return(ERROR(ERRSRV,ERRaccess));
3176 /* ipc services are limited */
3177 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3178 return(ERROR(ERRSRV,ERRaccess));
3180 /* load service specific parameters */
3181 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3182 return(ERROR(ERRSRV,ERRaccess));
3184 /* does this protocol need to be run as guest? */
3185 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3186 return(ERROR(ERRSRV,ERRaccess));
3190 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3194 outsize = reply_unknown(inbuf,outbuf);
3199 GetTimeOfDay(&msg_end_time);
3200 if (!(smb_messages[match].flags & TIME_INIT))
3202 smb_messages[match].time = 0;
3203 smb_messages[match].flags |= TIME_INIT;
3206 unsigned long this_time =
3207 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3208 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3209 smb_messages[match].time += this_time;
3210 total_time += this_time;
3212 DEBUG(2,("TIME %s %d usecs %g pct\n",
3213 smb_fn_name(type),smb_messages[match].time,
3214 (100.0*smb_messages[match].time) / total_time));
3221 /****************************************************************************
3222 construct a chained reply and add it to the already made reply
3224 inbuf points to the original message start.
3225 inbuf2 points to the smb_wct part of the secondary message
3226 type is the type of the secondary message
3227 outbuf points to the original outbuffer
3228 outbuf2 points to the smb_wct field of the new outbuffer
3229 size is the total length of the incoming message (from inbuf1)
3230 bufsize is the total buffer size
3232 return how many bytes were added to the response
3233 ****************************************************************************/
3234 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3238 static BOOL in_chain = False;
3239 static char *last_outbuf=NULL;
3240 BOOL was_inchain = in_chain;
3241 int insize_remaining;
3242 static int insize_deleted;
3245 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3247 outbuf = last_outbuf;
3253 inbuf2 -= insize_deleted;
3254 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3255 insize_deleted += size - (insize_remaining + smb_wct);
3258 last_outbuf = outbuf;
3261 /* allocate some space for the in and out buffers of the chained message */
3262 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3263 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3267 DEBUG(0,("Out of memory in chain reply\n"));
3268 return(ERROR(ERRSRV,ERRnoresource));
3271 ibuf += SMB_ALIGNMENT;
3272 obuf += SMB_ALIGNMENT;
3274 /* create the in buffer */
3275 memcpy(ibuf,inbuf,smb_wct);
3276 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3277 CVAL(ibuf,smb_com) = type;
3279 /* create the out buffer */
3280 bzero(obuf,smb_size);
3282 set_message(obuf,0,0,True);
3283 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3285 memcpy(obuf+4,ibuf+4,4);
3286 CVAL(obuf,smb_rcls) = SUCCESS;
3287 CVAL(obuf,smb_reh) = 0;
3288 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3290 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3291 SSVAL(obuf,smb_err,SUCCESS);
3292 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3293 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3294 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3295 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3297 DEBUG(3,("Chained message\n"));
3300 /* process the request */
3301 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3302 bufsize-chain_size);
3304 /* copy the new reply header over the old one, but preserve
3305 the smb_com field */
3306 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3308 /* and copy the data from the reply to the right spot */
3309 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3311 /* free the allocated buffers */
3312 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3313 if (obuf) free(obuf-SMB_ALIGNMENT);
3315 in_chain = was_inchain;
3317 /* return how much extra has been added to the packet */
3318 return(outsize - smb_wct);
3323 /****************************************************************************
3324 construct a reply to the incoming packet
3325 ****************************************************************************/
3326 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3328 int type = CVAL(inbuf,smb_com);
3330 int msg_type = CVAL(inbuf,0);
3332 smb_last_time = time(NULL);
3336 bzero(outbuf,smb_size);
3339 return(reply_special(inbuf,outbuf));
3341 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3342 set_message(outbuf,0,0,True);
3344 memcpy(outbuf+4,inbuf+4,4);
3345 CVAL(outbuf,smb_rcls) = SUCCESS;
3346 CVAL(outbuf,smb_reh) = 0;
3347 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3349 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3350 SSVAL(outbuf,smb_err,SUCCESS);
3351 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3352 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3353 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3354 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3356 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3359 smb_setlen(outbuf,outsize - 4);
3364 /****************************************************************************
3365 process commands from the client
3366 ****************************************************************************/
3367 static void process(void)
3369 static int trans_num = 0;
3371 extern struct from_host Client_info;
3374 fromhost(Client,&Client_info);
3376 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3377 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3378 if ((InBuffer == NULL) || (OutBuffer == NULL))
3381 InBuffer += SMB_ALIGNMENT;
3382 OutBuffer += SMB_ALIGNMENT;
3385 DEBUG(3,("priming nmbd\n"));
3388 ip = *interpret_addr2("localhost");
3389 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3391 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3401 int deadtime = lp_deadtime()*60;
3403 int last_keepalive=0;
3406 deadtime = DEFAULT_SMBD_TIMEOUT;
3408 if (lp_readprediction())
3409 do_read_prediction();
3412 extern pstring share_del_pending;
3413 if (*share_del_pending) {
3415 if (!unlink(share_del_pending))
3416 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3418 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3419 share_del_pending[0] = 0;
3423 if (share_mode_pending) {
3425 check_share_modes();
3426 share_mode_pending=False;
3431 for (counter=SMBD_SELECT_LOOP;
3432 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3433 counter += SMBD_SELECT_LOOP)
3437 BOOL allidle = True;
3438 extern int keepalive;
3440 /* check for socket failure */
3442 DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno)));
3448 /* become root again if waiting */
3451 /* check for smb.conf reload */
3452 if (!(counter%SMBD_RELOAD_CHECK))
3453 reload_services(True);
3455 /* check the share modes every 10 secs */
3456 if (!(counter%SHARE_MODES_CHECK))
3457 check_share_modes();
3459 /* clean the share modes every 5 minutes */
3460 if (!(counter%SHARE_MODES_CLEAN))
3461 clean_share_files();
3463 /* automatic timeout if all connections are closed */
3464 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3465 DEBUG(2,("%s Closing idle connection\n",timestring()));
3469 if (keepalive && (counter-last_keepalive)>keepalive) {
3470 extern int password_client;
3471 if (!send_keepalive(Client)) {
3472 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3475 /* also send a keepalive to the password server if its still
3477 if (password_client != -1)
3478 send_keepalive(password_client);
3479 last_keepalive = counter;
3482 /* check for connection timeouts */
3483 for (i=0;i<MAX_CONNECTIONS;i++)
3484 if (Connections[i].open)
3486 /* close dirptrs on connections that are idle */
3487 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3490 if (Connections[i].num_files_open > 0 ||
3491 (t-Connections[i].lastused)<deadtime)
3495 if (allidle && num_connections_open>0) {
3496 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3501 msg_type = CVAL(InBuffer,0);
3502 msg_flags = CVAL(InBuffer,1);
3503 type = CVAL(InBuffer,smb_com);
3505 len = smb_len(InBuffer);
3507 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3511 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3514 if(trans_num == 1 && VT_Check(InBuffer)) {
3524 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3527 if (CVAL(OutBuffer,0) == 0)
3528 show_msg(OutBuffer);
3530 if (nread != smb_len(OutBuffer) + 4)
3532 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3534 smb_len(OutBuffer)));
3537 send_smb(Client,OutBuffer);
3544 /****************************************************************************
3545 initialise connect, service and file structs
3546 ****************************************************************************/
3547 static void init_structs(void )
3550 get_myname(myhostname,NULL);
3552 for (i=0;i<MAX_CONNECTIONS;i++)
3554 Connections[i].open = False;
3555 Connections[i].num_files_open=0;
3556 Connections[i].lastused=0;
3557 Connections[i].used=False;
3558 string_init(&Connections[i].user,"");
3559 string_init(&Connections[i].dirpath,"");
3560 string_init(&Connections[i].connectpath,"");
3561 string_init(&Connections[i].origpath,"");
3564 for (i=0;i<MAX_OPEN_FILES;i++)
3566 Files[i].open = False;
3567 string_init(&Files[i].name,"");
3573 /****************************************************************************
3574 usage on the program
3575 ****************************************************************************/
3576 static void usage(char *pname)
3578 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3580 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3581 printf("Version %s\n",VERSION);
3582 printf("\t-D become a daemon\n");
3583 printf("\t-p port listen on the specified port\n");
3584 printf("\t-d debuglevel set the debuglevel\n");
3585 printf("\t-l log basename. Basename for log/debug files\n");
3586 printf("\t-s services file. Filename of services file\n");
3587 printf("\t-P passive only\n");
3588 printf("\t-a overwrite log file, don't append\n");
3593 /****************************************************************************
3595 ****************************************************************************/
3596 int main(int argc,char *argv[])
3598 extern BOOL append_log;
3599 /* shall I run as a daemon */
3600 BOOL is_daemon = False;
3601 int port = SMB_PORT;
3603 extern char *optarg;
3605 #ifdef NEED_AUTH_PARAMETERS
3606 set_auth_parameters(argc,argv);
3617 strcpy(debugf,SMBLOGFILE);
3619 setup_logging(argv[0],False);
3621 charset_initialise();
3623 /* make absolutely sure we run as root - to handle cases whre people
3624 are crazy enough to have it setuid */
3634 fault_setup(exit_server);
3636 umask(0777 & ~DEF_CREATE_MASK);
3640 /* this is for people who can't start the program correctly */
3641 while (argc > 1 && (*argv[1] != '-'))
3647 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3651 strcpy(user_socket_options,optarg);
3654 strcpy(scope,optarg);
3658 extern BOOL passive;
3663 strcpy(servicesf,optarg);
3666 strcpy(debugf,optarg);
3670 extern BOOL append_log;
3671 append_log = !append_log;
3681 DEBUGLEVEL = atoi(optarg);
3684 port = atoi(optarg);
3697 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3698 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3700 #ifndef NO_GETRLIMIT
3701 #ifdef RLIMIT_NOFILE
3704 getrlimit(RLIMIT_NOFILE, &rlp);
3705 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3706 setrlimit(RLIMIT_NOFILE, &rlp);
3707 getrlimit(RLIMIT_NOFILE, &rlp);
3708 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3714 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3715 getuid(),getgid(),geteuid(),getegid()));
3717 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3719 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3725 if (!reload_services(False))
3728 #ifndef NO_SIGNAL_TEST
3729 signal(SIGHUP,SIGNAL_CAST sig_hup);
3732 DEBUG(3,("%s loaded services\n",timestring()));
3734 if (!is_daemon && !is_a_socket(0))
3736 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3742 DEBUG(3,("%s becoming a daemon\n",timestring()));
3746 if (!open_sockets(is_daemon,port))
3749 /* possibly reload the services file. */
3750 reload_services(True);
3752 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3756 if (sys_chroot(lp_rootdir()) == 0)
3757 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3763 exit_server("normal exit");