2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1997
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;
28 extern fstring myworkgroup;
30 char *InBuffer = NULL;
31 char *OutBuffer = NULL;
32 char *last_inbuf = NULL;
37 /* the last message the was processed */
38 int last_message = -1;
40 /* a useful macro to debug the last message processed */
41 #define LAST_MESSAGE() smb_fn_name(last_message)
44 extern int DEBUGLEVEL;
45 extern int case_default;
46 extern BOOL case_sensitive;
47 extern BOOL case_preserve;
48 extern BOOL use_mangled_map;
49 extern BOOL short_case_preserve;
50 extern BOOL case_mangle;
51 extern time_t smb_last_time;
53 extern int smb_read_error;
55 extern pstring user_socket_options;
57 connection_struct Connections[MAX_CONNECTIONS];
58 files_struct Files[MAX_OPEN_FILES];
61 * Indirection for file fd's. Needed as POSIX locking
62 * is based on file/process, not fd/process.
64 file_fd_struct FileFd[MAX_OPEN_FILES];
65 int max_file_fd_used = 0;
70 * Size of data we can send to client. Set
71 * by the client for all protocols above CORE.
72 * Set by us for CORE protocol.
74 int max_send = BUFFER_SIZE;
76 * Size of the data we can receive. Set by us.
77 * Can be modified by the max xmit parameter.
79 int max_recv = BUFFER_SIZE;
81 /* a fnum to use when chaining */
84 /* number of open connections */
85 static int num_connections_open = 0;
87 extern fstring remote_machine;
91 /* these can be set by some functions to override the error codes */
92 int unix_ERR_class=SUCCESS;
96 extern int extra_time_offset;
98 extern pstring myhostname;
100 static int find_free_connection(int hash);
102 /* for readability... */
103 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
104 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
105 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
106 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
107 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
109 /****************************************************************************
110 when exiting, take the whole family
111 ****************************************************************************/
114 exit_server("caught signal");
115 return 0; /* Keep -Wall happy :-) */
117 /****************************************************************************
118 Send a SIGTERM to our process group.
119 *****************************************************************************/
122 if(am_parent) kill(0,SIGTERM);
125 /****************************************************************************
126 change a dos mode to a unix mode
127 base permission for files:
128 everybody gets read bit set
129 dos readonly is represented in unix by removing everyone's write bit
130 dos archive is represented in unix by the user's execute bit
131 dos system is represented in unix by the group's execute bit
132 dos hidden is represented in unix by the other's execute bit
133 Then apply create mask,
135 base permission for directories:
136 dos directory is represented in unix by unix's dir bit and the exec bit
137 Then apply create mask,
139 ****************************************************************************/
140 mode_t unix_mode(int cnum,int dosmode)
142 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
144 if ( !IS_DOS_READONLY(dosmode) )
145 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
147 if (IS_DOS_DIR(dosmode)) {
148 /* We never make directories read only for the owner as under DOS a user
149 can always create a file in a read-only directory. */
150 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
151 /* Apply directory mask */
152 result &= lp_dir_mode(SNUM(cnum));
153 /* Add in force bits */
154 result |= lp_force_dir_mode(SNUM(cnum));
156 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
159 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
162 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
165 /* Apply mode mask */
166 result &= lp_create_mode(SNUM(cnum));
167 /* Add in force bits */
168 result |= lp_force_create_mode(SNUM(cnum));
174 /****************************************************************************
175 change a unix mode to a dos mode
176 ****************************************************************************/
177 int dos_mode(int cnum,char *path,struct stat *sbuf)
180 extern struct current_user current_user;
182 DEBUG(5,("dos_mode: %d %s\n", cnum, path));
184 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
185 if (!((sbuf->st_mode & S_IWOTH) ||
186 Connections[cnum].admin_user ||
187 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
188 ((sbuf->st_mode & S_IWGRP) &&
189 in_group(sbuf->st_gid,current_user.gid,
190 current_user.ngroups,current_user.igroups))))
193 if ((sbuf->st_mode & S_IWUSR) == 0)
197 if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0))
200 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
203 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
206 if (S_ISDIR(sbuf->st_mode))
207 result = aDIR | (result & aRONLY);
210 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
214 /* hide files with a name starting with a . */
215 if (lp_hide_dot_files(SNUM(cnum)))
217 char *p = strrchr(path,'/');
223 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
227 /* Optimization : Only call is_hidden_path if it's not already
229 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path))
234 DEBUG(5,("dos_mode returning "));
236 if (result & aHIDDEN) DEBUG(5, ("h"));
237 if (result & aRONLY ) DEBUG(5, ("r"));
238 if (result & aSYSTEM) DEBUG(5, ("s"));
239 if (result & aDIR ) DEBUG(5, ("d"));
240 if (result & aARCH ) DEBUG(5, ("a"));
248 /*******************************************************************
249 chmod a file - but preserve some bits
250 ********************************************************************/
251 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
260 if (sys_stat(fname,st)) return(-1);
263 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
265 if (dos_mode(cnum,fname,st) == dosmode) return(0);
267 unixmode = unix_mode(cnum,dosmode);
269 /* preserve the s bits */
270 mask |= (S_ISUID | S_ISGID);
272 /* preserve the t bit */
277 /* possibly preserve the x bits */
278 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
279 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
280 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
282 unixmode |= (st->st_mode & mask);
284 /* if we previously had any r bits set then leave them alone */
285 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
286 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
290 /* if we previously had any w bits set then leave them alone
291 if the new mode is not rdonly */
292 if (!IS_DOS_READONLY(dosmode) &&
293 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
294 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
298 return(sys_chmod(fname,unixmode));
302 /****************************************************************************
303 check if two filenames are equal
305 this needs to be careful about whether we are case sensitive
306 ****************************************************************************/
307 static BOOL fname_equal(char *name1, char *name2)
309 int l1 = strlen(name1);
310 int l2 = strlen(name2);
312 /* handle filenames ending in a single dot */
313 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
317 ret = fname_equal(name1,name2);
322 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
326 ret = fname_equal(name1,name2);
331 /* now normal filename handling */
333 return(strcmp(name1,name2) == 0);
335 return(strequal(name1,name2));
339 /****************************************************************************
340 mangle the 2nd name and check if it is then equal to the first name
341 ****************************************************************************/
342 static BOOL mangled_equal(char *name1, char *name2)
346 if (is_8_3(name2, True))
349 strcpy(tmpname,name2);
350 mangle_name_83(tmpname);
352 return(strequal(name1,tmpname));
356 /****************************************************************************
357 scan a directory to find a filename, matching without case sensitivity
359 If the name looks like a mangled name then try via the mangling functions
360 ****************************************************************************/
361 static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
368 mangled = is_mangled(name);
370 /* handle null paths */
374 if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
380 check_mangled_stack(name);
382 /* open the directory */
383 if (!(cur_dir = OpenDir(cnum, path, True)))
385 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
389 /* now scan for matching names */
390 while ((dname = ReadDirName(cur_dir)))
393 (strequal(dname,".") || strequal(dname,"..")))
397 if (!name_map_mangle(name2,False,SNUM(cnum))) continue;
399 if ((mangled && mangled_equal(name,name2))
400 || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */
402 /* we've found the file, change it's name and return */
403 if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
414 /****************************************************************************
415 This routine is called to convert names from the dos namespace to unix
416 namespace. It needs to handle any case conversions, mangling, format
419 We assume that we have already done a chdir() to the right "root" directory
422 The function will return False if some part of the name except for the last
423 part cannot be resolved
425 If the saved_last_component != 0, then the unmodified last component
426 of the pathname is returned there. This is used in an exceptional
427 case in reply_mv (so far). If saved_last_component == 0 then nothing
430 The bad_path arg is set to True if the filename walk failed. This is
431 used to pick the correct error code to return between ENOENT and ENOTDIR
432 as Windows applications depend on ERRbadpath being returned if a component
433 of a pathname does not exist.
434 ****************************************************************************/
435 BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
445 if(saved_last_component)
446 *saved_last_component = 0;
448 /* convert to basic unix format - removing \ chars and cleaning it up */
450 unix_clean_name(name);
452 /* names must be relative to the root of the service - trim any leading /.
453 also trim trailing /'s */
454 trim_string(name,"/","/");
457 * Ensure saved_last_component is valid even if file exists.
459 if(saved_last_component) {
460 end = strrchr(name, '/');
462 strcpy(saved_last_component, end + 1);
464 strcpy(saved_last_component, name);
467 if (!case_sensitive &&
468 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
471 /* check if it's a printer file */
472 if (Connections[cnum].printer)
474 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
478 sprintf(name2,"%.6s.XXXXXX",remote_machine);
479 /* sanitise the name */
480 for (s=name2 ; *s ; s++)
481 if (!issafe(*s)) *s = '_';
482 strcpy(name,(char *)mktemp(name2));
487 /* stat the name - if it exists then we are all done! */
488 if (sys_stat(name,&st) == 0)
493 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
495 /* a special case - if we don't have any mangling chars and are case
496 sensitive then searching won't help */
497 if (case_sensitive && !is_mangled(name) &&
498 !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
501 /* now we need to recursively match the name against the real
502 directory structure */
505 while (strncmp(start,"./",2) == 0)
508 /* now match each part of the path name separately, trying the names
509 as is first, then trying to scan the directory for matching names */
510 for (;start;start = (end?end+1:(char *)NULL))
512 /* pinpoint the end of this section of the filename */
513 end = strchr(start, '/');
515 /* chop the name at this point */
518 if(saved_last_component != 0)
519 strcpy(saved_last_component, end ? end + 1 : start);
521 /* check if the name exists up to this point */
522 if (sys_stat(name, &st) == 0)
524 /* it exists. it must either be a directory or this must be
525 the last part of the path for it to be OK */
526 if (end && !(st.st_mode & S_IFDIR))
528 /* an intermediate part of the name isn't a directory */
529 DEBUG(5,("Not a dir %s\n",start));
540 /* remember the rest of the pathname so it can be restored
542 if (end) strcpy(rest,end+1);
544 /* try to find this part of the path in the directory */
545 if (strchr(start,'?') || strchr(start,'*') ||
546 !scan_directory(dirpath, start, cnum, end?True:False))
550 /* an intermediate part of the name can't be found */
551 DEBUG(5,("Intermediate not found %s\n",start));
553 /* We need to return the fact that the intermediate
554 name resolution failed. This is used to return an
555 error of ERRbadpath rather than ERRbadfile. Some
556 Windows applications depend on the difference between
563 /* just the last part of the name doesn't exist */
564 /* we may need to strupper() or strlower() it in case
565 this conversion is being used for file creation
567 /* if the filename is of mixed case then don't normalise it */
568 if (!case_preserve &&
569 (!strhasupper(start) || !strhaslower(start)))
572 /* check on the mangled stack to see if we can recover the
573 base of the filename */
574 if (is_mangled(start))
575 check_mangled_stack(start);
577 DEBUG(5,("New file %s\n",start));
581 /* restore the rest of the string */
584 strcpy(start+strlen(start)+1,rest);
585 end = start + strlen(start);
589 /* add to the dirpath that we have resolved so far */
590 if (*dirpath) strcat(dirpath,"/");
591 strcat(dirpath,start);
593 /* restore the / that we wiped out earlier */
597 /* the name has been resolved */
598 DEBUG(5,("conversion finished %s\n",name));
603 /****************************************************************************
604 normalise for DOS usage
605 ****************************************************************************/
606 static void disk_norm(int *bsize,int *dfree,int *dsize)
608 /* check if the disk is beyond the max disk size */
609 int maxdisksize = lp_maxdisksize();
611 /* convert to blocks - and don't overflow */
612 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
613 if (*dsize > maxdisksize) *dsize = maxdisksize;
614 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
619 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
624 if (*bsize > WORDMAX )
627 if (*dsize > WORDMAX)
629 if (*dfree > WORDMAX)
636 /****************************************************************************
637 return number of 1K blocks available on a path and total number
638 ****************************************************************************/
639 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
641 char *df_command = lp_dfree_command();
662 /* possibly use system() to get the result */
663 if (df_command && *df_command)
669 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
670 sprintf(syscmd,"%s %s",df_command,path);
671 standard_sub_basic(syscmd);
673 ret = smbrun(syscmd,outfile,False);
674 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
677 FILE *f = fopen(outfile,"r");
683 fscanf(f,"%d %d %d",dsize,dfree,bsize);
687 DEBUG(0,("Can't open %s\n",outfile));
691 disk_norm(bsize,dfree,dsize);
692 dfree_retval = ((*bsize)/1024)*(*dfree);
694 /* Ensure we return the min value between the users quota and
695 what's free on the disk. Thanks to Albrecht Gebhardt
696 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
698 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
700 disk_norm(&bsizeq, &dfreeq, &dsizeq);
701 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
702 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
703 dfree_retval : dfreeq_retval ;
704 /* maybe dfree and dfreeq are calculated using different bsizes
705 so convert dfree from bsize into bsizeq */
706 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
707 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
712 return(dfree_retval);
716 DEBUG(1,("Warning - no statfs function\n"));
720 if (statfs(path,&fs,sizeof(fs),0) != 0)
723 if (statvfs(path, &fs))
726 if (statfs(path,&fs,sizeof(fs)) == -1)
728 if (statfs(path,&fs) == -1)
730 #endif /* USE_STATVFS */
733 DEBUG(3,("dfree call failed code errno=%d\n",errno));
737 return(((*bsize)/1024)*(*dfree));
742 *dfree = fs.fd_req.bfree;
743 *dsize = fs.fd_req.btot;
746 *bsize = fs.f_frsize;
749 /* eg: osf1 has f_fsize = fundamental filesystem block size,
750 f_bsize = optimal transfer block size (MX: 94-04-19) */
755 #endif /* USE_STATVFS */
760 *dfree = fs.f_bavail;
762 *dsize = fs.f_blocks;
765 #if defined(SCO) || defined(ISC) || defined(MIPS)
769 /* handle rediculous bsize values - some OSes are broken */
770 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
772 disk_norm(bsize,dfree,dsize);
778 DEBUG(0,("dfree seems to be broken on your system\n"));
779 *dsize = 20*1024*1024/(*bsize);
780 *dfree = MAX(1,*dfree);
782 dfree_retval = ((*bsize)/1024)*(*dfree);
784 /* Ensure we return the min value between the users quota and
785 what's free on the disk. Thanks to Albrecht Gebhardt
786 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
788 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
790 disk_norm(&bsizeq, &dfreeq, &dsizeq);
791 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
792 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
793 dfree_retval : dfreeq_retval ;
794 /* maybe dfree and dfreeq are calculated using different bsizes
795 so convert dfree from bsize into bsizeq */
796 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
797 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
802 return(dfree_retval);
807 /****************************************************************************
808 wrap it to get filenames right
809 ****************************************************************************/
810 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
812 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
817 /****************************************************************************
818 check a filename - possibly caling reducename
820 This is called by every routine before it allows an operation on a filename.
821 It does any final confirmation necessary to ensure that the filename is
822 a valid one for the user to access.
823 ****************************************************************************/
824 BOOL check_name(char *name,int cnum)
830 if( IS_VETO_PATH(cnum, name))
832 DEBUG(5,("file path name %s vetoed\n",name));
836 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
838 /* Check if we are allowing users to follow symlinks */
839 /* Patch from David Clerc <David.Clerc@cui.unige.ch>
840 University of Geneva */
842 if (!lp_symlinks(SNUM(cnum)))
845 if ( (sys_lstat(name,&statbuf) != -1) &&
846 (S_ISLNK(statbuf.st_mode)) )
848 DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
854 DEBUG(5,("check_name on %s failed\n",name));
859 /****************************************************************************
860 check a filename - possibly caling reducename
861 ****************************************************************************/
862 static void check_for_pipe(char *fname)
864 /* special case of pipe opens */
868 if (strstr(s,"pipe/"))
870 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
871 unix_ERR_class = ERRSRV;
872 unix_ERR_code = ERRaccess;
876 /****************************************************************************
877 fd support routines - attempt to do a sys_open
878 ****************************************************************************/
880 int fd_attempt_open(char *fname, int flags, int mode)
882 int fd = sys_open(fname,flags,mode);
884 /* Fix for files ending in '.' */
885 if((fd == -1) && (errno == ENOENT) &&
886 (strchr(fname,'.')==NULL))
889 fd = sys_open(fname,flags,mode);
892 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
893 if ((fd == -1) && (errno == ENAMETOOLONG))
896 char *p = strrchr(fname, '/');
898 if (p == fname) /* name is "/xxx" */
900 max_len = pathconf("/", _PC_NAME_MAX);
903 else if ((p == NULL) || (p == fname))
906 max_len = pathconf(".", _PC_NAME_MAX);
911 max_len = pathconf(fname, _PC_NAME_MAX);
915 if (strlen(p) > max_len)
917 char tmp = p[max_len];
920 if ((fd = sys_open(fname,flags,mode)) == -1)
928 /****************************************************************************
929 fd support routines - attempt to find an already open file by dev
930 and inode - increments the ref_count of the returned file_fd_struct *.
931 ****************************************************************************/
932 file_fd_struct *fd_get_already_open(struct stat *sbuf)
935 file_fd_struct *fd_ptr;
940 for(i = 0; i <= max_file_fd_used; i++) {
942 if((fd_ptr->ref_count > 0) &&
943 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
944 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
947 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
948 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
955 /****************************************************************************
956 fd support routines - attempt to find a empty slot in the FileFd array.
957 Increments the ref_count of the returned entry.
958 ****************************************************************************/
959 file_fd_struct *fd_get_new()
962 file_fd_struct *fd_ptr;
964 for(i = 0; i < MAX_OPEN_FILES; i++) {
966 if(fd_ptr->ref_count == 0) {
967 fd_ptr->dev = (uint32)-1;
968 fd_ptr->inode = (uint32)-1;
970 fd_ptr->fd_readonly = -1;
971 fd_ptr->fd_writeonly = -1;
972 fd_ptr->real_open_flags = -1;
974 /* Increment max used counter if neccessary, cuts down
975 on search time when re-using */
976 if(i > max_file_fd_used)
977 max_file_fd_used = i;
978 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
979 i, fd_ptr->dev, fd_ptr->inode));
983 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
988 /****************************************************************************
989 fd support routines - attempt to re-open an already open fd as O_RDWR.
990 Save the already open fd (we cannot close due to POSIX file locking braindamage.
991 ****************************************************************************/
993 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
995 int fd = sys_open( fname, O_RDWR, mode);
1000 if(fd_ptr->real_open_flags == O_RDONLY)
1001 fd_ptr->fd_readonly = fd_ptr->fd;
1002 if(fd_ptr->real_open_flags == O_WRONLY)
1003 fd_ptr->fd_writeonly = fd_ptr->fd;
1006 fd_ptr->real_open_flags = O_RDWR;
1009 /****************************************************************************
1010 fd support routines - attempt to close the file referenced by this fd.
1011 Decrements the ref_count and returns it.
1012 ****************************************************************************/
1013 int fd_attempt_close(file_fd_struct *fd_ptr)
1015 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
1016 fd_ptr - &FileFd[0],
1017 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
1018 fd_ptr->real_open_flags,
1019 fd_ptr->ref_count));
1020 if(fd_ptr->ref_count > 0) {
1021 fd_ptr->ref_count--;
1022 if(fd_ptr->ref_count == 0) {
1023 if(fd_ptr->fd != -1)
1025 if(fd_ptr->fd_readonly != -1)
1026 close(fd_ptr->fd_readonly);
1027 if(fd_ptr->fd_writeonly != -1)
1028 close(fd_ptr->fd_writeonly);
1030 fd_ptr->fd_readonly = -1;
1031 fd_ptr->fd_writeonly = -1;
1032 fd_ptr->real_open_flags = -1;
1033 fd_ptr->dev = (uint32)-1;
1034 fd_ptr->inode = (uint32)-1;
1037 return fd_ptr->ref_count;
1040 /****************************************************************************
1042 ****************************************************************************/
1043 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1045 extern struct current_user current_user;
1047 struct stat statbuf;
1048 file_fd_struct *fd_ptr;
1050 Files[fnum].open = False;
1051 Files[fnum].fd_ptr = 0;
1054 strcpy(fname,fname1);
1056 /* check permissions */
1057 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1059 DEBUG(3,("Permission denied opening %s\n",fname));
1060 check_for_pipe(fname);
1064 /* this handles a bug in Win95 - it doesn't say to create the file when it
1066 if (Connections[cnum].printer)
1070 if (flags == O_WRONLY)
1071 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1074 #if UTIME_WORKAROUND
1075 /* XXXX - is this OK?? */
1076 /* this works around a utime bug but can cause other problems */
1077 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1082 * Ensure we have a valid struct stat so we can search the
1086 if(stat(fname, &statbuf) < 0) {
1087 if(errno != ENOENT) {
1088 DEBUG(3,("Error doing stat on file %s (%s)\n",
1089 fname,strerror(errno)));
1091 check_for_pipe(fname);
1101 * Check to see if we have this file already
1102 * open. If we do, just use the already open fd and increment the
1103 * reference count (fd_get_already_open increments the ref_count).
1105 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1107 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1109 /* File was already open. */
1110 if((flags & O_CREAT) && (flags & O_EXCL)) {
1111 fd_ptr->ref_count--;
1117 * If not opened O_RDWR try
1118 * and do that here - a chmod may have been done
1119 * between the last open and now.
1121 if(fd_ptr->real_open_flags != O_RDWR)
1122 fd_attempt_reopen(fname, mode, fd_ptr);
1125 * Ensure that if we wanted write access
1126 * it has been opened for write, and if we wanted read it
1127 * was open for read.
1129 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1130 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1131 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1132 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1133 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1134 check_for_pipe(fname);
1135 fd_ptr->ref_count--;
1141 /* We need to allocate a new file_fd_struct (this increments the
1143 if((fd_ptr = fd_get_new()) == 0)
1146 * Whatever the requested flags, attempt read/write access,
1147 * as we don't know what flags future file opens may require.
1148 * If this fails, try again with the required flags.
1149 * Even if we open read/write when only read access was
1150 * requested the setting of the can_write flag in
1151 * the file_struct will protect us from errant
1152 * write requests. We never need to worry about O_APPEND
1153 * as this is not set anywhere in Samba.
1155 fd_ptr->real_open_flags = O_RDWR;
1156 /* Set the flags as needed without the read/write modes. */
1157 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1158 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1160 * On some systems opening a file for R/W access on a read only
1161 * filesystems sets errno to EROFS.
1164 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1165 #else /* No EROFS */
1166 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1168 if(flags & O_WRONLY) {
1169 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1170 fd_ptr->real_open_flags = O_WRONLY;
1172 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1173 fd_ptr->real_open_flags = O_RDONLY;
1178 if ((fd_ptr->fd >=0) &&
1179 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1183 strcpy(dname,fname);
1184 p = strrchr(dname,'/');
1186 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1187 lp_minprintspace(SNUM(cnum))) {
1188 fd_attempt_close(fd_ptr);
1189 Files[fnum].fd_ptr = 0;
1190 if(fd_ptr->ref_count == 0)
1199 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1200 fname,strerror(errno),flags));
1201 /* Ensure the ref_count is decremented. */
1202 fd_attempt_close(fd_ptr);
1203 check_for_pipe(fname);
1207 if (fd_ptr->fd >= 0)
1211 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1212 /* Error - backout !! */
1213 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1214 fd_ptr->fd, fname,strerror(errno)));
1215 /* Ensure the ref_count is decremented. */
1216 fd_attempt_close(fd_ptr);
1221 /* Set the correct entries in fd_ptr. */
1222 fd_ptr->dev = (uint32)sbuf->st_dev;
1223 fd_ptr->inode = (uint32)sbuf->st_ino;
1225 Files[fnum].fd_ptr = fd_ptr;
1226 Connections[cnum].num_files_open++;
1227 Files[fnum].mode = sbuf->st_mode;
1228 GetTimeOfDay(&Files[fnum].open_time);
1229 Files[fnum].uid = current_user.id;
1230 Files[fnum].size = 0;
1231 Files[fnum].pos = -1;
1232 Files[fnum].open = True;
1233 Files[fnum].mmap_ptr = NULL;
1234 Files[fnum].mmap_size = 0;
1235 Files[fnum].can_lock = True;
1236 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1237 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1238 Files[fnum].share_mode = 0;
1239 Files[fnum].print_file = Connections[cnum].printer;
1240 Files[fnum].modified = False;
1241 Files[fnum].cnum = cnum;
1242 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1243 Files[fnum].wbmpx_ptr = NULL;
1246 * If the printer is marked as postscript output a leading
1247 * file identifier to ensure the file is treated as a raw
1249 * This has a similar effect as CtrlD=0 in WIN.INI file.
1250 * tim@fsg.com 09/06/94
1252 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1253 Files[fnum].can_write)
1255 DEBUG(3,("Writing postscript line\n"));
1256 write_file(fnum,"%!\n",3);
1259 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1260 timestring(),Connections[cnum].user,fname,
1261 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1262 Connections[cnum].num_files_open,fnum));
1267 /* mmap it if read-only */
1268 if (!Files[fnum].can_write)
1270 Files[fnum].mmap_size = file_size(fname);
1271 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1272 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1274 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1276 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1277 Files[fnum].mmap_ptr = NULL;
1283 /*******************************************************************
1285 ********************************************************************/
1286 void sync_file(int fnum)
1289 fsync(Files[fnum].fd_ptr->fd);
1293 /****************************************************************************
1294 run a file if it is a magic script
1295 ****************************************************************************/
1296 static void check_magic(int fnum,int cnum)
1298 if (!*lp_magicscript(SNUM(cnum)))
1301 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1305 if (!(p = strrchr(Files[fnum].name,'/')))
1306 p = Files[fnum].name;
1310 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1316 pstring magic_output;
1318 strcpy(fname,Files[fnum].name);
1320 if (*lp_magicoutput(SNUM(cnum)))
1321 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1323 sprintf(magic_output,"%s.out",fname);
1326 ret = smbrun(fname,magic_output,False);
1327 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1333 /****************************************************************************
1334 close a file - possibly invalidating the read prediction
1335 ****************************************************************************/
1336 void close_file(int fnum)
1338 files_struct *fs_p = &Files[fnum];
1339 int cnum = fs_p->cnum;
1340 uint32 dev = fs_p->fd_ptr->dev;
1341 uint32 inode = fs_p->fd_ptr->inode;
1342 share_lock_token token;
1344 invalidate_read_prediction(fs_p->fd_ptr->fd);
1346 Connections[cnum].num_files_open--;
1349 free((char *)fs_p->wbmpx_ptr);
1350 fs_p->wbmpx_ptr = NULL;
1356 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1357 fs_p->mmap_ptr = NULL;
1361 if (lp_share_modes(SNUM(cnum)))
1363 lock_share_entry( cnum, dev, inode, &token);
1364 del_share_mode(token, fnum);
1367 fd_attempt_close(fs_p->fd_ptr);
1369 if (lp_share_modes(SNUM(cnum)))
1370 unlock_share_entry( cnum, dev, inode, token);
1372 /* NT uses smbclose to start a print - weird */
1373 if (fs_p->print_file)
1376 /* check for magic scripts */
1377 check_magic(fnum,cnum);
1379 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1380 timestring(),Connections[cnum].user,fs_p->name,
1381 Connections[cnum].num_files_open));
1384 enum {AFAIL,AREAD,AWRITE,AALL};
1386 /*******************************************************************
1387 reproduce the share mode access table
1388 ********************************************************************/
1389 static int access_table(int new_deny,int old_deny,int old_mode,
1390 int share_pid,char *fname)
1392 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1394 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1395 if (old_deny == new_deny && share_pid == getpid())
1398 if (old_mode == 0) return(AREAD);
1400 /* the new smbpub.zip spec says that if the file extension is
1401 .com, .dll, .exe or .sym then allow the open. I will force
1402 it to read-only as this seems sensible although the spec is
1403 a little unclear on this. */
1404 if ((fname = strrchr(fname,'.'))) {
1405 if (strequal(fname,".com") ||
1406 strequal(fname,".dll") ||
1407 strequal(fname,".exe") ||
1408 strequal(fname,".sym"))
1418 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1419 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1420 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1423 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1424 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1425 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1428 if (old_deny==DENY_WRITE) return(AREAD);
1429 if (old_deny==DENY_READ) return(AWRITE);
1430 if (old_deny==DENY_NONE) return(AALL);
1436 /*******************************************************************
1437 check if the share mode on a file allows it to be deleted or unlinked
1438 return True if sharing doesn't prevent the operation
1439 ********************************************************************/
1440 BOOL check_file_sharing(int cnum,char *fname)
1444 min_share_mode_entry *old_shares = 0;
1445 int num_share_modes;
1447 share_lock_token token;
1450 if(!lp_share_modes(SNUM(cnum)))
1453 if (stat(fname,&sbuf) == -1) return(True);
1455 lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1456 num_share_modes = get_share_modes(cnum, token,
1457 (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1459 for( i = 0; i < num_share_modes; i++)
1461 if (old_shares[i].share_mode != DENY_DOS)
1464 if(old_shares[i].pid != pid)
1468 /* XXXX exactly what share mode combinations should be allowed for
1469 deleting/renaming? */
1470 /* If we got here then either there were no share modes or
1471 all share modes were DENY_DOS and the pid == getpid() */
1476 unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1477 if(old_shares != NULL)
1478 free((char *)old_shares);
1482 /****************************************************************************
1484 Helper for open_file_shared.
1485 Truncate a file after checking locking; close file if locked.
1486 **************************************************************************/
1487 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
1490 if (Files[fnum].can_write){
1491 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1492 /* If share modes are in force for this connection we
1493 have the share entry locked. Unlock it before closing. */
1494 if (*share_locked && lp_share_modes(SNUM(cnum)))
1495 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1496 Files[fnum].fd_ptr->inode, token);
1498 /* Share mode no longer locked. */
1499 *share_locked = False;
1501 unix_ERR_class = ERRDOS;
1502 unix_ERR_code = ERRlock;
1505 ftruncate(Files[fnum].fd_ptr->fd,0);
1510 /****************************************************************************
1511 open a file with a share mode
1512 ****************************************************************************/
1513 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1514 int mode,int *Access,int *action)
1516 files_struct *fs_p = &Files[fnum];
1519 int deny_mode = (share_mode>>4)&7;
1521 BOOL file_existed = file_exist(fname,&sbuf);
1522 BOOL share_locked = False;
1523 BOOL fcbopen = False;
1524 share_lock_token token;
1531 /* this is for OS/2 EAs - try and say we don't support them */
1532 if (strstr(fname,".+,;=[]."))
1534 unix_ERR_class = ERRDOS;
1535 /* OS/2 Workplace shell fix may be main code stream in a later release. */
1537 unix_ERR_code = ERRcannotopen;
1538 #else /* OS2_WPS_FIX */
1539 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1540 #endif /* OS2_WPS_FIX */
1545 if ((ofun & 0x3) == 0 && file_existed)
1553 if ((ofun & 0x3) == 2)
1556 /* note that we ignore the append flag as
1557 append does not mean the same thing under dos and unix */
1559 switch (share_mode&0xF)
1576 if (flags != O_RDONLY && file_existed &&
1577 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1587 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1589 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1594 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1596 if (lp_share_modes(SNUM(cnum)))
1600 min_share_mode_entry *old_shares = 0;
1605 dev = (uint32)sbuf.st_dev;
1606 inode = (uint32)sbuf.st_ino;
1607 lock_share_entry(cnum, dev, inode, &token);
1608 share_locked = True;
1609 num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1612 for(i = 0; i < num_shares; i++)
1614 /* someone else has a share lock on it, check to see
1616 int old_open_mode = old_shares[i].share_mode &0xF;
1617 int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1619 if (old_deny_mode > 4 || old_open_mode > 2)
1621 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1622 deny_mode,old_deny_mode,old_open_mode,fname));
1623 free((char *)old_shares);
1625 unlock_share_entry(cnum, dev, inode, token);
1627 unix_ERR_class = ERRDOS;
1628 unix_ERR_code = ERRbadshare;
1633 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1634 old_shares[i].pid,fname);
1636 if ((access_allowed == AFAIL) ||
1637 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1638 (access_allowed == AREAD && flags == O_WRONLY) ||
1639 (access_allowed == AWRITE && flags == O_RDONLY))
1641 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1642 deny_mode,old_deny_mode,old_open_mode,
1643 old_shares[i].pid,fname,
1645 free((char *)old_shares);
1647 unlock_share_entry(cnum, dev, inode, token);
1649 unix_ERR_class = ERRDOS;
1650 unix_ERR_code = ERRbadshare;
1654 if (access_allowed == AREAD)
1657 if (access_allowed == AWRITE)
1662 free((char *)old_shares);
1665 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1666 flags,flags2,mode));
1668 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1669 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1672 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1679 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1681 /* We created the file - thus we must now lock the share entry before creating it. */
1682 dev = fs_p->fd_ptr->dev;
1683 inode = fs_p->fd_ptr->inode;
1684 lock_share_entry(cnum, dev, inode, &token);
1685 share_locked = True;
1701 fs_p->share_mode = (deny_mode<<4) | open_mode;
1704 (*Access) = open_mode;
1708 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1709 if (!file_existed) *action = 2;
1710 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1712 /* We must create the share mode entry before truncate as
1713 truncate can fail due to locking and have to close the
1714 file (which expects the share_mode_entry to be there).
1716 if (lp_share_modes(SNUM(cnum)))
1717 set_share_mode(token, fnum);
1719 if ((flags2&O_TRUNC) && file_existed)
1720 truncate_unless_locked(fnum,cnum,token,&share_locked);
1723 if (share_locked && lp_share_modes(SNUM(cnum)))
1724 unlock_share_entry( cnum, dev, inode, token);
1727 /****************************************************************************
1728 seek a file. Try to avoid the seek if possible
1729 ****************************************************************************/
1730 int seek_file(int fnum,uint32 pos)
1733 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1736 Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET)
1738 return(Files[fnum].pos);
1741 /****************************************************************************
1743 ****************************************************************************/
1744 int read_file(int fnum,char *data,uint32 pos,int n)
1748 if (!Files[fnum].can_write)
1750 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1758 if (Files[fnum].mmap_ptr)
1760 int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
1763 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1775 if (seek_file(fnum,pos) != pos)
1777 DEBUG(3,("Failed to seek to %d\n",pos));
1782 readret = read(Files[fnum].fd_ptr->fd,data,n);
1783 if (readret > 0) ret += readret;
1790 /****************************************************************************
1792 ****************************************************************************/
1793 int write_file(int fnum,char *data,int n)
1795 if (!Files[fnum].can_write) {
1800 if (!Files[fnum].modified) {
1802 Files[fnum].modified = True;
1803 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1804 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1805 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1806 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1811 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1815 /****************************************************************************
1816 load parameters specific to a connection/service
1817 ****************************************************************************/
1818 BOOL become_service(int cnum,BOOL do_chdir)
1820 extern char magic_char;
1821 static int last_cnum = -1;
1824 if (!OPEN_CNUM(cnum))
1830 Connections[cnum].lastused = smb_last_time;
1835 ChDir(Connections[cnum].connectpath) != 0 &&
1836 ChDir(Connections[cnum].origpath) != 0)
1838 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1839 Connections[cnum].connectpath,cnum));
1843 if (cnum == last_cnum)
1848 case_default = lp_defaultcase(snum);
1849 case_preserve = lp_preservecase(snum);
1850 short_case_preserve = lp_shortpreservecase(snum);
1851 case_mangle = lp_casemangle(snum);
1852 case_sensitive = lp_casesensitive(snum);
1853 magic_char = lp_magicchar(snum);
1854 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1859 /****************************************************************************
1860 find a service entry
1861 ****************************************************************************/
1862 int find_service(char *service)
1866 string_sub(service,"\\","/");
1868 iService = lp_servicenumber(service);
1870 /* now handle the special case of a home directory */
1873 char *phome_dir = get_home_dir(service);
1874 DEBUG(3,("checking for home directory %s gave %s\n",service,
1875 phome_dir?phome_dir:"(NULL)"));
1879 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1881 lp_add_home(service,iHomeService,phome_dir);
1882 iService = lp_servicenumber(service);
1887 /* If we still don't have a service, attempt to add it as a printer. */
1890 int iPrinterService;
1892 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1896 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1898 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1900 DEBUG(3,("%s is a valid printer name\n", service));
1901 DEBUG(3,("adding %s as a printer service\n", service));
1902 lp_add_printer(service,iPrinterService);
1903 iService = lp_servicenumber(service);
1905 DEBUG(0,("failed to add %s as a printer service!\n", service));
1908 DEBUG(3,("%s is not a valid printer name\n", service));
1912 /* just possibly it's a default service? */
1915 char *defservice = lp_defaultservice();
1916 if (defservice && *defservice && !strequal(defservice,service)) {
1917 iService = find_service(defservice);
1918 if (iService >= 0) {
1919 string_sub(service,"_","/");
1920 iService = lp_add_service(service,iService);
1926 if (!VALID_SNUM(iService))
1928 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1933 DEBUG(3,("find_service() failed to find service %s\n", service));
1939 /****************************************************************************
1940 create an error packet from a cached error.
1941 ****************************************************************************/
1942 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1944 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1946 int32 eclass = wbmpx->wr_errclass;
1947 int32 err = wbmpx->wr_error;
1949 /* We can now delete the auxiliary struct */
1950 free((char *)wbmpx);
1951 Files[fnum].wbmpx_ptr = NULL;
1952 return error_packet(inbuf,outbuf,eclass,err,line);
1961 } unix_smb_errmap[] =
1963 {EPERM,ERRDOS,ERRnoaccess},
1964 {EACCES,ERRDOS,ERRnoaccess},
1965 {ENOENT,ERRDOS,ERRbadfile},
1966 {ENOTDIR,ERRDOS,ERRbaddirectory},
1967 {EIO,ERRHRD,ERRgeneral},
1968 {EBADF,ERRSRV,ERRsrverror},
1969 {EINVAL,ERRSRV,ERRsrverror},
1970 {EEXIST,ERRDOS,ERRfilexists},
1971 {ENFILE,ERRDOS,ERRnofids},
1972 {EMFILE,ERRDOS,ERRnofids},
1973 {ENOSPC,ERRHRD,ERRdiskfull},
1975 {EDQUOT,ERRHRD,ERRdiskfull},
1978 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1981 {EXDEV,ERRDOS,ERRdiffdevice},
1983 {EROFS,ERRHRD,ERRnowrite},
1987 /* Mapping for old clients. */
1994 enum remote_arch_types valid_ra_type;
1995 } old_client_errmap[] =
1997 {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT},
2001 /****************************************************************************
2002 create an error packet from errno
2003 ****************************************************************************/
2004 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
2006 int eclass=def_class;
2010 if (unix_ERR_class != SUCCESS)
2012 eclass = unix_ERR_class;
2013 ecode = unix_ERR_code;
2014 unix_ERR_class = SUCCESS;
2019 while (unix_smb_errmap[i].smbclass != 0)
2021 if (unix_smb_errmap[i].unixerror == errno)
2023 eclass = unix_smb_errmap[i].smbclass;
2024 ecode = unix_smb_errmap[i].smbcode;
2031 /* Make sure we don't return error codes that old
2032 clients don't understand. */
2034 /* JRA - unfortunately, WinNT needs some error codes
2035 for apps to work correctly, Win95 will break if
2036 these error codes are returned. But they both
2037 negotiate the *same* protocol. So we need to use
2038 the revolting 'remote_arch' enum to tie break.
2040 There must be a better way of doing this...
2043 for(i = 0; old_client_errmap[i].new_smb_error != 0; i++)
2045 if(((Protocol < old_client_errmap[i].protocol_level) ||
2046 (old_client_errmap[i].valid_ra_type != get_remote_arch())) &&
2047 (old_client_errmap[i].new_smb_error == ecode))
2049 ecode = old_client_errmap[i].old_smb_error;
2054 return(error_packet(inbuf,outbuf,eclass,ecode,line));
2058 /****************************************************************************
2059 create an error packet. Normally called using the ERROR() macro
2060 ****************************************************************************/
2061 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2063 int outsize = set_message(outbuf,0,0,True);
2065 cmd = CVAL(inbuf,smb_com);
2067 CVAL(outbuf,smb_rcls) = error_class;
2068 SSVAL(outbuf,smb_err,error_code);
2070 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2073 (int)CVAL(inbuf,smb_com),
2074 smb_fn_name(CVAL(inbuf,smb_com)),
2079 DEBUG(3,("error string = %s\n",strerror(errno)));
2085 #ifndef SIGCLD_IGNORE
2086 /****************************************************************************
2087 this prevents zombie child processes
2088 ****************************************************************************/
2089 static int sig_cld()
2091 static int depth = 0;
2094 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2100 BlockSignals(True,SIGCLD);
2101 DEBUG(5,("got SIGCLD\n"));
2104 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2108 /* Stevens, Adv. Unix Prog. says that on system V you must call
2109 wait before reinstalling the signal handler, because the kernel
2110 calls the handler from within the signal-call when there is a
2111 child that has exited. This would lead to an infinite recursion
2112 if done vice versa. */
2114 #ifndef DONT_REINSTALL_SIG
2115 #ifdef SIGCLD_IGNORE
2116 signal(SIGCLD, SIG_IGN);
2118 signal(SIGCLD, SIGNAL_CAST sig_cld);
2123 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2126 BlockSignals(False,SIGCLD);
2131 /****************************************************************************
2132 this is called when the client exits abruptly
2133 **************************************************************************/
2134 static int sig_pipe()
2136 extern int password_client;
2137 BlockSignals(True,SIGPIPE);
2139 if (password_client != -1) {
2140 DEBUG(3,("lost connection to password server\n"));
2141 close(password_client);
2142 password_client = -1;
2143 #ifndef DONT_REINSTALL_SIG
2144 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2146 BlockSignals(False,SIGPIPE);
2150 exit_server("Got sigpipe\n");
2154 /****************************************************************************
2155 open the socket communication
2156 ****************************************************************************/
2157 static BOOL open_sockets(BOOL is_daemon,int port)
2164 struct sockaddr addr;
2165 int in_addrlen = sizeof(addr);
2168 #ifdef SIGCLD_IGNORE
2169 signal(SIGCLD, SIG_IGN);
2171 signal(SIGCLD, SIGNAL_CAST sig_cld);
2174 /* open an incoming socket */
2175 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2179 /* ready to listen */
2180 if (listen(s, 5) == -1)
2182 DEBUG(0,("listen: %s\n",strerror(errno)));
2190 /* now accept incoming connections - forking a new process
2191 for each incoming connection */
2192 DEBUG(2,("waiting for a connection\n"));
2195 Client = accept(s,&addr,&in_addrlen);
2197 if (Client == -1 && errno == EINTR)
2202 DEBUG(0,("accept: %s\n",strerror(errno)));
2206 #ifdef NO_FORK_DEBUG
2207 #ifndef NO_SIGNAL_TEST
2208 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2209 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2213 if (Client != -1 && fork()==0)
2215 /* Child code ... */
2216 #ifndef NO_SIGNAL_TEST
2217 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2218 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2220 /* close the listening socket */
2223 /* close our standard file descriptors */
2227 set_socket_options(Client,"SO_KEEPALIVE");
2228 set_socket_options(Client,user_socket_options);
2230 /* Reset global variables in util.c so that
2231 client substitutions will be done correctly
2234 reset_globals_after_fork();
2237 close(Client); /* The parent doesn't need this socket */
2243 /* We will abort gracefully when the client or remote system
2245 #ifndef NO_SIGNAL_TEST
2246 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2250 /* close our standard file descriptors */
2253 set_socket_options(Client,"SO_KEEPALIVE");
2254 set_socket_options(Client,user_socket_options);
2261 /****************************************************************************
2262 check if a snum is in use
2263 ****************************************************************************/
2264 BOOL snum_used(int snum)
2267 for (i=0;i<MAX_CONNECTIONS;i++)
2268 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2273 /****************************************************************************
2274 reload the services file
2275 **************************************************************************/
2276 BOOL reload_services(BOOL test)
2283 strcpy(fname,lp_configfile());
2284 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2286 strcpy(servicesf,fname);
2293 if (test && !lp_file_list_changed())
2296 lp_killunused(snum_used);
2298 ret = lp_load(servicesf,False);
2300 /* perhaps the config filename is now set */
2302 reload_services(True);
2311 set_socket_options(Client,"SO_KEEPALIVE");
2312 set_socket_options(Client,user_socket_options);
2316 create_mangled_stack(lp_mangledstack());
2318 /* this forces service parameters to be flushed */
2319 become_service(-1,True);
2326 /****************************************************************************
2327 this prevents zombie child processes
2328 ****************************************************************************/
2329 static int sig_hup()
2331 BlockSignals(True,SIGHUP);
2332 DEBUG(0,("Got SIGHUP\n"));
2333 reload_services(False);
2334 #ifndef DONT_REINSTALL_SIG
2335 signal(SIGHUP,SIGNAL_CAST sig_hup);
2337 BlockSignals(False,SIGHUP);
2341 /****************************************************************************
2342 Setup the groups a user belongs to.
2343 ****************************************************************************/
2344 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2345 int **p_igroups, gid_t **p_groups)
2347 if (-1 == initgroups(user,gid))
2351 DEBUG(0,("Unable to initgroups!\n"));
2352 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2353 DEBUG(0,("This is probably a problem with the account %s\n",user));
2361 ngroups = getgroups(0,&grp);
2364 igroups = (int *)malloc(sizeof(int)*ngroups);
2365 for (i=0;i<ngroups;i++)
2366 igroups[i] = 0x42424242;
2367 ngroups = getgroups(ngroups,(gid_t *)igroups);
2369 if (igroups[0] == 0x42424242)
2372 *p_ngroups = ngroups;
2374 /* The following bit of code is very strange. It is due to the
2375 fact that some OSes use int* and some use gid_t* for
2376 getgroups, and some (like SunOS) use both, one in prototypes,
2377 and one in man pages and the actual code. Thus we detect it
2378 dynamically using some very ugly code */
2381 /* does getgroups return ints or gid_t ?? */
2382 static BOOL groups_use_ints = True;
2384 if (groups_use_ints &&
2386 SVAL(igroups,2) == 0x4242)
2387 groups_use_ints = False;
2389 for (i=0;groups_use_ints && i<ngroups;i++)
2390 if (igroups[i] == 0x42424242)
2391 groups_use_ints = False;
2393 if (groups_use_ints)
2395 *p_igroups = igroups;
2396 *p_groups = (gid_t *)igroups;
2400 gid_t *groups = (gid_t *)igroups;
2401 igroups = (int *)malloc(sizeof(int)*ngroups);
2402 for (i=0;i<ngroups;i++)
2403 igroups[i] = groups[i];
2404 *p_igroups = igroups;
2405 *p_groups = (gid_t *)groups;
2408 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2409 for (i=0;i<ngroups;i++)
2410 DEBUG(3,("%d ",igroups[i]));
2416 /****************************************************************************
2417 make a connection to a service
2418 ****************************************************************************/
2419 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2423 struct passwd *pass = NULL;
2424 connection_struct *pcon;
2427 static BOOL first_connection = True;
2431 snum = find_service(service);
2434 if (strequal(service,"IPC$"))
2436 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2440 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2444 if (strequal(service,HOMES_NAME))
2446 if (*user && Get_Pwnam(user,True))
2447 return(make_connection(user,user,password,pwlen,dev,vuid));
2449 if (validated_username(vuid))
2451 strcpy(user,validated_username(vuid));
2452 return(make_connection(user,user,password,pwlen,dev,vuid));
2456 if (!lp_snum_ok(snum) || !check_access(snum)) {
2460 /* you can only connect to the IPC$ service as an ipc device */
2461 if (strequal(service,"IPC$"))
2464 if (*dev == '?' || !*dev)
2466 if (lp_print_ok(snum))
2467 strcpy(dev,"LPT1:");
2472 /* if the request is as a printer and you can't print then refuse */
2474 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2475 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2479 /* lowercase the user name */
2482 /* add it as a possible user name */
2483 add_session_user(service);
2485 /* shall we let them in? */
2486 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2488 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2492 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2495 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2499 pcon = &Connections[cnum];
2500 bzero((char *)pcon,sizeof(*pcon));
2502 /* find out some info about the user */
2503 pass = Get_Pwnam(user,True);
2507 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2511 pcon->read_only = lp_readonly(snum);
2515 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2516 string_sub(list,"%S",service);
2518 if (user_in_list(user,list))
2519 pcon->read_only = True;
2521 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2522 string_sub(list,"%S",service);
2524 if (user_in_list(user,list))
2525 pcon->read_only = False;
2528 /* admin user check */
2529 if (user_in_list(user,lp_admin_users(snum)) &&
2532 pcon->admin_user = True;
2533 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2536 pcon->admin_user = False;
2538 pcon->force_user = force;
2540 pcon->uid = pass->pw_uid;
2541 pcon->gid = pass->pw_gid;
2542 pcon->num_files_open = 0;
2543 pcon->lastused = time(NULL);
2544 pcon->service = snum;
2546 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2547 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2548 pcon->dirptr = NULL;
2549 pcon->veto_list = NULL;
2550 pcon->hide_list = NULL;
2551 string_set(&pcon->dirpath,"");
2552 string_set(&pcon->user,user);
2555 if (*lp_force_group(snum))
2560 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2561 /* default service may be a group name */
2562 string_sub(gname,"%S",service);
2563 gptr = (struct group *)getgrnam(gname);
2567 pcon->gid = gptr->gr_gid;
2568 DEBUG(3,("Forced group %s\n",gname));
2571 DEBUG(1,("Couldn't find group %s\n",gname));
2575 if (*lp_force_user(snum))
2577 struct passwd *pass2;
2579 strcpy(fuser,lp_force_user(snum));
2580 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2583 pcon->uid = pass2->pw_uid;
2584 string_set(&pcon->user,fuser);
2586 pcon->force_user = True;
2587 DEBUG(3,("Forced user %s\n",fuser));
2590 DEBUG(1,("Couldn't find user %s\n",fuser));
2595 strcpy(s,lp_pathname(snum));
2596 standard_sub(cnum,s);
2597 string_set(&pcon->connectpath,s);
2598 DEBUG(3,("Connect path is %s\n",s));
2601 /* groups stuff added by ih */
2603 pcon->groups = NULL;
2607 /* Find all the groups this uid is in and store them. Used by become_user() */
2608 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2610 /* check number of connections */
2611 if (!claim_connection(cnum,
2612 lp_servicename(SNUM(cnum)),
2613 lp_max_connections(SNUM(cnum)),False))
2615 DEBUG(1,("too many connections - rejected\n"));
2619 if (lp_status(SNUM(cnum)))
2620 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2622 first_connection = False;
2627 /* execute any "root preexec = " line */
2628 if (*lp_rootpreexec(SNUM(cnum)))
2631 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2632 standard_sub(cnum,cmd);
2633 DEBUG(5,("cmd=%s\n",cmd));
2634 smbrun(cmd,NULL,False);
2637 if (!become_user(cnum,pcon->vuid))
2639 DEBUG(0,("Can't become connected user!\n"));
2641 if (!IS_IPC(cnum)) {
2642 yield_connection(cnum,
2643 lp_servicename(SNUM(cnum)),
2644 lp_max_connections(SNUM(cnum)));
2645 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2650 if (ChDir(pcon->connectpath) != 0)
2652 DEBUG(0,("Can't change directory to %s (%s)\n",
2653 pcon->connectpath,strerror(errno)));
2656 if (!IS_IPC(cnum)) {
2657 yield_connection(cnum,
2658 lp_servicename(SNUM(cnum)),
2659 lp_max_connections(SNUM(cnum)));
2660 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2665 string_set(&pcon->origpath,pcon->connectpath);
2667 #if SOFTLINK_OPTIMISATION
2668 /* resolve any soft links early */
2671 strcpy(s,pcon->connectpath);
2673 string_set(&pcon->connectpath,s);
2674 ChDir(pcon->connectpath);
2678 num_connections_open++;
2679 add_session_user(user);
2681 /* execute any "preexec = " line */
2682 if (*lp_preexec(SNUM(cnum)))
2685 strcpy(cmd,lp_preexec(SNUM(cnum)));
2686 standard_sub(cnum,cmd);
2687 smbrun(cmd,NULL,False);
2690 /* we've finished with the sensitive stuff */
2693 /* Add veto/hide lists */
2694 if (!IS_IPC(cnum) && !IS_PRINT(cnum))
2696 set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
2697 set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
2701 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2705 lp_servicename(SNUM(cnum)),user,
2715 /****************************************************************************
2716 find first available file slot
2717 ****************************************************************************/
2718 int find_free_file(void )
2721 /* we start at 1 here for an obscure reason I can't now remember,
2722 but I think is important :-) */
2723 for (i=1;i<MAX_OPEN_FILES;i++)
2726 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2730 /****************************************************************************
2731 find first available connection slot, starting from a random position.
2732 The randomisation stops problems with the server dieing and clients
2733 thinking the server is still available.
2734 ****************************************************************************/
2735 static int find_free_connection(int hash )
2739 hash = (hash % (MAX_CONNECTIONS-2))+1;
2743 for (i=hash+1;i!=hash;)
2745 if (!Connections[i].open && Connections[i].used == used)
2747 DEBUG(3,("found free connection number %d\n",i));
2751 if (i == MAX_CONNECTIONS)
2761 DEBUG(1,("ERROR! Out of connection structures\n"));
2766 /****************************************************************************
2767 reply for the core protocol
2768 ****************************************************************************/
2769 int reply_corep(char *outbuf)
2771 int outsize = set_message(outbuf,1,0,True);
2773 Protocol = PROTOCOL_CORE;
2779 /****************************************************************************
2780 reply for the coreplus protocol
2781 ****************************************************************************/
2782 int reply_coreplus(char *outbuf)
2784 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2785 int outsize = set_message(outbuf,13,0,True);
2786 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2787 readbraw and writebraw (possibly) */
2788 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2789 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2791 Protocol = PROTOCOL_COREPLUS;
2797 /****************************************************************************
2798 reply for the lanman 1.0 protocol
2799 ****************************************************************************/
2800 int reply_lanman1(char *outbuf)
2802 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2804 BOOL doencrypt = SMBENCRYPT();
2805 time_t t = time(NULL);
2806 /* We need to save and restore this as it can be destroyed
2807 if we call another server if security=server
2808 Thanks to Paul Nelson @ Thursby for pointing this out.
2810 uint16 mid = SVAL(outbuf, smb_mid);
2812 if (lp_security()>=SEC_USER) secword |= 1;
2813 if (doencrypt) secword |= 2;
2815 set_message(outbuf,13,doencrypt?8:0,True);
2816 SSVAL(outbuf,smb_vwv1,secword);
2817 /* Create a token value and add it to the outgoing packet. */
2819 generate_next_challenge(smb_buf(outbuf));
2821 Protocol = PROTOCOL_LANMAN1;
2823 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2824 DEBUG(3,("using password server validation\n"));
2825 if (doencrypt) set_challenge(smb_buf(outbuf));
2828 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2829 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2830 SSVAL(outbuf,smb_vwv2,max_recv);
2831 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2832 SSVAL(outbuf,smb_vwv4,1);
2833 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2834 readbraw writebraw (possibly) */
2835 SIVAL(outbuf,smb_vwv6,getpid());
2836 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2838 put_dos_date(outbuf,smb_vwv8,t);
2840 return (smb_len(outbuf)+4);
2844 /****************************************************************************
2845 reply for the lanman 2.0 protocol
2846 ****************************************************************************/
2847 int reply_lanman2(char *outbuf)
2849 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2851 BOOL doencrypt = SMBENCRYPT();
2852 time_t t = time(NULL);
2853 /* We need to save and restore this as it can be destroyed
2854 if we call another server if security=server
2855 Thanks to Paul Nelson @ Thursby for pointing this out.
2857 uint16 mid = SVAL(outbuf, smb_mid);
2859 if (lp_security()>=SEC_USER) secword |= 1;
2860 if (doencrypt) secword |= 2;
2862 set_message(outbuf,13,doencrypt?8:0,True);
2863 SSVAL(outbuf,smb_vwv1,secword);
2864 /* Create a token value and add it to the outgoing packet. */
2866 generate_next_challenge(smb_buf(outbuf));
2868 SIVAL(outbuf,smb_vwv6,getpid());
2870 Protocol = PROTOCOL_LANMAN2;
2872 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2873 DEBUG(3,("using password server validation\n"));
2874 if (doencrypt) set_challenge(smb_buf(outbuf));
2877 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2878 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2879 SSVAL(outbuf,smb_vwv2,max_recv);
2880 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2881 SSVAL(outbuf,smb_vwv4,1);
2882 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2883 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2884 put_dos_date(outbuf,smb_vwv8,t);
2886 return (smb_len(outbuf)+4);
2890 /****************************************************************************
2891 reply for the nt protocol
2892 ****************************************************************************/
2893 int reply_nt1(char *outbuf)
2895 /* dual names + lock_and_read + nt SMBs + remote API calls */
2896 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2898 other valid capabilities which we may support at some time...
2899 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2900 CAP_LARGE_FILES|CAP_LARGE_READX|
2901 CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2905 BOOL doencrypt = SMBENCRYPT();
2906 time_t t = time(NULL);
2909 char challenge_len = 8;
2910 /* We need to save and restore this as it can be destroyed
2911 if we call another server if security=server
2912 Thanks to Paul Nelson @ Thursby for pointing this out.
2914 uint16 mid = SVAL(outbuf, smb_mid);
2916 if (lp_readraw() && lp_writeraw())
2918 capabilities |= CAP_RAW_MODE;
2921 if (lp_security()>=SEC_USER) secword |= 1;
2922 if (doencrypt) secword |= 2;
2924 /* decide where (if) to put the encryption challenge, and
2925 follow it with the OEM'd domain name
2927 encrypt_len = doencrypt?challenge_len:0;
2929 data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2931 data_len = encrypt_len + strlen(myworkgroup) + 1;
2934 set_message(outbuf,17,data_len,True);
2937 /* put the OEM'd domain name */
2938 PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2940 strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2943 CVAL(outbuf,smb_vwv1) = secword;
2944 /* Create a token value and add it to the outgoing packet. */
2947 generate_next_challenge(smb_buf(outbuf));
2949 /* Tell the nt machine how long the challenge is. */
2950 SSVALS(outbuf,smb_vwv16+1,challenge_len);
2953 Protocol = PROTOCOL_NT1;
2955 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2956 DEBUG(3,("using password server validation\n"));
2957 if (doencrypt) set_challenge(smb_buf(outbuf));
2960 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2961 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2962 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2963 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2964 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2965 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2966 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2967 put_long_date(outbuf+smb_vwv11+1,t);
2968 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2969 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2971 return (smb_len(outbuf)+4);
2974 /* these are the protocol lists used for auto architecture detection:
2977 protocol [PC NETWORK PROGRAM 1.0]
2978 protocol [XENIX CORE]
2979 protocol [MICROSOFT NETWORKS 1.03]
2980 protocol [LANMAN1.0]
2981 protocol [Windows for Workgroups 3.1a]
2982 protocol [LM1.2X002]
2983 protocol [LANMAN2.1]
2984 protocol [NT LM 0.12]
2987 protocol [PC NETWORK PROGRAM 1.0]
2988 protocol [XENIX CORE]
2989 protocol [MICROSOFT NETWORKS 1.03]
2990 protocol [LANMAN1.0]
2991 protocol [Windows for Workgroups 3.1a]
2992 protocol [LM1.2X002]
2993 protocol [LANMAN2.1]
2994 protocol [NT LM 0.12]
2997 protocol [PC NETWORK PROGRAM 1.0]
2998 protocol [XENIX CORE]
2999 protocol [LANMAN1.0]
3000 protocol [LM1.2X002]
3001 protocol [LANMAN2.1]
3005 * Modified to recognize the architecture of the remote machine better.
3007 * This appears to be the matrix of which protocol is used by which
3009 Protocol WfWg Win95 WinNT OS/2
3010 PC NETWORK PROGRAM 1.0 1 1 1 1
3012 MICROSOFT NETWORKS 3.0 2 2
3014 MICROSOFT NETWORKS 1.03 3
3017 Windows for Workgroups 3.1a 5 5 5
3022 * tim@fsg.com 09/29/95
3025 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
3026 #define ARCH_WIN95 0x2
3027 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
3028 #define ARCH_WINNT 0x8
3029 #define ARCH_SAMBA 0x10
3031 #define ARCH_ALL 0x1F
3033 /* List of supported protocols, most desired first */
3037 int (*proto_reply_fn)(char *);
3039 } supported_protocols[] = {
3040 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
3041 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
3042 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3043 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3044 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3045 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3046 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3047 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
3048 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
3053 /****************************************************************************
3055 ****************************************************************************/
3056 static int reply_negprot(char *inbuf,char *outbuf)
3058 int outsize = set_message(outbuf,1,0,True);
3063 int bcc = SVAL(smb_buf(inbuf),-2);
3064 int arch = ARCH_ALL;
3066 p = smb_buf(inbuf)+1;
3067 while (p < (smb_buf(inbuf) + bcc))
3070 DEBUG(3,("Requested protocol [%s]\n",p));
3071 if (strcsequal(p,"Windows for Workgroups 3.1a"))
3072 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3073 else if (strcsequal(p,"DOS LM1.2X002"))
3074 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3075 else if (strcsequal(p,"DOS LANMAN2.1"))
3076 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3077 else if (strcsequal(p,"NT LM 0.12"))
3078 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3079 else if (strcsequal(p,"LANMAN2.1"))
3080 arch &= ( ARCH_WINNT | ARCH_OS2 );
3081 else if (strcsequal(p,"LM1.2X002"))
3082 arch &= ( ARCH_WINNT | ARCH_OS2 );
3083 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3085 else if (strcsequal(p,"XENIX CORE"))
3086 arch &= ( ARCH_WINNT | ARCH_OS2 );
3087 else if (strcsequal(p,"Samba")) {
3097 set_remote_arch(RA_SAMBA);
3100 set_remote_arch(RA_WFWG);
3103 set_remote_arch(RA_WIN95);
3106 set_remote_arch(RA_WINNT);
3109 set_remote_arch(RA_OS2);
3112 set_remote_arch(RA_UNKNOWN);
3116 /* possibly reload - change of architecture */
3117 reload_services(True);
3119 /* a special case to stop password server loops */
3120 if (Index == 1 && strequal(remote_machine,myhostname) &&
3121 lp_security()==SEC_SERVER)
3122 exit_server("Password server loop!");
3124 /* Check for protocols, most desirable first */
3125 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3127 p = smb_buf(inbuf)+1;
3129 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3130 while (p < (smb_buf(inbuf) + bcc))
3132 if (strequal(p,supported_protocols[protocol].proto_name))
3141 SSVAL(outbuf,smb_vwv0,choice);
3143 extern fstring remote_proto;
3144 strcpy(remote_proto,supported_protocols[protocol].short_name);
3145 reload_services(True);
3146 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3147 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3150 DEBUG(0,("No protocol supported !\n"));
3152 SSVAL(outbuf,smb_vwv0,choice);
3154 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3160 /****************************************************************************
3161 close all open files for a connection
3162 ****************************************************************************/
3163 static void close_open_files(int cnum)
3166 for (i=0;i<MAX_OPEN_FILES;i++)
3167 if( Files[i].cnum == cnum && Files[i].open) {
3174 /****************************************************************************
3176 ****************************************************************************/
3177 void close_cnum(int cnum, uint16 vuid)
3179 DirCacheFlush(SNUM(cnum));
3183 if (!OPEN_CNUM(cnum))
3185 DEBUG(0,("Can't close cnum %d\n",cnum));
3189 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3191 remote_machine,client_addr(),
3192 lp_servicename(SNUM(cnum))));
3194 yield_connection(cnum,
3195 lp_servicename(SNUM(cnum)),
3196 lp_max_connections(SNUM(cnum)));
3198 if (lp_status(SNUM(cnum)))
3199 yield_connection(cnum,"STATUS.",MAXSTATUS);
3201 close_open_files(cnum);
3202 dptr_closecnum(cnum);
3204 /* execute any "postexec = " line */
3205 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3208 strcpy(cmd,lp_postexec(SNUM(cnum)));
3209 standard_sub(cnum,cmd);
3210 smbrun(cmd,NULL,False);
3215 /* execute any "root postexec = " line */
3216 if (*lp_rootpostexec(SNUM(cnum)))
3219 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3220 standard_sub(cnum,cmd);
3221 smbrun(cmd,NULL,False);
3224 Connections[cnum].open = False;
3225 num_connections_open--;
3226 if (Connections[cnum].ngroups && Connections[cnum].groups)
3228 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3229 free(Connections[cnum].groups);
3230 free(Connections[cnum].igroups);
3231 Connections[cnum].groups = NULL;
3232 Connections[cnum].igroups = NULL;
3233 Connections[cnum].ngroups = 0;
3236 free_namearray(Connections[cnum].veto_list);
3237 free_namearray(Connections[cnum].hide_list);
3239 string_set(&Connections[cnum].user,"");
3240 string_set(&Connections[cnum].dirpath,"");
3241 string_set(&Connections[cnum].connectpath,"");
3245 /****************************************************************************
3246 simple routines to do connection counting
3247 ****************************************************************************/
3248 BOOL yield_connection(int cnum,char *name,int max_connections)
3250 struct connect_record crec;
3253 int mypid = getpid();
3256 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3258 if (max_connections <= 0)
3261 bzero(&crec,sizeof(crec));
3263 strcpy(fname,lp_lockdir());
3264 standard_sub(cnum,fname);
3265 trim_string(fname,"","/");
3269 strcat(fname,".LCK");
3271 f = fopen(fname,"r+");
3274 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3278 fseek(f,0,SEEK_SET);
3280 /* find a free spot */
3281 for (i=0;i<max_connections;i++)
3283 if (fread(&crec,sizeof(crec),1,f) != 1)
3285 DEBUG(2,("Entry not found in lock file %s\n",fname));
3289 if (crec.pid == mypid && crec.cnum == cnum)
3293 if (crec.pid != mypid || crec.cnum != cnum)
3296 DEBUG(2,("Entry not found in lock file %s\n",fname));
3300 bzero((void *)&crec,sizeof(crec));
3302 /* remove our mark */
3303 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3304 fwrite(&crec,sizeof(crec),1,f) != 1)
3306 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3311 DEBUG(3,("Yield successful\n"));
3318 /****************************************************************************
3319 simple routines to do connection counting
3320 ****************************************************************************/
3321 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3323 struct connect_record crec;
3326 int snum = SNUM(cnum);
3330 if (max_connections <= 0)
3333 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3335 strcpy(fname,lp_lockdir());
3336 standard_sub(cnum,fname);
3337 trim_string(fname,"","/");
3339 if (!directory_exist(fname,NULL))
3344 strcat(fname,".LCK");
3346 if (!file_exist(fname,NULL))
3348 int oldmask = umask(022);
3349 f = fopen(fname,"w");
3354 total_recs = file_size(fname) / sizeof(crec);
3356 f = fopen(fname,"r+");
3360 DEBUG(1,("couldn't open lock file %s\n",fname));
3364 /* find a free spot */
3365 for (i=0;i<max_connections;i++)
3368 if (i>=total_recs ||
3369 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3370 fread(&crec,sizeof(crec),1,f) != 1)
3372 if (foundi < 0) foundi = i;
3376 if (Clear && crec.pid && !process_exists(crec.pid))
3378 fseek(f,i*sizeof(crec),SEEK_SET);
3379 bzero((void *)&crec,sizeof(crec));
3380 fwrite(&crec,sizeof(crec),1,f);
3381 if (foundi < 0) foundi = i;
3384 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3393 DEBUG(3,("no free locks in %s\n",fname));
3398 /* fill in the crec */
3399 bzero((void *)&crec,sizeof(crec));
3400 crec.magic = 0x280267;
3401 crec.pid = getpid();
3403 crec.uid = Connections[cnum].uid;
3404 crec.gid = Connections[cnum].gid;
3405 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3406 crec.start = time(NULL);
3408 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3409 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3412 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3413 fwrite(&crec,sizeof(crec),1,f) != 1)
3424 /*******************************************************************
3425 prepare to dump a core file - carefully!
3426 ********************************************************************/
3427 static BOOL dump_core(void)
3431 strcpy(dname,debugf);
3432 if ((p=strrchr(dname,'/'))) *p=0;
3433 strcat(dname,"/corefiles");
3435 sys_chown(dname,getuid(),getgid());
3437 if (chdir(dname)) return(False);
3440 #ifndef NO_GETRLIMIT
3444 getrlimit(RLIMIT_CORE, &rlp);
3445 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3446 setrlimit(RLIMIT_CORE, &rlp);
3447 getrlimit(RLIMIT_CORE, &rlp);
3448 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3454 DEBUG(0,("Dumping core in %s\n",dname));
3459 /****************************************************************************
3461 ****************************************************************************/
3462 void exit_server(char *reason)
3464 static int firsttime=1;
3467 if (!firsttime) exit(0);
3471 DEBUG(2,("Closing connections\n"));
3472 for (i=0;i<MAX_CONNECTIONS;i++)
3473 if (Connections[i].open)
3474 close_cnum(i,(uint16)-1);
3476 if (dcelogin_atmost_once)
3480 int oldlevel = DEBUGLEVEL;
3482 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3484 show_msg(last_inbuf);
3485 DEBUGLEVEL = oldlevel;
3486 DEBUG(0,("===============================================================\n"));
3488 if (dump_core()) return;
3492 #ifdef FAST_SHARE_MODES
3493 stop_share_mode_mgmt();
3494 #endif /* FAST_SHARE_MODES */
3496 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3500 /****************************************************************************
3501 do some standard substitutions in a string
3502 ****************************************************************************/
3503 void standard_sub(int cnum,char *str)
3505 if (VALID_CNUM(cnum)) {
3508 for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) {
3510 case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
3511 string_sub(p,"%H",home);
3515 case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
3516 case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
3517 case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
3518 case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
3519 case '\0' : p++; break; /* don't run off the end of the string */
3520 default : p+=2; break;
3524 standard_sub_basic(str);
3528 These flags determine some of the permissions required to do an operation
3530 Note that I don't set NEED_WRITE on some write operations because they
3531 are used by some brain-dead clients when printing, and I don't want to
3532 force write permissions on print services.
3534 #define AS_USER (1<<0)
3535 #define NEED_WRITE (1<<1)
3536 #define TIME_INIT (1<<2)
3537 #define CAN_IPC (1<<3)
3538 #define AS_GUEST (1<<5)
3542 define a list of possible SMB messages and their corresponding
3543 functions. Any message that has a NULL function is unimplemented -
3544 please feel free to contribute implementations!
3546 struct smb_message_struct
3560 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3561 {SMBtcon,"SMBtcon",reply_tcon,0},
3562 {SMBtdis,"SMBtdis",reply_tdis,0},
3563 {SMBexit,"SMBexit",reply_exit,0},
3564 {SMBioctl,"SMBioctl",reply_ioctl,0},
3565 {SMBecho,"SMBecho",reply_echo,0},
3566 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3567 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3568 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3569 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3570 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3571 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3572 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3573 {SMBopen,"SMBopen",reply_open,AS_USER},
3575 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3576 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3577 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3579 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3580 {SMBread,"SMBread",reply_read,AS_USER},
3581 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3582 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3583 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3584 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3585 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3586 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3588 /* this is a Pathworks specific call, allowing the
3589 changing of the root path */
3590 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3592 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3593 {SMBflush,"SMBflush",reply_flush,AS_USER},
3594 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3595 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3596 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3597 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3598 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3599 {SMBlock,"SMBlock",reply_lock,AS_USER},
3600 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3602 /* CORE+ PROTOCOL FOLLOWS */
3604 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3605 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3606 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3607 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3608 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3610 /* LANMAN1.0 PROTOCOL FOLLOWS */
3612 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3613 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3614 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3615 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3616 {SMBwritec,"SMBwritec",NULL,AS_USER},
3617 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3618 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3619 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3620 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3621 {SMBioctls,"SMBioctls",NULL,AS_USER},
3622 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3623 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3625 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3626 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3627 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3628 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3630 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3631 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3632 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3634 /* LANMAN2.0 PROTOCOL FOLLOWS */
3635 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3636 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3637 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3638 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3640 /* messaging routines */
3641 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3642 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3643 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3644 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3646 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3648 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3649 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3650 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3651 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3654 /****************************************************************************
3655 return a string containing the function name of a SMB command
3656 ****************************************************************************/
3657 char *smb_fn_name(int type)
3659 static char *unknown_name = "SMBunknown";
3660 static int num_smb_messages =
3661 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3664 for (match=0;match<num_smb_messages;match++)
3665 if (smb_messages[match].code == type)
3668 if (match == num_smb_messages)
3669 return(unknown_name);
3671 return(smb_messages[match].name);
3675 /****************************************************************************
3676 do a switch on the message type, and return the response size
3677 ****************************************************************************/
3678 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3682 static int num_smb_messages =
3683 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3687 struct timeval msg_start_time;
3688 struct timeval msg_end_time;
3689 static unsigned long total_time = 0;
3691 GetTimeOfDay(&msg_start_time);
3698 last_message = type;
3700 /* make sure this is an SMB packet */
3701 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3703 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3707 for (match=0;match<num_smb_messages;match++)
3708 if (smb_messages[match].code == type)
3711 if (match == num_smb_messages)
3713 DEBUG(0,("Unknown message type %d!\n",type));
3714 outsize = reply_unknown(inbuf,outbuf);
3718 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3719 if (smb_messages[match].fn)
3721 int cnum = SVAL(inbuf,smb_tid);
3722 int flags = smb_messages[match].flags;
3723 uint16 session_tag = SVAL(inbuf,smb_uid);
3725 /* does this protocol need to be run as root? */
3726 if (!(flags & AS_USER))
3729 /* does this protocol need to be run as the connected user? */
3730 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3731 if (flags & AS_GUEST)
3734 return(ERROR(ERRSRV,ERRinvnid));
3736 /* this code is to work around a bug is MS client 3 without
3737 introducing a security hole - it needs to be able to do
3738 print queue checks as guest if it isn't logged in properly */
3739 if (flags & AS_USER)
3742 /* does it need write permission? */
3743 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3744 return(ERROR(ERRSRV,ERRaccess));
3746 /* ipc services are limited */
3747 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3748 return(ERROR(ERRSRV,ERRaccess));
3750 /* load service specific parameters */
3751 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3752 return(ERROR(ERRSRV,ERRaccess));
3754 /* does this protocol need to be run as guest? */
3755 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3756 return(ERROR(ERRSRV,ERRaccess));
3760 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3764 outsize = reply_unknown(inbuf,outbuf);
3769 GetTimeOfDay(&msg_end_time);
3770 if (!(smb_messages[match].flags & TIME_INIT))
3772 smb_messages[match].time = 0;
3773 smb_messages[match].flags |= TIME_INIT;
3776 unsigned long this_time =
3777 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3778 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3779 smb_messages[match].time += this_time;
3780 total_time += this_time;
3782 DEBUG(2,("TIME %s %d usecs %g pct\n",
3783 smb_fn_name(type),smb_messages[match].time,
3784 (100.0*smb_messages[match].time) / total_time));
3791 /****************************************************************************
3792 construct a chained reply and add it to the already made reply
3793 **************************************************************************/
3794 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3796 static char *orig_inbuf;
3797 static char *orig_outbuf;
3798 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3799 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3800 char *inbuf2, *outbuf2;
3802 char inbuf_saved[smb_wct];
3803 char outbuf_saved[smb_wct];
3804 extern int chain_size;
3805 int wct = CVAL(outbuf,smb_wct);
3806 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3808 /* maybe its not chained */
3809 if (smb_com2 == 0xFF) {
3810 CVAL(outbuf,smb_vwv0) = 0xFF;
3814 if (chain_size == 0) {
3815 /* this is the first part of the chain */
3817 orig_outbuf = outbuf;
3820 /* we need to tell the client where the next part of the reply will be */
3821 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3822 CVAL(outbuf,smb_vwv0) = smb_com2;
3824 /* remember how much the caller added to the chain, only counting stuff
3825 after the parameter words */
3826 chain_size += outsize - smb_wct;
3828 /* work out pointers into the original packets. The
3829 headers on these need to be filled in */
3830 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3831 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3833 /* remember the original command type */
3834 smb_com1 = CVAL(orig_inbuf,smb_com);
3836 /* save the data which will be overwritten by the new headers */
3837 memcpy(inbuf_saved,inbuf2,smb_wct);
3838 memcpy(outbuf_saved,outbuf2,smb_wct);
3840 /* give the new packet the same header as the last part of the SMB */
3841 memmove(inbuf2,inbuf,smb_wct);
3843 /* create the in buffer */
3844 CVAL(inbuf2,smb_com) = smb_com2;
3846 /* create the out buffer */
3847 bzero(outbuf2,smb_size);
3848 set_message(outbuf2,0,0,True);
3849 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3851 memcpy(outbuf2+4,inbuf2+4,4);
3852 CVAL(outbuf2,smb_rcls) = SUCCESS;
3853 CVAL(outbuf2,smb_reh) = 0;
3854 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3856 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3857 SSVAL(outbuf2,smb_err,SUCCESS);
3858 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3859 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3860 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3861 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3863 DEBUG(3,("Chained message\n"));
3866 /* process the request */
3867 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3868 bufsize-chain_size);
3870 /* copy the new reply and request headers over the old ones, but
3871 preserve the smb_com field */
3872 memmove(orig_outbuf,outbuf2,smb_wct);
3873 CVAL(orig_outbuf,smb_com) = smb_com1;
3875 /* restore the saved data, being careful not to overwrite any
3876 data from the reply header */
3877 memcpy(inbuf2,inbuf_saved,smb_wct);
3879 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3880 if (ofs < 0) ofs = 0;
3881 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3889 /****************************************************************************
3890 construct a reply to the incoming packet
3891 ****************************************************************************/
3892 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3894 int type = CVAL(inbuf,smb_com);
3896 int msg_type = CVAL(inbuf,0);
3897 extern int chain_size;
3899 smb_last_time = time(NULL);
3904 bzero(outbuf,smb_size);
3907 return(reply_special(inbuf,outbuf));
3909 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3910 set_message(outbuf,0,0,True);
3912 memcpy(outbuf+4,inbuf+4,4);
3913 CVAL(outbuf,smb_rcls) = SUCCESS;
3914 CVAL(outbuf,smb_reh) = 0;
3915 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3917 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3918 SSVAL(outbuf,smb_err,SUCCESS);
3919 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3920 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3921 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3922 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3924 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3926 outsize += chain_size;
3929 smb_setlen(outbuf,outsize - 4);
3934 /****************************************************************************
3935 process commands from the client
3936 ****************************************************************************/
3937 static void process(void)
3939 static int trans_num = 0;
3943 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3944 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3945 if ((InBuffer == NULL) || (OutBuffer == NULL))
3948 InBuffer += SMB_ALIGNMENT;
3949 OutBuffer += SMB_ALIGNMENT;
3952 DEBUG(3,("priming nmbd\n"));
3955 ip = *interpret_addr2("localhost");
3956 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3958 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3968 int deadtime = lp_deadtime()*60;
3970 int last_keepalive=0;
3971 int service_load_counter = 0;
3974 deadtime = DEFAULT_SMBD_TIMEOUT;
3976 if (lp_readprediction())
3977 do_read_prediction();
3981 for (counter=SMBD_SELECT_LOOP;
3982 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3983 counter += SMBD_SELECT_LOOP)
3987 BOOL allidle = True;
3988 extern int keepalive;
3990 if (counter > 365 * 3600) /* big number of seconds. */
3993 service_load_counter = 0;
3996 if (smb_read_error == READ_EOF) {
3997 DEBUG(3,("end of file from client\n"));
4001 if (smb_read_error == READ_ERROR) {
4002 DEBUG(3,("receive_smb error (%s) exiting\n",
4009 /* become root again if waiting */
4012 /* check for smb.conf reload */
4013 if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
4015 service_load_counter = counter;
4017 /* reload services, if files have changed. */
4018 reload_services(True);
4021 /* automatic timeout if all connections are closed */
4022 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
4023 DEBUG(2,("%s Closing idle connection\n",timestring()));
4027 if (keepalive && (counter-last_keepalive)>keepalive) {
4028 extern int password_client;
4029 if (!send_keepalive(Client)) {
4030 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
4033 /* also send a keepalive to the password server if its still
4035 if (password_client != -1)
4036 send_keepalive(password_client);
4037 last_keepalive = counter;
4040 /* check for connection timeouts */
4041 for (i=0;i<MAX_CONNECTIONS;i++)
4042 if (Connections[i].open)
4044 /* close dirptrs on connections that are idle */
4045 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4048 if (Connections[i].num_files_open > 0 ||
4049 (t-Connections[i].lastused)<deadtime)
4053 if (allidle && num_connections_open>0) {
4054 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4059 msg_type = CVAL(InBuffer,0);
4060 msg_flags = CVAL(InBuffer,1);
4061 type = CVAL(InBuffer,smb_com);
4063 len = smb_len(InBuffer);
4065 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
4069 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4072 if(trans_num == 1 && VT_Check(InBuffer)) {
4082 nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
4085 if (CVAL(OutBuffer,0) == 0)
4086 show_msg(OutBuffer);
4088 if (nread != smb_len(OutBuffer) + 4)
4090 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4092 smb_len(OutBuffer)));
4095 send_smb(Client,OutBuffer);
4102 /****************************************************************************
4103 initialise connect, service and file structs
4104 ****************************************************************************/
4105 static void init_structs(void )
4108 get_myname(myhostname,NULL);
4110 for (i=0;i<MAX_CONNECTIONS;i++)
4112 Connections[i].open = False;
4113 Connections[i].num_files_open=0;
4114 Connections[i].lastused=0;
4115 Connections[i].used=False;
4116 string_init(&Connections[i].user,"");
4117 string_init(&Connections[i].dirpath,"");
4118 string_init(&Connections[i].connectpath,"");
4119 string_init(&Connections[i].origpath,"");
4122 for (i=0;i<MAX_OPEN_FILES;i++)
4124 Files[i].open = False;
4125 string_init(&Files[i].name,"");
4129 for (i=0;i<MAX_OPEN_FILES;i++)
4131 file_fd_struct *fd_ptr = &FileFd[i];
4132 fd_ptr->ref_count = 0;
4133 fd_ptr->dev = (int32)-1;
4134 fd_ptr->inode = (int32)-1;
4136 fd_ptr->fd_readonly = -1;
4137 fd_ptr->fd_writeonly = -1;
4138 fd_ptr->real_open_flags = -1;
4144 /****************************************************************************
4145 usage on the program
4146 ****************************************************************************/
4147 static void usage(char *pname)
4149 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4151 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4152 printf("Version %s\n",VERSION);
4153 printf("\t-D become a daemon\n");
4154 printf("\t-p port listen on the specified port\n");
4155 printf("\t-d debuglevel set the debuglevel\n");
4156 printf("\t-l log basename. Basename for log/debug files\n");
4157 printf("\t-s services file. Filename of services file\n");
4158 printf("\t-P passive only\n");
4159 printf("\t-a overwrite log file, don't append\n");
4164 /****************************************************************************
4166 ****************************************************************************/
4167 int main(int argc,char *argv[])
4169 extern BOOL append_log;
4170 /* shall I run as a daemon */
4171 BOOL is_daemon = False;
4172 int port = SMB_PORT;
4174 extern char *optarg;
4175 char pidFile[100] = { 0 };
4177 #ifdef NEED_AUTH_PARAMETERS
4178 set_auth_parameters(argc,argv);
4189 strcpy(debugf,SMBLOGFILE);
4191 setup_logging(argv[0],False);
4193 charset_initialise();
4195 /* make absolutely sure we run as root - to handle cases whre people
4196 are crazy enough to have it setuid */
4206 fault_setup(exit_server);
4207 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4209 /* we want total control over the permissions on created files,
4210 so set our umask to 0 */
4217 /* this is for people who can't start the program correctly */
4218 while (argc > 1 && (*argv[1] != '-'))
4224 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4228 strncpy(pidFile, optarg, sizeof(pidFile));
4231 strcpy(user_socket_options,optarg);
4234 strcpy(scope,optarg);
4238 extern BOOL passive;
4243 strcpy(servicesf,optarg);
4246 strcpy(debugf,optarg);
4250 extern BOOL append_log;
4251 append_log = !append_log;
4261 DEBUGLEVEL = atoi(optarg);
4264 port = atoi(optarg);
4277 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4278 DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4280 #ifndef NO_GETRLIMIT
4281 #ifdef RLIMIT_NOFILE
4284 getrlimit(RLIMIT_NOFILE, &rlp);
4285 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4286 setrlimit(RLIMIT_NOFILE, &rlp);
4287 getrlimit(RLIMIT_NOFILE, &rlp);
4288 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4294 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4295 getuid(),getgid(),geteuid(),getegid()));
4297 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4299 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4305 if (!reload_services(False))
4308 codepage_initialise(lp_client_code_page());
4310 strcpy(myworkgroup, lp_workgroup());
4312 #ifndef NO_SIGNAL_TEST
4313 signal(SIGHUP,SIGNAL_CAST sig_hup);
4316 DEBUG(3,("%s loaded services\n",timestring()));
4318 if (!is_daemon && !is_a_socket(0))
4320 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4326 DEBUG(3,("%s becoming a daemon\n",timestring()));
4335 if ((fd = open(pidFile,
4339 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4341 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4344 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4346 DEBUG(0,("ERROR: smbd is already running\n"));
4349 sprintf(buf, "%u\n", (unsigned int) getpid());
4350 if (write(fd, buf, strlen(buf)) < 0)
4352 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4355 /* Leave pid file open & locked for the duration... */
4358 if (!open_sockets(is_daemon,port))
4361 #ifdef FAST_SHARE_MODES
4362 if (!start_share_mode_mgmt())
4364 #endif /* FAST_SHARE_MODES */
4366 /* possibly reload the services file. */
4367 reload_services(True);
4369 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4373 if (sys_chroot(lp_rootdir()) == 0)
4374 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4380 exit_server("normal exit");