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 extern pstring debugf;
30 extern pstring sesssetup_user;
32 char *InBuffer = NULL;
33 char *OutBuffer = NULL;
34 char *last_inbuf = NULL;
36 BOOL share_mode_pending = False;
38 /* the last message the was processed */
39 int last_message = -1;
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
45 extern int DEBUGLEVEL;
46 extern int case_default;
47 extern BOOL case_sensitive;
48 extern BOOL case_preserve;
49 extern BOOL use_mangled_map;
50 extern BOOL short_case_preserve;
51 extern BOOL case_mangle;
52 extern time_t smb_last_time;
54 extern pstring user_socket_options;
56 connection_struct Connections[MAX_CONNECTIONS];
57 files_struct Files[MAX_OPEN_FILES];
61 int maxxmit = BUFFER_SIZE;
65 /* a fnum to use when chaining */
68 /* number of open connections */
69 static int num_connections_open = 0;
71 extern fstring remote_machine;
74 /* these can be set by some functions to override the error codes */
75 int unix_ERR_class=SUCCESS;
79 extern int extra_time_offset;
81 extern pstring myhostname;
82 extern struct in_addr myip;
85 static int find_free_connection(int hash);
88 extern void generate_next_challenge(char *challenge);
89 extern void set_challenge(char *challenge);
92 /* for readability... */
93 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
94 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
95 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
96 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
97 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
101 /****************************************************************************
102 change a dos mode to a unix mode
103 base permission for files:
104 everybody gets read bit set
105 dos readonly is represented in unix by removing everyone's write bit
106 dos archive is represented in unix by the user's execute bit
107 dos system is represented in unix by the group's execute bit
108 dos hidden is represented in unix by the other's execute bit
109 base permission for directories:
110 dos directory is represented in unix by unix's dir bit and the exec bit
111 ****************************************************************************/
112 mode_t unix_mode(int cnum,int dosmode)
114 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
116 if ( !IS_DOS_READONLY(dosmode) )
117 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
119 if (IS_DOS_DIR(dosmode))
120 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
122 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
125 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
128 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
131 result &= CREATE_MODE(cnum);
136 /****************************************************************************
137 change a unix mode to a dos mode
138 ****************************************************************************/
139 int dos_mode(int cnum,char *path,struct stat *sbuf)
142 extern struct current_user current_user;
144 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
145 if (!((sbuf->st_mode & S_IWOTH) ||
146 Connections[cnum].admin_user ||
147 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
148 ((sbuf->st_mode & S_IWGRP) &&
149 in_group(sbuf->st_gid,current_user.gid,
150 current_user.ngroups,current_user.igroups))))
153 if ((sbuf->st_mode & S_IWUSR) == 0)
157 if ((sbuf->st_mode & S_IXUSR) != 0)
160 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
163 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
166 if (S_ISDIR(sbuf->st_mode))
167 result = aDIR | (result & aRONLY);
170 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
174 /* hide files with a name starting with a . */
175 if (lp_hide_dot_files(SNUM(cnum)))
177 char *p = strrchr(path,'/');
183 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
191 /*******************************************************************
192 chmod a file - but preserve some bits
193 ********************************************************************/
194 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
203 if (sys_stat(fname,st)) return(-1);
206 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
208 if (dos_mode(cnum,fname,st) == dosmode) return(0);
210 unixmode = unix_mode(cnum,dosmode);
212 /* preserve the s bits */
213 mask |= (S_ISUID | S_ISGID);
215 /* preserve the t bit */
220 /* possibly preserve the x bits */
221 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
222 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
223 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
225 unixmode |= (st->st_mode & mask);
227 /* if we previously had any r bits set then leave them alone */
228 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
229 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
233 /* if we previously had any w bits set then leave them alone
234 if the new mode is not rdonly */
235 if (!IS_DOS_READONLY(dosmode) &&
236 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
237 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
241 return(chmod(fname,unixmode));
245 /****************************************************************************
246 check if two filenames are equal
248 this needs to be careful about whether we are case sensitive
249 ****************************************************************************/
250 static BOOL fname_equal(char *name1, char *name2)
252 int l1 = strlen(name1);
253 int l2 = strlen(name2);
255 /* handle filenames ending in a single dot */
256 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
260 ret = fname_equal(name1,name2);
265 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
269 ret = fname_equal(name1,name2);
274 /* now normal filename handling */
276 return(strcmp(name1,name2) == 0);
278 return(strequal(name1,name2));
282 /****************************************************************************
283 mangle the 2nd name and check if it is then equal to the first name
284 ****************************************************************************/
285 static BOOL mangled_equal(char *name1, char *name2)
292 strcpy(tmpname,name2);
293 mangle_name_83(tmpname);
295 return(strequal(name1,tmpname));
299 /****************************************************************************
300 scan a directory to find a filename, matching without case sensitivity
302 If the name looks like a mangled name then try via the mangling functions
303 ****************************************************************************/
304 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
311 mangled = is_mangled(name);
313 /* handle null paths */
317 if (docache && (dname = DirCacheCheck(path,name,snum))) {
323 check_mangled_stack(name);
325 /* open the directory */
326 if (!(cur_dir = OpenDir(path)))
328 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
332 /* now scan for matching names */
333 while ((dname = ReadDirName(cur_dir)))
336 (strequal(dname,".") || strequal(dname,"..")))
340 if (!name_map_mangle(name2,False,snum)) continue;
342 if ((mangled && mangled_equal(name,name2))
343 || fname_equal(name, name2))
345 /* we've found the file, change it's name and return */
346 if (docache) DirCacheAdd(path,name,dname,snum);
357 /****************************************************************************
358 This routine is called to convert names from the dos namespace to unix
359 namespace. It needs to handle any case conversions, mangling, format
362 We assume that we have already done a chdir() to the right "root" directory
365 The function will return False if some part of the name except for the last
366 part cannot be resolved
367 ****************************************************************************/
368 BOOL unix_convert(char *name,int cnum)
376 /* convert to basic unix format - removing \ chars and cleaning it up */
378 unix_clean_name(name);
380 if (!case_sensitive &&
381 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
384 /* names must be relative to the root of the service - trim any leading /.
385 also trim trailing /'s */
386 trim_string(name,"/","/");
388 /* check if it's a printer file */
389 if (Connections[cnum].printer)
391 if ((! *name) || strchr(name,'/') || !is_8_3(name))
395 sprintf(name2,"%.6s.XXXXXX",remote_machine);
396 /* sanitise the name */
397 for (s=name2 ; *s ; s++)
398 if (!issafe(*s)) *s = '_';
399 strcpy(name,(char *)mktemp(name2));
404 /* stat the name - if it exists then we are all done! */
405 if (sys_stat(name,&st) == 0)
408 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
410 /* a special case - if we don't have any mangling chars and are case
411 sensitive then searching won't help */
412 if (case_sensitive && !is_mangled(name) &&
413 !lp_strip_dot() && !use_mangled_map)
416 /* now we need to recursively match the name against the real
417 directory structure */
420 while (strncmp(start,"./",2) == 0)
423 /* now match each part of the path name separately, trying the names
424 as is first, then trying to scan the directory for matching names */
425 for (;start;start = (end?end+1:(char *)NULL))
427 /* pinpoint the end of this section of the filename */
428 end = strchr(start, '/');
430 /* chop the name at this point */
433 /* check if the name exists up to this point */
434 if (sys_stat(name, &st) == 0)
436 /* it exists. it must either be a directory or this must be
437 the last part of the path for it to be OK */
438 if (end && !(st.st_mode & S_IFDIR))
440 /* an intermediate part of the name isn't a directory */
441 DEBUG(5,("Not a dir %s\n",start));
452 /* remember the rest of the pathname so it can be restored
454 if (end) strcpy(rest,end+1);
457 /* try to find this part of the path in the directory */
458 if (strchr(start,'?') || strchr(start,'*') ||
459 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
463 /* an intermediate part of the name can't be found */
464 DEBUG(5,("Intermediate not found %s\n",start));
469 /* just the last part of the name doesn't exist */
470 /* we may need to strupper() or strlower() it in case
471 this conversion is being used for file creation
473 /* if the filename is of mixed case then don't normalise it */
474 if (!case_preserve &&
475 (!strhasupper(start) || !strhaslower(start)))
478 /* check on the mangled stack to see if we can recover the
479 base of the filename */
480 if (is_mangled(start))
481 check_mangled_stack(start);
483 DEBUG(5,("New file %s\n",start));
487 /* restore the rest of the string */
490 strcpy(start+strlen(start)+1,rest);
491 end = start + strlen(start);
495 /* add to the dirpath that we have resolved so far */
496 if (*dirpath) strcat(dirpath,"/");
497 strcat(dirpath,start);
499 /* restore the / that we wiped out earlier */
503 /* the name has been resolved */
504 DEBUG(5,("conversion finished %s\n",name));
509 /****************************************************************************
510 normalise for DOS usage
511 ****************************************************************************/
512 static void disk_norm(int *bsize,int *dfree,int *dsize)
514 /* check if the disk is beyond the max disk size */
515 int maxdisksize = lp_maxdisksize();
517 /* convert to blocks - and don't overflow */
518 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
519 if (*dsize > maxdisksize) *dsize = maxdisksize;
520 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
525 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
530 if (*bsize > WORDMAX )
533 if (*dsize > WORDMAX)
535 if (*dfree > WORDMAX)
542 /****************************************************************************
543 return number of 1K blocks available on a path and total number
544 ****************************************************************************/
545 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
547 char *df_command = lp_dfree_command();
561 if (disk_quotas(path, bsize, dfree, dsize))
563 disk_norm(bsize,dfree,dsize);
564 return(((*bsize)/1024)*(*dfree));
569 /* possibly use system() to get the result */
570 if (df_command && *df_command)
576 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
577 sprintf(syscmd,"%s %s",df_command,path);
578 standard_sub_basic(syscmd);
580 ret = smbrun(syscmd,outfile);
581 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
584 FILE *f = fopen(outfile,"r");
590 fscanf(f,"%d %d %d",dsize,dfree,bsize);
594 DEBUG(0,("Can't open %s\n",outfile));
598 disk_norm(bsize,dfree,dsize);
599 return(((*bsize)/1024)*(*dfree));
603 DEBUG(1,("Warning - no statfs function\n"));
607 if (statfs(path,&fs,sizeof(fs),0) != 0)
610 if (statvfs(path, &fs))
613 if (statfs(path,&fs,sizeof(fs)) == -1)
615 if (statfs(path,&fs) == -1)
617 #endif /* USE_STATVFS */
620 DEBUG(3,("dfree call failed code errno=%d\n",errno));
624 return(((*bsize)/1024)*(*dfree));
629 *dfree = fs.fd_req.bfree;
630 *dsize = fs.fd_req.btot;
633 *bsize = fs.f_frsize;
636 /* eg: osf1 has f_fsize = fundamental filesystem block size,
637 f_bsize = optimal transfer block size (MX: 94-04-19) */
642 #endif /* USE_STATVFS */
647 *dfree = fs.f_bavail;
649 *dsize = fs.f_blocks;
652 #if defined(SCO) || defined(ISC) || defined(MIPS)
656 /* handle rediculous bsize values - some OSes are broken */
657 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
659 disk_norm(bsize,dfree,dsize);
665 DEBUG(0,("dfree seems to be broken on your system\n"));
666 *dsize = 20*1024*1024/(*bsize);
667 *dfree = MAX(1,*dfree);
669 return(((*bsize)/1024)*(*dfree));
674 /****************************************************************************
675 wrap it to get filenames right
676 ****************************************************************************/
677 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
679 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
684 /****************************************************************************
685 check a filename - possibly caling reducename
687 This is called by every routine before it allows an operation on a filename.
688 It does any final confirmation necessary to ensure that the filename is
689 a valid one for the user to access.
690 ****************************************************************************/
691 BOOL check_name(char *name,int cnum)
697 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
699 DEBUG(5,("check_name on %s failed\n",name));
704 /****************************************************************************
705 check a filename - possibly caling reducename
706 ****************************************************************************/
707 static void check_for_pipe(char *fname)
709 /* special case of pipe opens */
713 if (strstr(s,"pipe/"))
715 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
716 unix_ERR_class = ERRSRV;
717 unix_ERR_code = ERRaccess;
722 /****************************************************************************
724 ****************************************************************************/
725 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
729 Files[fnum].open = False;
733 strcpy(fname,fname1);
735 /* check permissions */
736 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
738 DEBUG(3,("Permission denied opening %s\n",fname));
739 check_for_pipe(fname);
743 /* this handles a bug in Win95 - it doesn't say to create the file when it
745 if (Connections[cnum].printer)
749 if (flags == O_WRONLY)
750 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
754 /* XXXX - is this OK?? */
755 /* this works around a utime bug but can cause other problems */
756 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
761 Files[fnum].fd = sys_open(fname,flags,mode);
763 if ((Files[fnum].fd>=0) &&
764 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
769 p = strrchr(dname,'/');
771 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
772 lp_minprintspace(SNUM(cnum))) {
773 close(Files[fnum].fd);
782 /* Fix for files ending in '.' */
783 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
784 (strchr(fname,'.')==NULL))
787 Files[fnum].fd = sys_open(fname,flags,mode);
790 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
791 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
794 char *p = strrchr(fname, '/');
796 if (p == fname) /* name is "/xxx" */
798 max_len = pathconf("/", _PC_NAME_MAX);
801 else if ((p == NULL) || (p == fname))
804 max_len = pathconf(".", _PC_NAME_MAX);
809 max_len = pathconf(fname, _PC_NAME_MAX);
813 if (strlen(p) > max_len)
815 char tmp = p[max_len];
818 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
824 if (Files[fnum].fd < 0)
826 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
827 fname,strerror(errno),flags));
828 check_for_pipe(fname);
832 if (Files[fnum].fd >= 0)
835 Connections[cnum].num_files_open++;
836 fstat(Files[fnum].fd,&st);
837 Files[fnum].mode = st.st_mode;
838 Files[fnum].open_time = time(NULL);
839 Files[fnum].size = 0;
840 Files[fnum].pos = -1;
841 Files[fnum].open = True;
842 Files[fnum].mmap_ptr = NULL;
843 Files[fnum].mmap_size = 0;
844 Files[fnum].can_lock = True;
845 Files[fnum].can_read = ((flags & O_WRONLY)==0);
846 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
847 Files[fnum].share_mode = 0;
848 Files[fnum].share_pending = False;
849 Files[fnum].print_file = Connections[cnum].printer;
850 Files[fnum].modified = False;
851 Files[fnum].cnum = cnum;
852 string_set(&Files[fnum].name,fname);
853 Files[fnum].wbmpx_ptr = NULL;
856 * If the printer is marked as postscript output a leading
857 * file identifier to ensure the file is treated as a raw
859 * This has a similar effect as CtrlD=0 in WIN.INI file.
860 * tim@fsg.com 09/06/94
862 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
863 Files[fnum].can_write)
865 DEBUG(3,("Writing postscript line\n"));
866 write_file(fnum,"%!\n",3);
869 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
870 timestring(),Connections[cnum].user,fname,
871 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
872 Connections[cnum].num_files_open,fnum));
877 /* mmap it if read-only */
878 if (!Files[fnum].can_write)
880 Files[fnum].mmap_size = file_size(fname);
881 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
882 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
884 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
886 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
887 Files[fnum].mmap_ptr = NULL;
893 /*******************************************************************
895 ********************************************************************/
896 void sync_file(int fnum)
899 fsync(Files[fnum].fd);
903 /****************************************************************************
904 run a file if it is a magic script
905 ****************************************************************************/
906 static void check_magic(int fnum,int cnum)
908 if (!*lp_magicscript(SNUM(cnum)))
911 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
915 if (!(p = strrchr(Files[fnum].name,'/')))
916 p = Files[fnum].name;
920 if (!strequal(lp_magicscript(SNUM(cnum)),p))
926 pstring magic_output;
928 strcpy(fname,Files[fnum].name);
930 if (*lp_magicoutput(SNUM(cnum)))
931 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
933 sprintf(magic_output,"%s.out",fname);
936 ret = smbrun(fname,magic_output);
937 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
943 /****************************************************************************
944 close a file - possibly invalidating the read prediction
945 ****************************************************************************/
946 void close_file(int fnum)
948 int cnum = Files[fnum].cnum;
949 invalidate_read_prediction(Files[fnum].fd);
950 Files[fnum].open = False;
951 Connections[cnum].num_files_open--;
952 if(Files[fnum].wbmpx_ptr)
954 free((char *)Files[fnum].wbmpx_ptr);
955 Files[fnum].wbmpx_ptr = NULL;
959 if(Files[fnum].mmap_ptr)
961 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
962 Files[fnum].mmap_ptr = NULL;
966 if (lp_share_modes(SNUM(cnum)))
967 del_share_mode(fnum);
969 close(Files[fnum].fd);
971 /* NT uses smbclose to start a print - weird */
972 if (Files[fnum].print_file)
975 /* check for magic scripts */
976 check_magic(fnum,cnum);
978 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
979 timestring(),Connections[cnum].user,Files[fnum].name,
980 Connections[cnum].num_files_open));
983 enum {AFAIL,AREAD,AWRITE,AALL};
985 /*******************************************************************
986 reproduce the share mode access table
987 ********************************************************************/
988 static int access_table(int new_deny,int old_deny,int old_mode,
989 int share_pid,char *fname)
991 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
993 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
994 if (old_deny == new_deny && share_pid == getpid())
997 if (old_mode == 0) return(AREAD);
999 /* the new smbpub.zip spec says that if the file extension is
1000 .com, .dll, .exe or .sym then allow the open. I will force
1001 it to read-only as this seems sensible although the spec is
1002 a little unclear on this. */
1003 if ((fname = strrchr(fname,'.'))) {
1004 if (strequal(fname,".com") ||
1005 strequal(fname,".dll") ||
1006 strequal(fname,".exe") ||
1007 strequal(fname,".sym"))
1017 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1018 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1019 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1022 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1023 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1024 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1027 if (old_deny==DENY_WRITE) return(AREAD);
1028 if (old_deny==DENY_READ) return(AWRITE);
1029 if (old_deny==DENY_NONE) return(AALL);
1035 /*******************************************************************
1036 check if the share mode on a file allows it to be deleted or unlinked
1037 return True if sharing doesn't prevent the operation
1038 ********************************************************************/
1039 BOOL check_file_sharing(int cnum,char *fname)
1042 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1044 if (!pid || !share_mode) return(True);
1046 if (share_mode == DENY_DOS)
1047 return(pid == getpid());
1049 /* XXXX exactly what share mode combinations should be allowed for
1050 deleting/renaming? */
1054 /****************************************************************************
1056 Helper for open_file_shared.
1057 Truncate a file after checking locking; close file if locked.
1058 **************************************************************************/
1059 static void truncate_unless_locked(int fnum, int cnum)
1061 if (Files[fnum].can_write){
1062 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1065 unix_ERR_class = ERRDOS;
1066 unix_ERR_code = ERRlock;
1069 ftruncate(Files[fnum].fd,0);
1074 /****************************************************************************
1075 open a file with a share mode
1076 ****************************************************************************/
1077 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1078 int mode,int *Access,int *action)
1082 int deny_mode = (share_mode>>4)&7;
1084 BOOL file_existed = file_exist(fname,&sbuf);
1085 BOOL fcbopen = False;
1088 Files[fnum].open = False;
1089 Files[fnum].fd = -1;
1091 /* this is for OS/2 EAs - try and say we don't support them */
1092 if (strstr(fname,".+,;=[].")) {
1093 unix_ERR_class = ERRDOS;
1094 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1098 if ((ofun & 0x3) == 0 && file_existed) {
1105 if ((ofun & 0x3) == 2)
1108 /* note that we ignore the append flag as
1109 append does not mean the same thing under dos and unix */
1111 switch (share_mode&0xF)
1128 if (flags != O_RDONLY && file_existed &&
1129 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1137 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1138 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1143 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1145 if (lp_share_modes(SNUM(cnum))) {
1149 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1152 /* someone else has a share lock on it, check to see
1154 int old_open_mode = old_share&0xF;
1155 int old_deny_mode = (old_share>>4)&7;
1157 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1158 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1159 deny_mode,old_deny_mode,old_open_mode,fname));
1161 unix_ERR_class = ERRDOS;
1162 unix_ERR_code = ERRbadshare;
1167 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1170 if ((access_allowed == AFAIL) ||
1171 (access_allowed == AREAD && flags == O_WRONLY) ||
1172 (access_allowed == AWRITE && flags == O_RDONLY)) {
1173 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1174 deny_mode,old_deny_mode,old_open_mode,
1178 unix_ERR_class = ERRDOS;
1179 unix_ERR_code = ERRbadshare;
1183 if (access_allowed == AREAD)
1186 if (access_allowed == AWRITE)
1192 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1193 flags,flags2,mode));
1195 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1196 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1198 open_file(fnum,cnum,fname,flags,mode);
1201 if (Files[fnum].open) {
1215 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1216 Files[fnum].share_pending = True;
1219 (*Access) = open_mode;
1223 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1224 if (!file_existed) *action = 2;
1225 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1229 share_mode_pending = True;
1231 if ((flags2&O_TRUNC) && file_existed)
1232 truncate_unless_locked(fnum,cnum);
1238 /*******************************************************************
1239 check for files that we should now set our share modes on
1240 ********************************************************************/
1241 static void check_share_modes(void)
1244 for (i=0;i<MAX_OPEN_FILES;i++)
1245 if(Files[i].open && Files[i].share_pending) {
1246 if (lp_share_modes(SNUM(Files[i].cnum))) {
1248 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1250 set_share_mode(i,Files[i].share_mode);
1251 Files[i].share_pending = False;
1254 Files[i].share_pending = False;
1260 /****************************************************************************
1261 seek a file. Try to avoid the seek if possible
1262 ****************************************************************************/
1263 int seek_file(int fnum,int pos)
1266 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1269 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1270 return(Files[fnum].pos);
1273 /****************************************************************************
1275 ****************************************************************************/
1276 int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
1280 if (!Files[fnum].can_write)
1282 ret = read_predict(Files[fnum].fd,
1290 mincnt = MAX(mincnt-ret,0);
1295 if (Files[fnum].mmap_ptr)
1297 int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1300 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1304 mincnt = MAX(mincnt-num,0);
1313 if (seek_file(fnum,pos) != pos)
1315 DEBUG(3,("Failed to seek to %d\n",pos));
1320 ret += read_with_timeout(Files[fnum].fd,
1331 /****************************************************************************
1333 ****************************************************************************/
1334 int write_file(int fnum,char *data,int n)
1336 if (!Files[fnum].can_write) {
1341 if (!Files[fnum].modified) {
1343 Files[fnum].modified = True;
1344 if (fstat(Files[fnum].fd,&st) == 0) {
1345 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1346 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1347 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1352 return(write_data(Files[fnum].fd,data,n));
1356 /****************************************************************************
1357 load parameters specific to a connection/service
1358 ****************************************************************************/
1359 BOOL become_service(int cnum,BOOL do_chdir)
1361 extern char magic_char;
1362 static int last_cnum = -1;
1365 if (!OPEN_CNUM(cnum))
1371 Connections[cnum].lastused = smb_last_time;
1376 ChDir(Connections[cnum].connectpath) != 0 &&
1377 ChDir(Connections[cnum].origpath) != 0)
1379 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1380 Connections[cnum].connectpath,cnum));
1384 if (cnum == last_cnum)
1389 case_default = lp_defaultcase(snum);
1390 case_preserve = lp_preservecase(snum);
1391 short_case_preserve = lp_shortpreservecase(snum);
1392 case_mangle = lp_casemangle(snum);
1393 case_sensitive = lp_casesensitive(snum);
1394 magic_char = lp_magicchar(snum);
1395 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1400 /****************************************************************************
1401 find a service entry
1402 ****************************************************************************/
1403 int find_service(char *service)
1407 string_sub(service,"\\","/");
1409 iService = lp_servicenumber(service);
1411 /* now handle the special case of a home directory */
1414 char *phome_dir = get_home_dir(service);
1415 DEBUG(3,("checking for home directory %s gave %s\n",service,
1416 phome_dir?phome_dir:"(NULL)"));
1420 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1422 lp_add_home(service,iHomeService,phome_dir);
1423 iService = lp_servicenumber(service);
1428 /* If we still don't have a service, attempt to add it as a printer. */
1431 int iPrinterService;
1433 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1437 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1439 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1441 DEBUG(3,("%s is a valid printer name\n", service));
1442 DEBUG(3,("adding %s as a printer service\n", service));
1443 lp_add_printer(service,iPrinterService);
1444 iService = lp_servicenumber(service);
1446 DEBUG(0,("failed to add %s as a printer service!\n", service));
1449 DEBUG(3,("%s is not a valid printer name\n", service));
1453 /* just possibly it's a default service? */
1456 char *defservice = lp_defaultservice();
1457 if (defservice && *defservice && !strequal(defservice,service)) {
1458 iService = find_service(defservice);
1459 if (iService >= 0) {
1460 string_sub(service,"_","/");
1461 iService = lp_add_service(service,iService);
1467 if (!VALID_SNUM(iService))
1469 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1474 DEBUG(3,("find_service() failed to find service %s\n", service));
1480 /****************************************************************************
1481 create an error packet from a cached error.
1482 ****************************************************************************/
1483 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1485 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1487 int32 eclass = wbmpx->wr_errclass;
1488 int32 err = wbmpx->wr_error;
1490 /* We can now delete the auxiliary struct */
1491 free((char *)wbmpx);
1492 Files[fnum].wbmpx_ptr = NULL;
1493 return error_packet(inbuf,outbuf,eclass,err,line);
1502 } unix_smb_errmap[] =
1504 {EPERM,ERRDOS,ERRnoaccess},
1505 {EACCES,ERRDOS,ERRnoaccess},
1506 {ENOENT,ERRDOS,ERRbadfile},
1507 {EIO,ERRHRD,ERRgeneral},
1508 {EBADF,ERRSRV,ERRsrverror},
1509 {EINVAL,ERRSRV,ERRsrverror},
1510 {EEXIST,ERRDOS,ERRfilexists},
1511 {ENFILE,ERRDOS,ERRnofids},
1512 {EMFILE,ERRDOS,ERRnofids},
1513 {ENOSPC,ERRHRD,ERRdiskfull},
1515 {EDQUOT,ERRHRD,ERRdiskfull},
1518 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1521 {EXDEV,ERRDOS,ERRdiffdevice},
1523 {EROFS,ERRHRD,ERRnowrite},
1528 /****************************************************************************
1529 create an error packet from errno
1530 ****************************************************************************/
1531 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1533 int eclass=def_class;
1537 if (unix_ERR_class != SUCCESS)
1539 eclass = unix_ERR_class;
1540 ecode = unix_ERR_code;
1541 unix_ERR_class = SUCCESS;
1546 while (unix_smb_errmap[i].smbclass != 0)
1548 if (unix_smb_errmap[i].unixerror == errno)
1550 eclass = unix_smb_errmap[i].smbclass;
1551 ecode = unix_smb_errmap[i].smbcode;
1558 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1562 /****************************************************************************
1563 create an error packet. Normally called using the ERROR() macro
1564 ****************************************************************************/
1565 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1567 int outsize = set_message(outbuf,0,0,True);
1569 cmd = CVAL(inbuf,smb_com);
1571 CVAL(outbuf,smb_rcls) = error_class;
1572 SSVAL(outbuf,smb_err,error_code);
1574 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1577 (int)CVAL(inbuf,smb_com),
1578 smb_fn_name(CVAL(inbuf,smb_com)),
1583 DEBUG(3,("error string = %s\n",strerror(errno)));
1589 #ifndef SIGCLD_IGNORE
1590 /****************************************************************************
1591 this prevents zombie child processes
1592 ****************************************************************************/
1593 static int sig_cld()
1595 static int depth = 0;
1598 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1605 DEBUG(5,("got SIGCLD\n"));
1608 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1612 /* Stevens, Adv. Unix Prog. says that on system V you must call
1613 wait before reinstalling the signal handler, because the kernel
1614 calls the handler from within the signal-call when there is a
1615 child that has exited. This would lead to an infinite recursion
1616 if done vice versa. */
1618 #ifndef DONT_REINSTALL_SIG
1619 #ifdef SIGCLD_IGNORE
1620 signal(SIGCLD, SIG_IGN);
1622 signal(SIGCLD, SIGNAL_CAST sig_cld);
1627 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1630 BlockSignals(False);
1635 /****************************************************************************
1636 this is called when the client exits abruptly
1637 **************************************************************************/
1638 static int sig_pipe()
1640 exit_server("Got sigpipe\n");
1644 /****************************************************************************
1645 open the socket communication
1646 ****************************************************************************/
1647 static BOOL open_sockets(BOOL is_daemon,int port)
1654 struct sockaddr addr;
1655 int in_addrlen = sizeof(addr);
1658 #ifdef SIGCLD_IGNORE
1659 signal(SIGCLD, SIG_IGN);
1661 signal(SIGCLD, SIGNAL_CAST sig_cld);
1664 /* open an incoming socket */
1665 s = open_socket_in(SOCK_STREAM, port, 0);
1669 /* ready to listen */
1670 if (listen(s, 5) == -1)
1672 DEBUG(0,("listen: %s",strerror(errno)));
1677 /* now accept incoming connections - forking a new process
1678 for each incoming connection */
1679 DEBUG(2,("waiting for a connection\n"));
1682 Client = accept(s,&addr,&in_addrlen);
1684 if (Client == -1 && errno == EINTR)
1689 DEBUG(0,("accept: %s",strerror(errno)));
1693 #ifdef NO_FORK_DEBUG
1694 #ifndef NO_SIGNAL_TEST
1695 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1696 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1700 if (Client != -1 && fork()==0)
1702 #ifndef NO_SIGNAL_TEST
1703 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1704 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1706 /* close the listening socket */
1709 /* close our standard file descriptors */
1712 set_socket_options(Client,"SO_KEEPALIVE");
1713 set_socket_options(Client,user_socket_options);
1717 close(Client); /* The parent doesn't need this socket */
1723 /* We will abort gracefully when the client or remote system
1725 #ifndef NO_SIGNAL_TEST
1726 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1730 /* close our standard file descriptors */
1733 set_socket_options(Client,"SO_KEEPALIVE");
1734 set_socket_options(Client,user_socket_options);
1741 /****************************************************************************
1742 check if a snum is in use
1743 ****************************************************************************/
1744 BOOL snum_used(int snum)
1747 for (i=0;i<MAX_CONNECTIONS;i++)
1748 if (OPEN_CNUM(i) && (SNUM(i) == snum))
1753 /****************************************************************************
1754 reload the services file
1755 **************************************************************************/
1756 BOOL reload_services(BOOL test)
1763 strcpy(fname,lp_configfile());
1764 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
1766 strcpy(servicesf,fname);
1773 if (test && !lp_file_list_changed())
1776 lp_killunused(snum_used);
1778 ret = lp_load(servicesf,False);
1780 /* perhaps the config filename is now set */
1782 reload_services(True);
1789 set_socket_options(Client,"SO_KEEPALIVE");
1790 set_socket_options(Client,user_socket_options);
1794 create_mangled_stack(lp_mangledstack());
1796 /* this forces service parameters to be flushed */
1797 become_service(-1,True);
1804 /****************************************************************************
1805 this prevents zombie child processes
1806 ****************************************************************************/
1807 static int sig_hup()
1810 DEBUG(0,("Got SIGHUP\n"));
1811 reload_services(False);
1812 #ifndef DONT_REINSTALL_SIG
1813 signal(SIGHUP,SIGNAL_CAST sig_hup);
1815 BlockSignals(False);
1819 /****************************************************************************
1820 Setup the groups a user belongs to.
1821 ****************************************************************************/
1822 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
1823 int **p_igroups, gid_t **p_groups)
1825 if (-1 == initgroups(user,gid))
1829 DEBUG(0,("Unable to initgroups!\n"));
1830 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
1831 DEBUG(0,("This is probably a problem with the account %s\n",user));
1839 ngroups = getgroups(0,&grp);
1842 igroups = (int *)malloc(sizeof(int)*ngroups);
1843 for (i=0;i<ngroups;i++)
1844 igroups[i] = 0x42424242;
1845 ngroups = getgroups(ngroups,(gid_t *)igroups);
1847 if (igroups[0] == 0x42424242)
1850 *p_ngroups = ngroups;
1852 /* The following bit of code is very strange. It is due to the
1853 fact that some OSes use int* and some use gid_t* for
1854 getgroups, and some (like SunOS) use both, one in prototypes,
1855 and one in man pages and the actual code. Thus we detect it
1856 dynamically using some very ugly code */
1859 /* does getgroups return ints or gid_t ?? */
1860 static BOOL groups_use_ints = True;
1862 if (groups_use_ints &&
1864 SVAL(igroups,2) == 0x4242)
1865 groups_use_ints = False;
1867 for (i=0;groups_use_ints && i<ngroups;i++)
1868 if (igroups[i] == 0x42424242)
1869 groups_use_ints = False;
1871 if (groups_use_ints)
1873 *p_igroups = igroups;
1874 *p_groups = (gid_t *)igroups;
1878 gid_t *groups = (gid_t *)igroups;
1879 igroups = (int *)malloc(sizeof(int)*ngroups);
1880 for (i=0;i<ngroups;i++)
1881 igroups[i] = groups[i];
1882 *p_igroups = igroups;
1883 *p_groups = (gid_t *)groups;
1886 DEBUG(3,("%s is in %d groups\n",user,ngroups));
1887 for (i=0;i<ngroups;i++)
1888 DEBUG(3,("%d ",igroups[i]));
1894 /****************************************************************************
1895 make a connection to a service
1896 ****************************************************************************/
1897 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
1901 struct passwd *pass = NULL;
1902 connection_struct *pcon;
1905 static BOOL first_connection = True;
1909 snum = find_service(service);
1912 if (strequal(service,"IPC$"))
1914 DEBUG(3,("%s refusing IPC connection\n",timestring()));
1918 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
1922 if (strequal(service,HOMES_NAME))
1924 if (*user && Get_Pwnam(user,True))
1925 return(make_connection(user,user,password,pwlen,dev,vuid));
1927 if (validated_username(vuid))
1929 strcpy(user,validated_username(vuid));
1930 return(make_connection(user,user,password,pwlen,dev,vuid));
1934 if (!lp_snum_ok(snum) || !check_access(snum)) {
1938 /* you can only connect to the IPC$ service as an ipc device */
1939 if (strequal(service,"IPC$"))
1942 if (*dev == '?' || !*dev)
1944 if (lp_print_ok(snum))
1945 strcpy(dev,"LPT1:");
1950 /* if the request is as a printer and you can't print then refuse */
1952 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
1953 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
1957 /* lowercase the user name */
1960 /* add it as a possible user name */
1961 add_session_user(service);
1963 /* shall we let them in? */
1964 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
1966 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
1970 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
1973 DEBUG(0,("%s couldn't find free connection\n",timestring()));
1977 pcon = &Connections[cnum];
1978 bzero((char *)pcon,sizeof(*pcon));
1980 /* find out some info about the user */
1981 pass = Get_Pwnam(user,True);
1985 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
1989 pcon->read_only = lp_readonly(snum);
1993 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
1994 string_sub(list,"%S",service);
1996 if (user_in_list(user,list))
1997 pcon->read_only = True;
1999 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2000 string_sub(list,"%S",service);
2002 if (user_in_list(user,list))
2003 pcon->read_only = False;
2006 /* admin user check */
2007 if (user_in_list(user,lp_admin_users(snum)) &&
2010 pcon->admin_user = True;
2011 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2014 pcon->admin_user = False;
2016 pcon->force_user = force;
2017 pcon->uid = pass->pw_uid;
2018 pcon->gid = pass->pw_gid;
2019 pcon->num_files_open = 0;
2020 pcon->lastused = time(NULL);
2021 pcon->service = snum;
2023 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2024 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2025 pcon->dirptr = NULL;
2026 string_set(&pcon->dirpath,"");
2027 string_set(&pcon->user,user);
2030 if (*lp_force_group(snum))
2032 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2035 pcon->gid = gptr->gr_gid;
2036 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2039 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2043 if (*lp_force_user(snum))
2045 struct passwd *pass2;
2047 strcpy(fuser,lp_force_user(snum));
2048 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2051 pcon->uid = pass2->pw_uid;
2052 string_set(&pcon->user,fuser);
2054 pcon->force_user = True;
2055 DEBUG(3,("Forced user %s\n",fuser));
2058 DEBUG(1,("Couldn't find user %s\n",fuser));
2063 strcpy(s,lp_pathname(snum));
2064 standard_sub(cnum,s);
2065 string_set(&pcon->connectpath,s);
2066 DEBUG(3,("Connect path is %s\n",s));
2069 /* groups stuff added by ih */
2071 pcon->groups = NULL;
2075 /* Find all the groups this uid is in and store them. Used by become_user() */
2076 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2078 /* check number of connections */
2079 if (!claim_connection(cnum,
2080 lp_servicename(SNUM(cnum)),
2081 lp_max_connections(SNUM(cnum)),False))
2083 DEBUG(1,("too many connections - rejected\n"));
2087 if (lp_status(SNUM(cnum)))
2088 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2090 first_connection = False;
2095 /* execute any "root preexec = " line */
2096 if (*lp_rootpreexec(SNUM(cnum)))
2099 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2100 standard_sub(cnum,cmd);
2101 DEBUG(5,("cmd=%s\n",cmd));
2105 if (!become_user(cnum,pcon->uid))
2107 DEBUG(0,("Can't become connected user!\n"));
2109 if (!IS_IPC(cnum)) {
2110 yield_connection(cnum,
2111 lp_servicename(SNUM(cnum)),
2112 lp_max_connections(SNUM(cnum)));
2113 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2118 if (ChDir(pcon->connectpath) != 0)
2120 DEBUG(0,("Can't change directory to %s (%s)\n",
2121 pcon->connectpath,strerror(errno)));
2124 if (!IS_IPC(cnum)) {
2125 yield_connection(cnum,
2126 lp_servicename(SNUM(cnum)),
2127 lp_max_connections(SNUM(cnum)));
2128 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2133 string_set(&pcon->origpath,pcon->connectpath);
2135 #if SOFTLINK_OPTIMISATION
2136 /* resolve any soft links early */
2139 strcpy(s,pcon->connectpath);
2141 string_set(&pcon->connectpath,s);
2142 ChDir(pcon->connectpath);
2146 num_connections_open++;
2147 add_session_user(user);
2149 /* execute any "preexec = " line */
2150 if (*lp_preexec(SNUM(cnum)))
2153 strcpy(cmd,lp_preexec(SNUM(cnum)));
2154 standard_sub(cnum,cmd);
2158 /* we've finished with the sensitive stuff */
2162 extern struct from_host Client_info;
2163 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2165 Client_info.name,Client_info.addr,
2166 lp_servicename(SNUM(cnum)),user,
2176 /****************************************************************************
2177 find first available file slot
2178 ****************************************************************************/
2179 int find_free_file(void )
2182 /* we start at 1 here for an obscure reason I can't now remember,
2183 but I think is important :-) */
2184 for (i=1;i<MAX_OPEN_FILES;i++)
2187 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2191 /****************************************************************************
2192 find first available connection slot, starting from a random position.
2193 The randomisation stops problems with the server dieing and clients
2194 thinking the server is still available.
2195 ****************************************************************************/
2196 static int find_free_connection(int hash )
2200 hash = (hash % (MAX_CONNECTIONS-2))+1;
2204 for (i=hash+1;i!=hash;)
2206 if (!Connections[i].open && Connections[i].used == used)
2208 DEBUG(3,("found free connection number %d\n",i));
2212 if (i == MAX_CONNECTIONS)
2222 DEBUG(1,("ERROR! Out of connection structures\n"));
2227 /****************************************************************************
2228 reply for the core protocol
2229 ****************************************************************************/
2230 int reply_corep(char *outbuf)
2232 int outsize = set_message(outbuf,1,0,True);
2234 Protocol = PROTOCOL_CORE;
2240 /****************************************************************************
2241 reply for the coreplus protocol
2242 ****************************************************************************/
2243 int reply_coreplus(char *outbuf)
2245 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2246 int outsize = set_message(outbuf,13,0,True);
2247 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2248 readbraw and writebraw (possibly) */
2249 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2250 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2252 Protocol = PROTOCOL_COREPLUS;
2258 /****************************************************************************
2259 reply for the lanman 1.0 protocol
2260 ****************************************************************************/
2261 int reply_lanman1(char *outbuf)
2263 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2265 BOOL doencrypt = SMBENCRYPT();
2266 time_t t = time(NULL);
2268 if (lp_security()>=SEC_USER) secword |= 1;
2269 if (doencrypt) secword |= 2;
2271 set_message(outbuf,13,doencrypt?8:0,True);
2272 SSVAL(outbuf,smb_vwv1,secword);
2274 /* Create a token value and add it to the outgoing packet. */
2276 generate_next_challenge(smb_buf(outbuf));
2279 Protocol = PROTOCOL_LANMAN1;
2281 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2282 DEBUG(3,("using password server validation\n"));
2284 if (doencrypt) set_challenge(smb_buf(outbuf));
2288 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2289 SSVAL(outbuf,smb_vwv2,maxxmit);
2290 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2291 SSVAL(outbuf,smb_vwv4,1);
2292 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2293 readbraw writebraw (possibly) */
2294 SIVAL(outbuf,smb_vwv6,getpid());
2295 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2297 put_dos_date(outbuf,smb_vwv8,t);
2299 return (smb_len(outbuf)+4);
2303 /****************************************************************************
2304 reply for the lanman 2.0 protocol
2305 ****************************************************************************/
2306 int reply_lanman2(char *outbuf)
2308 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2310 BOOL doencrypt = SMBENCRYPT();
2311 time_t t = time(NULL);
2313 if (lp_security()>=SEC_USER) secword |= 1;
2314 if (doencrypt) secword |= 2;
2316 set_message(outbuf,13,doencrypt?8:0,True);
2317 SSVAL(outbuf,smb_vwv1,secword);
2319 /* Create a token value and add it to the outgoing packet. */
2321 generate_next_challenge(smb_buf(outbuf));
2324 SIVAL(outbuf,smb_vwv6,getpid());
2326 Protocol = PROTOCOL_LANMAN2;
2328 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2329 DEBUG(3,("using password server validation\n"));
2331 if (doencrypt) set_challenge(smb_buf(outbuf));
2335 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2336 SSVAL(outbuf,smb_vwv2,maxxmit);
2337 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2338 SSVAL(outbuf,smb_vwv4,1);
2339 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2340 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2341 put_dos_date(outbuf,smb_vwv8,t);
2343 return (smb_len(outbuf)+4);
2346 /****************************************************************************
2347 reply for the nt protocol
2348 ****************************************************************************/
2349 int reply_nt1(char *outbuf)
2351 int capabilities=0x300; /* has dual names + lock_and_read */
2353 BOOL doencrypt = SMBENCRYPT();
2354 time_t t = time(NULL);
2356 if (lp_security()>=SEC_USER) secword |= 1;
2357 if (doencrypt) secword |= 2;
2359 set_message(outbuf,17,doencrypt?8:0,True);
2360 CVAL(outbuf,smb_vwv1) = secword;
2362 /* Create a token value and add it to the outgoing packet. */
2364 generate_next_challenge(smb_buf(outbuf));
2365 /* Tell the nt machine how long the challenge is. */
2366 SSVALS(outbuf,smb_vwv16+1,8);
2370 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2372 Protocol = PROTOCOL_NT1;
2374 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2375 DEBUG(3,("using password server validation\n"));
2377 if (doencrypt) set_challenge(smb_buf(outbuf));
2381 if (lp_readraw() && lp_writeraw())
2384 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2385 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2386 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2387 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2388 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2389 put_long_date(outbuf+smb_vwv11+1,t);
2390 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2392 return (smb_len(outbuf)+4);
2396 /* these are the protocol lists used for auto architecture detection:
2399 protocol [PC NETWORK PROGRAM 1.0]
2400 protocol [XENIX CORE]
2401 protocol [MICROSOFT NETWORKS 1.03]
2402 protocol [LANMAN1.0]
2403 protocol [Windows for Workgroups 3.1a]
2404 protocol [LM1.2X002]
2405 protocol [LANMAN2.1]
2406 protocol [NT LM 0.12]
2409 protocol [PC NETWORK PROGRAM 1.0]
2410 protocol [XENIX CORE]
2411 protocol [MICROSOFT NETWORKS 1.03]
2412 protocol [LANMAN1.0]
2413 protocol [Windows for Workgroups 3.1a]
2414 protocol [LM1.2X002]
2415 protocol [LANMAN2.1]
2416 protocol [NT LM 0.12]
2419 protocol [PC NETWORK PROGRAM 1.0]
2420 protocol [XENIX CORE]
2421 protocol [LANMAN1.0]
2422 protocol [LM1.2X002]
2423 protocol [LANMAN2.1]
2427 * Modified to recognize the architecture of the remote machine better.
2429 * This appears to be the matrix of which protocol is used by which
2431 Protocol WfWg Win95 WinNT OS/2
2432 PC NETWORK PROGRAM 1.0 1 1 1 1
2434 MICROSOFT NETWORKS 3.0 2 2
2436 MICROSOFT NETWORKS 1.03 3
2439 Windows for Workgroups 3.1a 5 5 5
2444 * tim@fsg.com 09/29/95
2447 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2448 #define ARCH_WIN95 0x2
2449 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2450 #define ARCH_WINNT 0x8
2451 #define ARCH_SAMBA 0x10
2453 #define ARCH_ALL 0x1F
2455 /* List of supported protocols, most desired first */
2459 int (*proto_reply_fn)(char *);
2461 } supported_protocols[] = {
2462 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2463 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2464 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2465 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2466 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2467 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2468 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2469 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2470 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2475 /****************************************************************************
2477 ****************************************************************************/
2478 static int reply_negprot(char *inbuf,char *outbuf)
2480 extern fstring remote_arch;
2481 int outsize = set_message(outbuf,1,0,True);
2486 int bcc = SVAL(smb_buf(inbuf),-2);
2487 int arch = ARCH_ALL;
2489 p = smb_buf(inbuf)+1;
2490 while (p < (smb_buf(inbuf) + bcc))
2493 DEBUG(3,("Requested protocol [%s]\n",p));
2494 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2495 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2496 else if (strcsequal(p,"DOS LM1.2X002"))
2497 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2498 else if (strcsequal(p,"DOS LANMAN2.1"))
2499 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2500 else if (strcsequal(p,"NT LM 0.12"))
2501 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2502 else if (strcsequal(p,"LANMAN2.1"))
2503 arch &= ( ARCH_WINNT | ARCH_OS2 );
2504 else if (strcsequal(p,"LM1.2X002"))
2505 arch &= ( ARCH_WINNT | ARCH_OS2 );
2506 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2508 else if (strcsequal(p,"XENIX CORE"))
2509 arch &= ( ARCH_WINNT | ARCH_OS2 );
2510 else if (strcsequal(p,"Samba")) {
2520 strcpy(remote_arch,"Samba");
2523 strcpy(remote_arch,"WfWg");
2526 strcpy(remote_arch,"Win95");
2529 strcpy(remote_arch,"WinNT");
2532 strcpy(remote_arch,"OS2");
2535 strcpy(remote_arch,"UNKNOWN");
2539 /* possibly reload - change of architecture */
2540 reload_services(True);
2542 /* a special case to stop password server loops */
2543 if (Index == 1 && strequal(remote_machine,myhostname) &&
2544 lp_security()==SEC_SERVER)
2545 exit_server("Password server loop!");
2547 /* Check for protocols, most desirable first */
2548 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2550 p = smb_buf(inbuf)+1;
2552 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2553 while (p < (smb_buf(inbuf) + bcc))
2555 if (strequal(p,supported_protocols[protocol].proto_name))
2564 SSVAL(outbuf,smb_vwv0,choice);
2566 extern fstring remote_proto;
2567 strcpy(remote_proto,supported_protocols[protocol].short_name);
2568 reload_services(True);
2569 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2570 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2573 DEBUG(0,("No protocol supported !\n"));
2575 SSVAL(outbuf,smb_vwv0,choice);
2577 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2583 /****************************************************************************
2584 parse a connect packet
2585 ****************************************************************************/
2586 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
2588 char *p = smb_buf(buf) + 1;
2591 DEBUG(4,("parsing connect string %s\n",p));
2593 p2 = strrchr(p,'\\');
2597 strcpy(service,p2+1);
2602 *pwlen = strlen(password);
2609 p = strchr(service,'%');
2618 /****************************************************************************
2619 close all open files for a connection
2620 ****************************************************************************/
2621 static void close_open_files(int cnum)
2624 for (i=0;i<MAX_OPEN_FILES;i++)
2625 if( Files[i].cnum == cnum && Files[i].open) {
2632 /****************************************************************************
2634 ****************************************************************************/
2635 void close_cnum(int cnum, int uid)
2637 extern struct from_host Client_info;
2639 DirCacheFlush(SNUM(cnum));
2643 if (!OPEN_CNUM(cnum))
2645 DEBUG(0,("Can't close cnum %d\n",cnum));
2649 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2651 Client_info.name,Client_info.addr,
2652 lp_servicename(SNUM(cnum))));
2654 yield_connection(cnum,
2655 lp_servicename(SNUM(cnum)),
2656 lp_max_connections(SNUM(cnum)));
2658 if (lp_status(SNUM(cnum)))
2659 yield_connection(cnum,"STATUS.",MAXSTATUS);
2661 close_open_files(cnum);
2662 dptr_closecnum(cnum);
2664 /* execute any "postexec = " line */
2665 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
2668 strcpy(cmd,lp_postexec(SNUM(cnum)));
2669 standard_sub(cnum,cmd);
2675 /* execute any "root postexec = " line */
2676 if (*lp_rootpostexec(SNUM(cnum)))
2679 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2680 standard_sub(cnum,cmd);
2684 Connections[cnum].open = False;
2685 num_connections_open--;
2686 if (Connections[cnum].ngroups && Connections[cnum].groups)
2688 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2689 free(Connections[cnum].groups);
2690 free(Connections[cnum].igroups);
2691 Connections[cnum].groups = NULL;
2692 Connections[cnum].igroups = NULL;
2693 Connections[cnum].ngroups = 0;
2696 string_set(&Connections[cnum].user,"");
2697 string_set(&Connections[cnum].dirpath,"");
2698 string_set(&Connections[cnum].connectpath,"");
2702 /****************************************************************************
2703 simple routines to do connection counting
2704 ****************************************************************************/
2705 BOOL yield_connection(int cnum,char *name,int max_connections)
2707 struct connect_record crec;
2710 int mypid = getpid();
2713 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2715 if (max_connections <= 0)
2718 bzero(&crec,sizeof(crec));
2720 strcpy(fname,lp_lockdir());
2721 standard_sub(cnum,fname);
2722 trim_string(fname,"","/");
2726 strcat(fname,".LCK");
2728 f = fopen(fname,"r+");
2731 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
2735 fseek(f,0,SEEK_SET);
2737 /* find a free spot */
2738 for (i=0;i<max_connections;i++)
2740 if (fread(&crec,sizeof(crec),1,f) != 1)
2742 DEBUG(2,("Entry not found in lock file %s\n",fname));
2746 if (crec.pid == mypid && crec.cnum == cnum)
2750 if (crec.pid != mypid || crec.cnum != cnum)
2753 DEBUG(2,("Entry not found in lock file %s\n",fname));
2757 bzero((void *)&crec,sizeof(crec));
2759 /* remove our mark */
2760 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2761 fwrite(&crec,sizeof(crec),1,f) != 1)
2763 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
2768 DEBUG(3,("Yield successful\n"));
2775 /****************************************************************************
2776 simple routines to do connection counting
2777 ****************************************************************************/
2778 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
2780 struct connect_record crec;
2783 int snum = SNUM(cnum);
2787 if (max_connections <= 0)
2790 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
2792 strcpy(fname,lp_lockdir());
2793 standard_sub(cnum,fname);
2794 trim_string(fname,"","/");
2796 if (!directory_exist(fname,NULL))
2801 strcat(fname,".LCK");
2803 if (!file_exist(fname,NULL))
2805 f = fopen(fname,"w");
2809 total_recs = file_size(fname) / sizeof(crec);
2811 f = fopen(fname,"r+");
2815 DEBUG(1,("couldn't open lock file %s\n",fname));
2819 /* find a free spot */
2820 for (i=0;i<max_connections;i++)
2823 if (i>=total_recs ||
2824 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
2825 fread(&crec,sizeof(crec),1,f) != 1)
2827 if (foundi < 0) foundi = i;
2831 if (Clear && crec.pid && !process_exists(crec.pid))
2833 fseek(f,i*sizeof(crec),SEEK_SET);
2834 bzero((void *)&crec,sizeof(crec));
2835 fwrite(&crec,sizeof(crec),1,f);
2836 if (foundi < 0) foundi = i;
2839 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
2848 DEBUG(3,("no free locks in %s\n",fname));
2853 /* fill in the crec */
2854 bzero((void *)&crec,sizeof(crec));
2855 crec.magic = 0x280267;
2856 crec.pid = getpid();
2858 crec.uid = Connections[cnum].uid;
2859 crec.gid = Connections[cnum].gid;
2860 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
2861 crec.start = time(NULL);
2864 extern struct from_host Client_info;
2865 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
2866 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
2870 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
2871 fwrite(&crec,sizeof(crec),1,f) != 1)
2882 /*******************************************************************
2883 prepare to dump a core file - carefully!
2884 ********************************************************************/
2885 static BOOL dump_core(void)
2889 strcpy(dname,debugf);
2890 if ((p=strrchr(dname,'/'))) *p=0;
2891 strcat(dname,"/corefiles");
2893 sys_chown(dname,getuid(),getgid());
2895 if (chdir(dname)) return(False);
2898 #ifndef NO_GETRLIMIT
2902 getrlimit(RLIMIT_CORE, &rlp);
2903 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
2904 setrlimit(RLIMIT_CORE, &rlp);
2905 getrlimit(RLIMIT_CORE, &rlp);
2906 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
2912 DEBUG(0,("Dumping core in %s\n",dname));
2917 /****************************************************************************
2919 ****************************************************************************/
2920 void exit_server(char *reason)
2922 static int firsttime=1;
2925 if (!firsttime) exit(0);
2929 DEBUG(2,("Closing connections\n"));
2930 for (i=0;i<MAX_CONNECTIONS;i++)
2931 if (Connections[i].open)
2934 if (dcelogin_atmost_once)
2938 int oldlevel = DEBUGLEVEL;
2940 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
2942 show_msg(last_inbuf);
2943 DEBUGLEVEL = oldlevel;
2944 DEBUG(0,("===============================================================\n"));
2946 if (dump_core()) return;
2949 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
2953 /****************************************************************************
2954 do some standard substitutions in a string
2955 ****************************************************************************/
2956 void standard_sub(int cnum,char *s)
2958 if (!strchr(s,'%')) return;
2960 if (VALID_CNUM(cnum))
2962 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
2963 string_sub(s,"%P",Connections[cnum].connectpath);
2964 string_sub(s,"%u",Connections[cnum].user);
2965 if (strstr(s,"%H")) {
2966 char *home = get_home_dir(Connections[cnum].user);
2967 if (home) string_sub(s,"%H",home);
2969 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
2971 standard_sub_basic(s);
2975 These flags determine some of the permissions required to do an operation
2977 Note that I don't set NEED_WRITE on some write operations because they
2978 are used by some brain-dead clients when printing, and I don't want to
2979 force write permissions on print services.
2981 #define AS_USER (1<<0)
2982 #define NEED_WRITE (1<<1)
2983 #define TIME_INIT (1<<2)
2984 #define CAN_IPC (1<<3)
2985 #define AS_GUEST (1<<5)
2989 define a list of possible SMB messages and their corresponding
2990 functions. Any message that has a NULL function is unimplemented -
2991 please feel free to contribute implementations!
2993 struct smb_message_struct
3007 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3008 {SMBtcon,"SMBtcon",reply_tcon,0},
3009 {SMBtdis,"SMBtdis",reply_tdis,0},
3010 {SMBexit,"SMBexit",reply_exit,0},
3011 {SMBioctl,"SMBioctl",reply_ioctl,0},
3012 {SMBecho,"SMBecho",reply_echo,0},
3013 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3014 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3015 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3016 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3017 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3018 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3019 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3020 {SMBopen,"SMBopen",reply_open,AS_USER},
3022 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3023 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3024 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3026 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3027 {SMBread,"SMBread",reply_read,AS_USER},
3028 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3029 {SMBclose,"SMBclose",reply_close,AS_USER},
3030 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3031 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3032 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3033 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3035 /* this is a Pathworks specific call, allowing the
3036 changing of the root path */
3037 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3039 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3040 {SMBflush,"SMBflush",reply_flush,AS_USER},
3041 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3042 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3043 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3044 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3045 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3046 {SMBlock,"SMBlock",reply_lock,AS_USER},
3047 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3049 /* CORE+ PROTOCOL FOLLOWS */
3051 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3052 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3053 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3054 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3055 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3057 /* LANMAN1.0 PROTOCOL FOLLOWS */
3059 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3060 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3061 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3062 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3063 {SMBwritec,"SMBwritec",NULL,AS_USER},
3064 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3065 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3066 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3067 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3068 {SMBioctls,"SMBioctls",NULL,AS_USER},
3069 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3070 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3072 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3073 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3074 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3075 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3077 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3078 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3079 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3081 /* LANMAN2.0 PROTOCOL FOLLOWS */
3082 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3083 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3084 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3085 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3087 /* messaging routines */
3088 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3089 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3090 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3091 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3093 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3095 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3096 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3097 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3098 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3101 /****************************************************************************
3102 return a string containing the function name of a SMB command
3103 ****************************************************************************/
3104 char *smb_fn_name(int type)
3106 static char *unknown_name = "SMBunknown";
3107 static int num_smb_messages =
3108 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3111 for (match=0;match<num_smb_messages;match++)
3112 if (smb_messages[match].code == type)
3115 if (match == num_smb_messages)
3116 return(unknown_name);
3118 return(smb_messages[match].name);
3122 /****************************************************************************
3123 do a switch on the message type, and return the response size
3124 ****************************************************************************/
3125 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3129 static int num_smb_messages =
3130 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3134 struct timeval msg_start_time;
3135 struct timeval msg_end_time;
3136 static unsigned long total_time = 0;
3138 GetTimeOfDay(&msg_start_time);
3145 last_message = type;
3147 /* make sure this is an SMB packet */
3148 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3150 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3154 for (match=0;match<num_smb_messages;match++)
3155 if (smb_messages[match].code == type)
3158 if (match == num_smb_messages)
3160 DEBUG(0,("Unknown message type %d!\n",type));
3161 outsize = reply_unknown(inbuf,outbuf);
3165 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3166 if (smb_messages[match].fn)
3168 int cnum = SVAL(inbuf,smb_tid);
3169 int flags = smb_messages[match].flags;
3170 int uid = SVAL(inbuf,smb_uid);
3172 /* does this protocol need to be run as root? */
3173 if (!(flags & AS_USER))
3176 /* does this protocol need to be run as the connected user? */
3177 if ((flags & AS_USER) && !become_user(cnum,uid))
3178 return(ERROR(ERRSRV,ERRinvnid));
3180 /* does it need write permission? */
3181 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3182 return(ERROR(ERRSRV,ERRaccess));
3184 /* ipc services are limited */
3185 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3186 return(ERROR(ERRSRV,ERRaccess));
3188 /* load service specific parameters */
3189 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3190 return(ERROR(ERRSRV,ERRaccess));
3192 /* does this protocol need to be run as guest? */
3193 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3194 return(ERROR(ERRSRV,ERRaccess));
3198 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3202 outsize = reply_unknown(inbuf,outbuf);
3207 GetTimeOfDay(&msg_end_time);
3208 if (!(smb_messages[match].flags & TIME_INIT))
3210 smb_messages[match].time = 0;
3211 smb_messages[match].flags |= TIME_INIT;
3214 unsigned long this_time =
3215 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3216 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3217 smb_messages[match].time += this_time;
3218 total_time += this_time;
3220 DEBUG(2,("TIME %s %d usecs %g pct\n",
3221 smb_fn_name(type),smb_messages[match].time,
3222 (100.0*smb_messages[match].time) / total_time));
3229 /****************************************************************************
3230 construct a chained reply and add it to the already made reply
3232 inbuf points to the original message start.
3233 inbuf2 points to the smb_wct part of the secondary message
3234 type is the type of the secondary message
3235 outbuf points to the original outbuffer
3236 outbuf2 points to the smb_wct field of the new outbuffer
3237 size is the total length of the incoming message (from inbuf1)
3238 bufsize is the total buffer size
3240 return how many bytes were added to the response
3241 ****************************************************************************/
3242 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3246 static BOOL in_chain = False;
3247 static char *last_outbuf=NULL;
3248 BOOL was_inchain = in_chain;
3249 int insize_remaining;
3250 static int insize_deleted;
3253 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3255 outbuf = last_outbuf;
3261 inbuf2 -= insize_deleted;
3262 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3263 insize_deleted += size - (insize_remaining + smb_wct);
3266 last_outbuf = outbuf;
3269 /* allocate some space for the in and out buffers of the chained message */
3270 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3271 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3275 DEBUG(0,("Out of memory in chain reply\n"));
3276 return(ERROR(ERRSRV,ERRnoresource));
3279 ibuf += SMB_ALIGNMENT;
3280 obuf += SMB_ALIGNMENT;
3282 /* create the in buffer */
3283 memcpy(ibuf,inbuf,smb_wct);
3284 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3285 CVAL(ibuf,smb_com) = type;
3287 /* create the out buffer */
3288 bzero(obuf,smb_size);
3290 set_message(obuf,0,0,True);
3291 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3293 memcpy(obuf+4,ibuf+4,4);
3294 CVAL(obuf,smb_rcls) = SUCCESS;
3295 CVAL(obuf,smb_reh) = 0;
3296 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3298 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3299 SSVAL(obuf,smb_err,SUCCESS);
3300 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3301 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3302 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3303 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3305 DEBUG(3,("Chained message\n"));
3308 /* process the request */
3309 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3310 bufsize-chain_size);
3312 /* copy the new reply header over the old one, but preserve
3313 the smb_com field */
3314 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3316 /* and copy the data from the reply to the right spot */
3317 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3319 /* free the allocated buffers */
3320 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3321 if (obuf) free(obuf-SMB_ALIGNMENT);
3323 in_chain = was_inchain;
3325 /* return how much extra has been added to the packet */
3326 return(outsize - smb_wct);
3331 /****************************************************************************
3332 construct a reply to the incoming packet
3333 ****************************************************************************/
3334 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3336 int type = CVAL(inbuf,smb_com);
3338 int msg_type = CVAL(inbuf,0);
3340 smb_last_time = time(NULL);
3344 bzero(outbuf,smb_size);
3347 return(reply_special(inbuf,outbuf));
3349 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3350 set_message(outbuf,0,0,True);
3352 memcpy(outbuf+4,inbuf+4,4);
3353 CVAL(outbuf,smb_rcls) = SUCCESS;
3354 CVAL(outbuf,smb_reh) = 0;
3355 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3357 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3358 SSVAL(outbuf,smb_err,SUCCESS);
3359 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3360 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3361 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3362 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3364 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3367 smb_setlen(outbuf,outsize - 4);
3372 /****************************************************************************
3373 process commands from the client
3374 ****************************************************************************/
3375 static void process(void)
3377 static int trans_num = 0;
3379 extern struct from_host Client_info;
3382 fromhost(Client,&Client_info);
3384 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3385 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3386 if ((InBuffer == NULL) || (OutBuffer == NULL))
3389 InBuffer += SMB_ALIGNMENT;
3390 OutBuffer += SMB_ALIGNMENT;
3393 DEBUG(3,("priming nmbd\n"));
3396 ip = *interpret_addr2("localhost");
3397 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3399 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3409 int deadtime = lp_deadtime()*60;
3411 int last_keepalive=0;
3414 deadtime = DEFAULT_SMBD_TIMEOUT;
3416 if (lp_readprediction())
3417 do_read_prediction();
3420 extern pstring share_del_pending;
3421 if (*share_del_pending) {
3423 if (!unlink(share_del_pending))
3424 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3426 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3427 share_del_pending[0] = 0;
3431 if (share_mode_pending) {
3433 check_share_modes();
3434 share_mode_pending=False;
3439 for (counter=SMBD_SELECT_LOOP;
3440 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3441 counter += SMBD_SELECT_LOOP)
3445 BOOL allidle = True;
3446 extern int keepalive;
3448 /* check for socket failure */
3450 DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno)));
3456 /* become root again if waiting */
3459 /* check for smb.conf reload */
3460 if (!(counter%SMBD_RELOAD_CHECK))
3461 reload_services(True);
3463 /* check the share modes every 10 secs */
3464 if (!(counter%SHARE_MODES_CHECK))
3465 check_share_modes();
3467 /* clean the share modes every 5 minutes */
3468 if (!(counter%SHARE_MODES_CLEAN))
3469 clean_share_files();
3471 /* automatic timeout if all connections are closed */
3472 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3473 DEBUG(2,("%s Closing idle connection\n",timestring()));
3477 if (keepalive && (counter-last_keepalive)>keepalive) {
3478 extern int password_client;
3479 if (!send_keepalive(Client)) {
3480 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3483 /* also send a keepalive to the password server if its still
3485 if (password_client != -1)
3486 send_keepalive(password_client);
3487 last_keepalive = counter;
3490 /* check for connection timeouts */
3491 for (i=0;i<MAX_CONNECTIONS;i++)
3492 if (Connections[i].open)
3494 /* close dirptrs on connections that are idle */
3495 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3498 if (Connections[i].num_files_open > 0 ||
3499 (t-Connections[i].lastused)<deadtime)
3503 if (allidle && num_connections_open>0) {
3504 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3509 msg_type = CVAL(InBuffer,0);
3510 msg_flags = CVAL(InBuffer,1);
3511 type = CVAL(InBuffer,smb_com);
3513 len = smb_len(InBuffer);
3515 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3519 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3522 if(trans_num == 1 && VT_Check(InBuffer)) {
3532 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3535 if (CVAL(OutBuffer,0) == 0)
3536 show_msg(OutBuffer);
3538 if (nread != smb_len(OutBuffer) + 4)
3540 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3542 smb_len(OutBuffer)));
3545 send_smb(Client,OutBuffer);
3552 /****************************************************************************
3553 initialise connect, service and file structs
3554 ****************************************************************************/
3555 static void init_structs(void )
3558 get_myname(myhostname,&myip);
3560 for (i=0;i<MAX_CONNECTIONS;i++)
3562 Connections[i].open = False;
3563 Connections[i].num_files_open=0;
3564 Connections[i].lastused=0;
3565 Connections[i].used=False;
3566 string_init(&Connections[i].user,"");
3567 string_init(&Connections[i].dirpath,"");
3568 string_init(&Connections[i].connectpath,"");
3569 string_init(&Connections[i].origpath,"");
3572 for (i=0;i<MAX_OPEN_FILES;i++)
3574 Files[i].open = False;
3575 string_init(&Files[i].name,"");
3581 /****************************************************************************
3582 usage on the program
3583 ****************************************************************************/
3584 static void usage(char *pname)
3586 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3588 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3589 printf("Version %s\n",VERSION);
3590 printf("\t-D become a daemon\n");
3591 printf("\t-p port listen on the specified port\n");
3592 printf("\t-d debuglevel set the debuglevel\n");
3593 printf("\t-l log basename. Basename for log/debug files\n");
3594 printf("\t-s services file. Filename of services file\n");
3595 printf("\t-P passive only\n");
3596 printf("\t-a overwrite log file, don't append\n");
3601 /****************************************************************************
3603 ****************************************************************************/
3604 int main(int argc,char *argv[])
3606 extern BOOL append_log;
3607 /* shall I run as a daemon */
3608 BOOL is_daemon = False;
3609 int port = SMB_PORT;
3611 extern char *optarg;
3613 #ifdef NEED_AUTH_PARAMETERS
3614 set_auth_parameters(argc,argv);
3625 strcpy(debugf,SMBLOGFILE);
3627 setup_logging(argv[0],False);
3629 charset_initialise();
3631 /* make absolutely sure we run as root - to handle cases whre people
3632 are crazy enough to have it setuid */
3642 fault_setup(exit_server);
3644 umask(0777 & ~DEF_CREATE_MASK);
3648 /* this is for people who can't start the program correctly */
3649 while (argc > 1 && (*argv[1] != '-'))
3655 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
3659 strcpy(user_socket_options,optarg);
3662 strcpy(scope,optarg);
3666 extern BOOL passive;
3671 strcpy(servicesf,optarg);
3674 strcpy(debugf,optarg);
3678 extern BOOL append_log;
3679 append_log = !append_log;
3689 DEBUGLEVEL = atoi(optarg);
3692 port = atoi(optarg);
3705 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
3706 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
3708 #ifndef NO_GETRLIMIT
3709 #ifdef RLIMIT_NOFILE
3712 getrlimit(RLIMIT_NOFILE, &rlp);
3713 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
3714 setrlimit(RLIMIT_NOFILE, &rlp);
3715 getrlimit(RLIMIT_NOFILE, &rlp);
3716 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
3722 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
3723 getuid(),getgid(),geteuid(),getegid()));
3725 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
3727 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
3733 if (!reload_services(False))
3736 #ifndef NO_SIGNAL_TEST
3737 signal(SIGHUP,SIGNAL_CAST sig_hup);
3740 DEBUG(3,("%s loaded services\n",timestring()));
3742 if (!is_daemon && !is_a_socket(0))
3744 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
3750 DEBUG(3,("%s becoming a daemon\n",timestring()));
3754 if (!open_sockets(is_daemon,port))
3757 /* possibly reload the services file. */
3758 reload_services(True);
3760 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
3764 if (sys_chroot(lp_rootdir()) == 0)
3765 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
3771 exit_server("normal exit");