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 ((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 if (is_hidden_path(SNUM(cnum), path))
232 DEBUG(5,("dos_mode returning "));
234 if (result & aHIDDEN) DEBUG(5, ("h"));
235 if (result & aRONLY ) DEBUG(5, ("r"));
236 if (result & aSYSTEM) DEBUG(5, ("s"));
237 if (result & aDIR ) DEBUG(5, ("d"));
238 if (result & aARCH ) DEBUG(5, ("a"));
246 /*******************************************************************
247 chmod a file - but preserve some bits
248 ********************************************************************/
249 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
258 if (sys_stat(fname,st)) return(-1);
261 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
263 if (dos_mode(cnum,fname,st) == dosmode) return(0);
265 unixmode = unix_mode(cnum,dosmode);
267 /* preserve the s bits */
268 mask |= (S_ISUID | S_ISGID);
270 /* preserve the t bit */
275 /* possibly preserve the x bits */
276 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
277 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
278 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
280 unixmode |= (st->st_mode & mask);
282 /* if we previously had any r bits set then leave them alone */
283 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
284 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
288 /* if we previously had any w bits set then leave them alone
289 if the new mode is not rdonly */
290 if (!IS_DOS_READONLY(dosmode) &&
291 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
292 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
296 return(sys_chmod(fname,unixmode));
300 /****************************************************************************
301 check if two filenames are equal
303 this needs to be careful about whether we are case sensitive
304 ****************************************************************************/
305 static BOOL fname_equal(char *name1, char *name2)
307 int l1 = strlen(name1);
308 int l2 = strlen(name2);
310 /* handle filenames ending in a single dot */
311 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
315 ret = fname_equal(name1,name2);
320 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
324 ret = fname_equal(name1,name2);
329 /* now normal filename handling */
331 return(strcmp(name1,name2) == 0);
333 return(strequal(name1,name2));
337 /****************************************************************************
338 mangle the 2nd name and check if it is then equal to the first name
339 ****************************************************************************/
340 static BOOL mangled_equal(char *name1, char *name2)
344 if (is_8_3(name2, True))
347 strcpy(tmpname,name2);
348 mangle_name_83(tmpname);
350 return(strequal(name1,tmpname));
354 /****************************************************************************
355 scan a directory to find a filename, matching without case sensitivity
357 If the name looks like a mangled name then try via the mangling functions
358 ****************************************************************************/
359 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
366 mangled = is_mangled(name);
368 /* handle null paths */
372 if (docache && (dname = DirCacheCheck(path,name,snum))) {
378 check_mangled_stack(name);
380 /* open the directory */
381 if (!(cur_dir = OpenDir(snum, path, True)))
383 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
387 /* now scan for matching names */
388 while ((dname = ReadDirName(cur_dir)))
391 (strequal(dname,".") || strequal(dname,"..")))
395 if (!name_map_mangle(name2,False,snum)) continue;
397 if ((mangled && mangled_equal(name,name2))
398 || fname_equal(name, name2))
400 /* we've found the file, change it's name and return */
401 if (docache) DirCacheAdd(path,name,dname,snum);
412 /****************************************************************************
413 This routine is called to convert names from the dos namespace to unix
414 namespace. It needs to handle any case conversions, mangling, format
417 We assume that we have already done a chdir() to the right "root" directory
420 The function will return False if some part of the name except for the last
421 part cannot be resolved
423 If the saved_last_component != 0, then the unmodified last component
424 of the pathname is returned there. This is used in an exceptional
425 case in reply_mv (so far). If saved_last_component == 0 then nothing
427 ****************************************************************************/
428 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
435 if(saved_last_component)
436 *saved_last_component = 0;
438 /* convert to basic unix format - removing \ chars and cleaning it up */
440 unix_clean_name(name);
442 /* names must be relative to the root of the service - trim any leading /.
443 also trim trailing /'s */
444 trim_string(name,"/","/");
447 * Ensure saved_last_component is valid even if file exists.
449 if(saved_last_component) {
450 end = strrchr(name, '/');
452 strcpy(saved_last_component, end + 1);
454 strcpy(saved_last_component, name);
457 if (!case_sensitive &&
458 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
461 /* check if it's a printer file */
462 if (Connections[cnum].printer)
464 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
468 sprintf(name2,"%.6s.XXXXXX",remote_machine);
469 /* sanitise the name */
470 for (s=name2 ; *s ; s++)
471 if (!issafe(*s)) *s = '_';
472 strcpy(name,(char *)mktemp(name2));
477 /* stat the name - if it exists then we are all done! */
478 if (sys_stat(name,&st) == 0)
481 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
483 /* a special case - if we don't have any mangling chars and are case
484 sensitive then searching won't help */
485 if (case_sensitive && !is_mangled(name) &&
486 !lp_strip_dot() && !use_mangled_map)
489 /* now we need to recursively match the name against the real
490 directory structure */
493 while (strncmp(start,"./",2) == 0)
496 /* now match each part of the path name separately, trying the names
497 as is first, then trying to scan the directory for matching names */
498 for (;start;start = (end?end+1:(char *)NULL))
500 /* pinpoint the end of this section of the filename */
501 end = strchr(start, '/');
503 /* chop the name at this point */
506 if(saved_last_component != 0)
507 strcpy(saved_last_component, end ? end + 1 : start);
509 /* check if the name exists up to this point */
510 if (sys_stat(name, &st) == 0)
512 /* it exists. it must either be a directory or this must be
513 the last part of the path for it to be OK */
514 if (end && !(st.st_mode & S_IFDIR))
516 /* an intermediate part of the name isn't a directory */
517 DEBUG(5,("Not a dir %s\n",start));
528 /* remember the rest of the pathname so it can be restored
530 if (end) strcpy(rest,end+1);
532 /* try to find this part of the path in the directory */
533 if (strchr(start,'?') || strchr(start,'*') ||
534 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
538 /* an intermediate part of the name can't be found */
539 DEBUG(5,("Intermediate not found %s\n",start));
544 /* just the last part of the name doesn't exist */
545 /* we may need to strupper() or strlower() it in case
546 this conversion is being used for file creation
548 /* if the filename is of mixed case then don't normalise it */
549 if (!case_preserve &&
550 (!strhasupper(start) || !strhaslower(start)))
553 /* check on the mangled stack to see if we can recover the
554 base of the filename */
555 if (is_mangled(start))
556 check_mangled_stack(start);
558 DEBUG(5,("New file %s\n",start));
562 /* restore the rest of the string */
565 strcpy(start+strlen(start)+1,rest);
566 end = start + strlen(start);
570 /* add to the dirpath that we have resolved so far */
571 if (*dirpath) strcat(dirpath,"/");
572 strcat(dirpath,start);
574 /* restore the / that we wiped out earlier */
578 /* the name has been resolved */
579 DEBUG(5,("conversion finished %s\n",name));
584 /****************************************************************************
585 normalise for DOS usage
586 ****************************************************************************/
587 static void disk_norm(int *bsize,int *dfree,int *dsize)
589 /* check if the disk is beyond the max disk size */
590 int maxdisksize = lp_maxdisksize();
592 /* convert to blocks - and don't overflow */
593 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
594 if (*dsize > maxdisksize) *dsize = maxdisksize;
595 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
600 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
605 if (*bsize > WORDMAX )
608 if (*dsize > WORDMAX)
610 if (*dfree > WORDMAX)
617 /****************************************************************************
618 return number of 1K blocks available on a path and total number
619 ****************************************************************************/
620 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
622 char *df_command = lp_dfree_command();
643 /* possibly use system() to get the result */
644 if (df_command && *df_command)
650 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
651 sprintf(syscmd,"%s %s",df_command,path);
652 standard_sub_basic(syscmd);
654 ret = smbrun(syscmd,outfile,False);
655 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
658 FILE *f = fopen(outfile,"r");
664 fscanf(f,"%d %d %d",dsize,dfree,bsize);
668 DEBUG(0,("Can't open %s\n",outfile));
672 disk_norm(bsize,dfree,dsize);
673 dfree_retval = ((*bsize)/1024)*(*dfree);
675 /* Ensure we return the min value between the users quota and
676 what's free on the disk. Thanks to Albrecht Gebhardt
677 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
679 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
681 disk_norm(&bsizeq, &dfreeq, &dsizeq);
682 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
683 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
684 dfree_retval : dfreeq_retval ;
685 /* maybe dfree and dfreeq are calculated using different bsizes
686 so convert dfree from bsize into bsizeq */
687 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
688 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
693 return(dfree_retval);
697 DEBUG(1,("Warning - no statfs function\n"));
701 if (statfs(path,&fs,sizeof(fs),0) != 0)
704 if (statvfs(path, &fs))
707 if (statfs(path,&fs,sizeof(fs)) == -1)
709 if (statfs(path,&fs) == -1)
711 #endif /* USE_STATVFS */
714 DEBUG(3,("dfree call failed code errno=%d\n",errno));
718 return(((*bsize)/1024)*(*dfree));
723 *dfree = fs.fd_req.bfree;
724 *dsize = fs.fd_req.btot;
727 *bsize = fs.f_frsize;
730 /* eg: osf1 has f_fsize = fundamental filesystem block size,
731 f_bsize = optimal transfer block size (MX: 94-04-19) */
736 #endif /* USE_STATVFS */
741 *dfree = fs.f_bavail;
743 *dsize = fs.f_blocks;
746 #if defined(SCO) || defined(ISC) || defined(MIPS)
750 /* handle rediculous bsize values - some OSes are broken */
751 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
753 disk_norm(bsize,dfree,dsize);
759 DEBUG(0,("dfree seems to be broken on your system\n"));
760 *dsize = 20*1024*1024/(*bsize);
761 *dfree = MAX(1,*dfree);
763 dfree_retval = ((*bsize)/1024)*(*dfree);
765 /* Ensure we return the min value between the users quota and
766 what's free on the disk. Thanks to Albrecht Gebhardt
767 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
769 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
771 disk_norm(&bsizeq, &dfreeq, &dsizeq);
772 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
773 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
774 dfree_retval : dfreeq_retval ;
775 /* maybe dfree and dfreeq are calculated using different bsizes
776 so convert dfree from bsize into bsizeq */
777 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
778 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
783 return(dfree_retval);
788 /****************************************************************************
789 wrap it to get filenames right
790 ****************************************************************************/
791 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
793 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
798 /****************************************************************************
799 check a filename - possibly caling reducename
801 This is called by every routine before it allows an operation on a filename.
802 It does any final confirmation necessary to ensure that the filename is
803 a valid one for the user to access.
804 ****************************************************************************/
805 BOOL check_name(char *name,int cnum)
811 if( is_vetoed_name(SNUM(cnum), name))
813 DEBUG(5,("file path name %s vetoed\n",name));
817 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
819 DEBUG(5,("check_name on %s failed\n",name));
824 /****************************************************************************
825 check a filename - possibly caling reducename
826 ****************************************************************************/
827 static void check_for_pipe(char *fname)
829 /* special case of pipe opens */
833 if (strstr(s,"pipe/"))
835 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
836 unix_ERR_class = ERRSRV;
837 unix_ERR_code = ERRaccess;
841 /****************************************************************************
842 fd support routines - attempt to do a sys_open
843 ****************************************************************************/
845 int fd_attempt_open(char *fname, int flags, int mode)
847 int fd = sys_open(fname,flags,mode);
849 /* Fix for files ending in '.' */
850 if((fd == -1) && (errno == ENOENT) &&
851 (strchr(fname,'.')==NULL))
854 fd = sys_open(fname,flags,mode);
857 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
858 if ((fd == -1) && (errno == ENAMETOOLONG))
861 char *p = strrchr(fname, '/');
863 if (p == fname) /* name is "/xxx" */
865 max_len = pathconf("/", _PC_NAME_MAX);
868 else if ((p == NULL) || (p == fname))
871 max_len = pathconf(".", _PC_NAME_MAX);
876 max_len = pathconf(fname, _PC_NAME_MAX);
880 if (strlen(p) > max_len)
882 char tmp = p[max_len];
885 if ((fd = sys_open(fname,flags,mode)) == -1)
893 /****************************************************************************
894 fd support routines - attempt to find an already open file by dev
895 and inode - increments the ref_count of the returned file_fd_struct *.
896 ****************************************************************************/
897 file_fd_struct *fd_get_already_open(struct stat *sbuf)
900 file_fd_struct *fd_ptr;
905 for(i = 0; i <= max_file_fd_used; i++) {
907 if((fd_ptr->ref_count > 0) &&
908 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
909 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
912 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
913 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
920 /****************************************************************************
921 fd support routines - attempt to find a empty slot in the FileFd array.
922 Increments the ref_count of the returned entry.
923 ****************************************************************************/
924 file_fd_struct *fd_get_new()
927 file_fd_struct *fd_ptr;
929 for(i = 0; i < MAX_OPEN_FILES; i++) {
931 if(fd_ptr->ref_count == 0) {
932 fd_ptr->dev = (uint32)-1;
933 fd_ptr->inode = (uint32)-1;
935 fd_ptr->fd_readonly = -1;
936 fd_ptr->fd_writeonly = -1;
937 fd_ptr->real_open_flags = -1;
939 /* Increment max used counter if neccessary, cuts down
940 on search time when re-using */
941 if(i > max_file_fd_used)
942 max_file_fd_used = i;
943 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
944 i, fd_ptr->dev, fd_ptr->inode));
948 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
953 /****************************************************************************
954 fd support routines - attempt to re-open an already open fd as O_RDWR.
955 Save the already open fd (we cannot close due to POSIX file locking braindamage.
956 ****************************************************************************/
958 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
960 int fd = sys_open( fname, O_RDWR, mode);
965 if(fd_ptr->real_open_flags == O_RDONLY)
966 fd_ptr->fd_readonly = fd_ptr->fd;
967 if(fd_ptr->real_open_flags == O_WRONLY)
968 fd_ptr->fd_writeonly = fd_ptr->fd;
971 fd_ptr->real_open_flags = O_RDWR;
974 /****************************************************************************
975 fd support routines - attempt to close the file referenced by this fd.
976 Decrements the ref_count and returns it.
977 ****************************************************************************/
978 int fd_attempt_close(file_fd_struct *fd_ptr)
980 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
982 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
983 fd_ptr->real_open_flags,
985 if(fd_ptr->ref_count > 0) {
987 if(fd_ptr->ref_count == 0) {
990 if(fd_ptr->fd_readonly != -1)
991 close(fd_ptr->fd_readonly);
992 if(fd_ptr->fd_writeonly != -1)
993 close(fd_ptr->fd_writeonly);
995 fd_ptr->fd_readonly = -1;
996 fd_ptr->fd_writeonly = -1;
997 fd_ptr->real_open_flags = -1;
998 fd_ptr->dev = (uint32)-1;
999 fd_ptr->inode = (uint32)-1;
1002 return fd_ptr->ref_count;
1005 /****************************************************************************
1007 ****************************************************************************/
1008 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1010 extern struct current_user current_user;
1012 struct stat statbuf;
1013 file_fd_struct *fd_ptr;
1015 Files[fnum].open = False;
1016 Files[fnum].fd_ptr = 0;
1019 strcpy(fname,fname1);
1021 /* check permissions */
1022 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1024 DEBUG(3,("Permission denied opening %s\n",fname));
1025 check_for_pipe(fname);
1029 /* this handles a bug in Win95 - it doesn't say to create the file when it
1031 if (Connections[cnum].printer)
1035 if (flags == O_WRONLY)
1036 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1039 #if UTIME_WORKAROUND
1040 /* XXXX - is this OK?? */
1041 /* this works around a utime bug but can cause other problems */
1042 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1047 * Ensure we have a valid struct stat so we can search the
1051 if(stat(fname, &statbuf) < 0) {
1052 if(errno != ENOENT) {
1053 DEBUG(3,("Error doing stat on file %s (%s)\n",
1054 fname,strerror(errno)));
1056 check_for_pipe(fname);
1066 * Check to see if we have this file already
1067 * open. If we do, just use the already open fd and increment the
1068 * reference count (fd_get_already_open increments the ref_count).
1070 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1072 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1074 /* File was already open. */
1075 if((flags & O_CREAT) && (flags & O_EXCL)) {
1076 fd_ptr->ref_count--;
1082 * If not opened O_RDWR try
1083 * and do that here - a chmod may have been done
1084 * between the last open and now.
1086 if(fd_ptr->real_open_flags != O_RDWR)
1087 fd_attempt_reopen(fname, mode, fd_ptr);
1090 * Ensure that if we wanted write access
1091 * it has been opened for write, and if we wanted read it
1092 * was open for read.
1094 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1095 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1096 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1097 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1098 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1099 check_for_pipe(fname);
1100 fd_ptr->ref_count--;
1106 /* We need to allocate a new file_fd_struct (this increments the
1108 if((fd_ptr = fd_get_new()) == 0)
1111 * Whatever the requested flags, attempt read/write access,
1112 * as we don't know what flags future file opens may require.
1113 * If this fails, try again with the required flags.
1114 * Even if we open read/write when only read access was
1115 * requested the setting of the can_write flag in
1116 * the file_struct will protect us from errant
1117 * write requests. We never need to worry about O_APPEND
1118 * as this is not set anywhere in Samba.
1120 fd_ptr->real_open_flags = O_RDWR;
1121 /* Set the flags as needed without the read/write modes. */
1122 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1123 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1125 * On some systems opening a file for R/W access on a read only
1126 * filesystems sets errno to EROFS.
1129 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1130 #else /* No EROFS */
1131 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1133 if(flags & O_WRONLY) {
1134 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1135 fd_ptr->real_open_flags = O_WRONLY;
1137 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1138 fd_ptr->real_open_flags = O_RDONLY;
1143 if ((fd_ptr->fd >=0) &&
1144 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1148 strcpy(dname,fname);
1149 p = strrchr(dname,'/');
1151 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1152 lp_minprintspace(SNUM(cnum))) {
1153 fd_attempt_close(fd_ptr);
1154 Files[fnum].fd_ptr = 0;
1155 if(fd_ptr->ref_count == 0)
1164 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1165 fname,strerror(errno),flags));
1166 /* Ensure the ref_count is decremented. */
1167 fd_attempt_close(fd_ptr);
1168 check_for_pipe(fname);
1172 if (fd_ptr->fd >= 0)
1176 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1177 /* Error - backout !! */
1178 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1179 fd_ptr->fd, fname,strerror(errno)));
1180 /* Ensure the ref_count is decremented. */
1181 fd_attempt_close(fd_ptr);
1186 /* Set the correct entries in fd_ptr. */
1187 fd_ptr->dev = (uint32)sbuf->st_dev;
1188 fd_ptr->inode = (uint32)sbuf->st_ino;
1190 Files[fnum].fd_ptr = fd_ptr;
1191 Connections[cnum].num_files_open++;
1192 Files[fnum].mode = sbuf->st_mode;
1193 GetTimeOfDay(&Files[fnum].open_time);
1194 Files[fnum].uid = current_user.id;
1195 Files[fnum].size = 0;
1196 Files[fnum].pos = -1;
1197 Files[fnum].open = True;
1198 Files[fnum].mmap_ptr = NULL;
1199 Files[fnum].mmap_size = 0;
1200 Files[fnum].can_lock = True;
1201 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1202 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1203 Files[fnum].share_mode = 0;
1204 Files[fnum].print_file = Connections[cnum].printer;
1205 Files[fnum].modified = False;
1206 Files[fnum].cnum = cnum;
1207 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1208 Files[fnum].wbmpx_ptr = NULL;
1211 * If the printer is marked as postscript output a leading
1212 * file identifier to ensure the file is treated as a raw
1214 * This has a similar effect as CtrlD=0 in WIN.INI file.
1215 * tim@fsg.com 09/06/94
1217 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1218 Files[fnum].can_write)
1220 DEBUG(3,("Writing postscript line\n"));
1221 write_file(fnum,"%!\n",3);
1224 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1225 timestring(),Connections[cnum].user,fname,
1226 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1227 Connections[cnum].num_files_open,fnum));
1232 /* mmap it if read-only */
1233 if (!Files[fnum].can_write)
1235 Files[fnum].mmap_size = file_size(fname);
1236 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1237 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1239 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1241 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1242 Files[fnum].mmap_ptr = NULL;
1248 /*******************************************************************
1250 ********************************************************************/
1251 void sync_file(int fnum)
1254 fsync(Files[fnum].fd_ptr->fd);
1258 /****************************************************************************
1259 run a file if it is a magic script
1260 ****************************************************************************/
1261 static void check_magic(int fnum,int cnum)
1263 if (!*lp_magicscript(SNUM(cnum)))
1266 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1270 if (!(p = strrchr(Files[fnum].name,'/')))
1271 p = Files[fnum].name;
1275 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1281 pstring magic_output;
1283 strcpy(fname,Files[fnum].name);
1285 if (*lp_magicoutput(SNUM(cnum)))
1286 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1288 sprintf(magic_output,"%s.out",fname);
1291 ret = smbrun(fname,magic_output,False);
1292 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1298 /****************************************************************************
1299 close a file - possibly invalidating the read prediction
1300 ****************************************************************************/
1301 void close_file(int fnum)
1303 files_struct *fs_p = &Files[fnum];
1304 int cnum = fs_p->cnum;
1305 uint32 dev = fs_p->fd_ptr->dev;
1306 uint32 inode = fs_p->fd_ptr->inode;
1307 share_lock_token token;
1309 invalidate_read_prediction(fs_p->fd_ptr->fd);
1311 Connections[cnum].num_files_open--;
1314 free((char *)fs_p->wbmpx_ptr);
1315 fs_p->wbmpx_ptr = NULL;
1321 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1322 fs_p->mmap_ptr = NULL;
1326 if (lp_share_modes(SNUM(cnum)))
1328 lock_share_entry( cnum, dev, inode, &token);
1329 del_share_mode(token, fnum);
1332 fd_attempt_close(fs_p->fd_ptr);
1334 if (lp_share_modes(SNUM(cnum)))
1335 unlock_share_entry( cnum, dev, inode, token);
1337 /* NT uses smbclose to start a print - weird */
1338 if (fs_p->print_file)
1341 /* check for magic scripts */
1342 check_magic(fnum,cnum);
1344 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1345 timestring(),Connections[cnum].user,fs_p->name,
1346 Connections[cnum].num_files_open));
1349 enum {AFAIL,AREAD,AWRITE,AALL};
1351 /*******************************************************************
1352 reproduce the share mode access table
1353 ********************************************************************/
1354 static int access_table(int new_deny,int old_deny,int old_mode,
1355 int share_pid,char *fname)
1357 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1359 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1360 if (old_deny == new_deny && share_pid == getpid())
1363 if (old_mode == 0) return(AREAD);
1365 /* the new smbpub.zip spec says that if the file extension is
1366 .com, .dll, .exe or .sym then allow the open. I will force
1367 it to read-only as this seems sensible although the spec is
1368 a little unclear on this. */
1369 if ((fname = strrchr(fname,'.'))) {
1370 if (strequal(fname,".com") ||
1371 strequal(fname,".dll") ||
1372 strequal(fname,".exe") ||
1373 strequal(fname,".sym"))
1383 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1384 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1385 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1388 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1389 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1390 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1393 if (old_deny==DENY_WRITE) return(AREAD);
1394 if (old_deny==DENY_READ) return(AWRITE);
1395 if (old_deny==DENY_NONE) return(AALL);
1401 /*******************************************************************
1402 check if the share mode on a file allows it to be deleted or unlinked
1403 return True if sharing doesn't prevent the operation
1404 ********************************************************************/
1405 BOOL check_file_sharing(int cnum,char *fname)
1409 min_share_mode_entry *old_shares = 0;
1410 int num_share_modes;
1412 share_lock_token token;
1415 if(!lp_share_modes(SNUM(cnum)))
1418 if (stat(fname,&sbuf) == -1) return(True);
1420 lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1421 num_share_modes = get_share_modes(cnum, token,
1422 (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1424 for( i = 0; i < num_share_modes; i++)
1426 if (old_shares[i].share_mode != DENY_DOS)
1429 if(old_shares[i].pid != pid)
1433 /* XXXX exactly what share mode combinations should be allowed for
1434 deleting/renaming? */
1435 /* If we got here then either there were no share modes or
1436 all share modes were DENY_DOS and the pid == getpid() */
1441 unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1442 if(old_shares != NULL)
1443 free((char *)old_shares);
1447 /****************************************************************************
1449 Helper for open_file_shared.
1450 Truncate a file after checking locking; close file if locked.
1451 **************************************************************************/
1452 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
1455 if (Files[fnum].can_write){
1456 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1457 /* If share modes are in force for this connection we
1458 have the share entry locked. Unlock it before closing. */
1459 if (*share_locked && lp_share_modes(SNUM(cnum)))
1460 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1461 Files[fnum].fd_ptr->inode, token);
1463 /* Share mode no longer locked. */
1464 *share_locked = False;
1466 unix_ERR_class = ERRDOS;
1467 unix_ERR_code = ERRlock;
1470 ftruncate(Files[fnum].fd_ptr->fd,0);
1475 /****************************************************************************
1476 open a file with a share mode
1477 ****************************************************************************/
1478 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1479 int mode,int *Access,int *action)
1481 files_struct *fs_p = &Files[fnum];
1484 int deny_mode = (share_mode>>4)&7;
1486 BOOL file_existed = file_exist(fname,&sbuf);
1487 BOOL share_locked = False;
1488 BOOL fcbopen = False;
1489 share_lock_token token;
1496 /* this is for OS/2 EAs - try and say we don't support them */
1497 if (strstr(fname,".+,;=[]."))
1499 unix_ERR_class = ERRDOS;
1500 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1504 if ((ofun & 0x3) == 0 && file_existed)
1512 if ((ofun & 0x3) == 2)
1515 /* note that we ignore the append flag as
1516 append does not mean the same thing under dos and unix */
1518 switch (share_mode&0xF)
1535 if (flags != O_RDONLY && file_existed &&
1536 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1546 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1548 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1553 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1555 if (lp_share_modes(SNUM(cnum)))
1559 min_share_mode_entry *old_shares = 0;
1564 dev = (uint32)sbuf.st_dev;
1565 inode = (uint32)sbuf.st_ino;
1566 lock_share_entry(cnum, dev, inode, &token);
1567 share_locked = True;
1568 num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1571 for(i = 0; i < num_shares; i++)
1573 /* someone else has a share lock on it, check to see
1575 int old_open_mode = old_shares[i].share_mode &0xF;
1576 int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1578 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2)
1580 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1581 deny_mode,old_deny_mode,old_open_mode,fname));
1582 free((char *)old_shares);
1584 unlock_share_entry(cnum, dev, inode, token);
1586 unix_ERR_class = ERRDOS;
1587 unix_ERR_code = ERRbadshare;
1592 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1593 old_shares[i].pid,fname);
1595 if ((access_allowed == AFAIL) ||
1596 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1597 (access_allowed == AREAD && flags == O_WRONLY) ||
1598 (access_allowed == AWRITE && flags == O_RDONLY))
1600 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1601 deny_mode,old_deny_mode,old_open_mode,
1602 old_shares[i].pid,fname,
1604 free((char *)old_shares);
1606 unlock_share_entry(cnum, dev, inode, token);
1608 unix_ERR_class = ERRDOS;
1609 unix_ERR_code = ERRbadshare;
1613 if (access_allowed == AREAD)
1616 if (access_allowed == AWRITE)
1621 free((char *)old_shares);
1624 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1625 flags,flags2,mode));
1627 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1628 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1631 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1638 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1640 /* We created the file - thus we must now lock the share entry before creating it. */
1641 dev = fs_p->fd_ptr->dev;
1642 inode = fs_p->fd_ptr->inode;
1643 lock_share_entry(cnum, dev, inode, &token);
1644 share_locked = True;
1660 fs_p->share_mode = (deny_mode<<4) | open_mode;
1663 (*Access) = open_mode;
1667 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1668 if (!file_existed) *action = 2;
1669 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1671 /* We must create the share mode entry before truncate as
1672 truncate can fail due to locking and have to close the
1673 file (which expects the share_mode_entry to be there).
1675 if (lp_share_modes(SNUM(cnum)))
1676 set_share_mode(token, fnum);
1678 if ((flags2&O_TRUNC) && file_existed)
1679 truncate_unless_locked(fnum,cnum,token,&share_locked);
1682 if (share_locked && lp_share_modes(SNUM(cnum)))
1683 unlock_share_entry( cnum, dev, inode, token);
1686 /****************************************************************************
1687 seek a file. Try to avoid the seek if possible
1688 ****************************************************************************/
1689 int seek_file(int fnum,int pos)
1692 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1695 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1696 return(Files[fnum].pos);
1699 /****************************************************************************
1701 ****************************************************************************/
1702 int read_file(int fnum,char *data,int pos,int n)
1706 if (!Files[fnum].can_write)
1708 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1716 if (Files[fnum].mmap_ptr)
1718 int num = MIN(n,Files[fnum].mmap_size-pos);
1721 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1733 if (seek_file(fnum,pos) != pos)
1735 DEBUG(3,("Failed to seek to %d\n",pos));
1740 readret = read(Files[fnum].fd_ptr->fd,data,n);
1741 if (readret > 0) ret += readret;
1748 /****************************************************************************
1750 ****************************************************************************/
1751 int write_file(int fnum,char *data,int n)
1753 if (!Files[fnum].can_write) {
1758 if (!Files[fnum].modified) {
1760 Files[fnum].modified = True;
1761 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1762 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1763 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1764 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1769 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1773 /****************************************************************************
1774 load parameters specific to a connection/service
1775 ****************************************************************************/
1776 BOOL become_service(int cnum,BOOL do_chdir)
1778 extern char magic_char;
1779 static int last_cnum = -1;
1782 if (!OPEN_CNUM(cnum))
1788 Connections[cnum].lastused = smb_last_time;
1793 ChDir(Connections[cnum].connectpath) != 0 &&
1794 ChDir(Connections[cnum].origpath) != 0)
1796 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1797 Connections[cnum].connectpath,cnum));
1801 if (cnum == last_cnum)
1806 case_default = lp_defaultcase(snum);
1807 case_preserve = lp_preservecase(snum);
1808 short_case_preserve = lp_shortpreservecase(snum);
1809 case_mangle = lp_casemangle(snum);
1810 case_sensitive = lp_casesensitive(snum);
1811 magic_char = lp_magicchar(snum);
1812 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1817 /****************************************************************************
1818 find a service entry
1819 ****************************************************************************/
1820 int find_service(char *service)
1824 string_sub(service,"\\","/");
1826 iService = lp_servicenumber(service);
1828 /* now handle the special case of a home directory */
1831 char *phome_dir = get_home_dir(service);
1832 DEBUG(3,("checking for home directory %s gave %s\n",service,
1833 phome_dir?phome_dir:"(NULL)"));
1837 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1839 lp_add_home(service,iHomeService,phome_dir);
1840 iService = lp_servicenumber(service);
1845 /* If we still don't have a service, attempt to add it as a printer. */
1848 int iPrinterService;
1850 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1854 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1856 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1858 DEBUG(3,("%s is a valid printer name\n", service));
1859 DEBUG(3,("adding %s as a printer service\n", service));
1860 lp_add_printer(service,iPrinterService);
1861 iService = lp_servicenumber(service);
1863 DEBUG(0,("failed to add %s as a printer service!\n", service));
1866 DEBUG(3,("%s is not a valid printer name\n", service));
1870 /* just possibly it's a default service? */
1873 char *defservice = lp_defaultservice();
1874 if (defservice && *defservice && !strequal(defservice,service)) {
1875 iService = find_service(defservice);
1876 if (iService >= 0) {
1877 string_sub(service,"_","/");
1878 iService = lp_add_service(service,iService);
1884 if (!VALID_SNUM(iService))
1886 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1891 DEBUG(3,("find_service() failed to find service %s\n", service));
1897 /****************************************************************************
1898 create an error packet from a cached error.
1899 ****************************************************************************/
1900 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1902 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1904 int32 eclass = wbmpx->wr_errclass;
1905 int32 err = wbmpx->wr_error;
1907 /* We can now delete the auxiliary struct */
1908 free((char *)wbmpx);
1909 Files[fnum].wbmpx_ptr = NULL;
1910 return error_packet(inbuf,outbuf,eclass,err,line);
1919 } unix_smb_errmap[] =
1921 {EPERM,ERRDOS,ERRnoaccess},
1922 {EACCES,ERRDOS,ERRnoaccess},
1923 {ENOENT,ERRDOS,ERRbadfile},
1924 {EIO,ERRHRD,ERRgeneral},
1925 {EBADF,ERRSRV,ERRsrverror},
1926 {EINVAL,ERRSRV,ERRsrverror},
1927 {EEXIST,ERRDOS,ERRfilexists},
1928 {ENFILE,ERRDOS,ERRnofids},
1929 {EMFILE,ERRDOS,ERRnofids},
1930 {ENOSPC,ERRHRD,ERRdiskfull},
1932 {EDQUOT,ERRHRD,ERRdiskfull},
1935 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1938 {EXDEV,ERRDOS,ERRdiffdevice},
1940 {EROFS,ERRHRD,ERRnowrite},
1945 /****************************************************************************
1946 create an error packet from errno
1947 ****************************************************************************/
1948 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1950 int eclass=def_class;
1954 if (unix_ERR_class != SUCCESS)
1956 eclass = unix_ERR_class;
1957 ecode = unix_ERR_code;
1958 unix_ERR_class = SUCCESS;
1963 while (unix_smb_errmap[i].smbclass != 0)
1965 if (unix_smb_errmap[i].unixerror == errno)
1967 eclass = unix_smb_errmap[i].smbclass;
1968 ecode = unix_smb_errmap[i].smbcode;
1975 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1979 /****************************************************************************
1980 create an error packet. Normally called using the ERROR() macro
1981 ****************************************************************************/
1982 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1984 int outsize = set_message(outbuf,0,0,True);
1986 cmd = CVAL(inbuf,smb_com);
1988 CVAL(outbuf,smb_rcls) = error_class;
1989 SSVAL(outbuf,smb_err,error_code);
1991 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1994 (int)CVAL(inbuf,smb_com),
1995 smb_fn_name(CVAL(inbuf,smb_com)),
2000 DEBUG(3,("error string = %s\n",strerror(errno)));
2006 #ifndef SIGCLD_IGNORE
2007 /****************************************************************************
2008 this prevents zombie child processes
2009 ****************************************************************************/
2010 static int sig_cld()
2012 static int depth = 0;
2015 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2021 BlockSignals(True,SIGCLD);
2022 DEBUG(5,("got SIGCLD\n"));
2025 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2029 /* Stevens, Adv. Unix Prog. says that on system V you must call
2030 wait before reinstalling the signal handler, because the kernel
2031 calls the handler from within the signal-call when there is a
2032 child that has exited. This would lead to an infinite recursion
2033 if done vice versa. */
2035 #ifndef DONT_REINSTALL_SIG
2036 #ifdef SIGCLD_IGNORE
2037 signal(SIGCLD, SIG_IGN);
2039 signal(SIGCLD, SIGNAL_CAST sig_cld);
2044 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2047 BlockSignals(False,SIGCLD);
2052 /****************************************************************************
2053 this is called when the client exits abruptly
2054 **************************************************************************/
2055 static int sig_pipe()
2057 extern int password_client;
2058 BlockSignals(True,SIGPIPE);
2060 if (password_client != -1) {
2061 DEBUG(3,("lost connection to password server\n"));
2062 close(password_client);
2063 password_client = -1;
2064 #ifndef DONT_REINSTALL_SIG
2065 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2067 BlockSignals(False,SIGPIPE);
2071 exit_server("Got sigpipe\n");
2075 /****************************************************************************
2076 open the socket communication
2077 ****************************************************************************/
2078 static BOOL open_sockets(BOOL is_daemon,int port)
2085 struct sockaddr addr;
2086 int in_addrlen = sizeof(addr);
2089 #ifdef SIGCLD_IGNORE
2090 signal(SIGCLD, SIG_IGN);
2092 signal(SIGCLD, SIGNAL_CAST sig_cld);
2095 /* open an incoming socket */
2096 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2100 /* ready to listen */
2101 if (listen(s, 5) == -1)
2103 DEBUG(0,("listen: %s",strerror(errno)));
2111 /* now accept incoming connections - forking a new process
2112 for each incoming connection */
2113 DEBUG(2,("waiting for a connection\n"));
2116 Client = accept(s,&addr,&in_addrlen);
2118 if (Client == -1 && errno == EINTR)
2123 DEBUG(0,("accept: %s",strerror(errno)));
2127 #ifdef NO_FORK_DEBUG
2128 #ifndef NO_SIGNAL_TEST
2129 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2130 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2134 if (Client != -1 && fork()==0)
2136 /* Child code ... */
2137 #ifndef NO_SIGNAL_TEST
2138 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2139 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2141 /* close the listening socket */
2144 /* close our standard file descriptors */
2148 set_socket_options(Client,"SO_KEEPALIVE");
2149 set_socket_options(Client,user_socket_options);
2151 /* Reset global variables in util.c so that
2152 client substitutions will be done correctly
2155 reset_globals_after_fork();
2158 close(Client); /* The parent doesn't need this socket */
2164 /* We will abort gracefully when the client or remote system
2166 #ifndef NO_SIGNAL_TEST
2167 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2171 /* close our standard file descriptors */
2174 set_socket_options(Client,"SO_KEEPALIVE");
2175 set_socket_options(Client,user_socket_options);
2182 /****************************************************************************
2183 check if a snum is in use
2184 ****************************************************************************/
2185 BOOL snum_used(int snum)
2188 for (i=0;i<MAX_CONNECTIONS;i++)
2189 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2194 /****************************************************************************
2195 reload the services file
2196 **************************************************************************/
2197 BOOL reload_services(BOOL test)
2204 strcpy(fname,lp_configfile());
2205 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2207 strcpy(servicesf,fname);
2214 if (test && !lp_file_list_changed())
2217 lp_killunused(snum_used);
2219 ret = lp_load(servicesf,False);
2221 /* perhaps the config filename is now set */
2223 reload_services(True);
2232 set_socket_options(Client,"SO_KEEPALIVE");
2233 set_socket_options(Client,user_socket_options);
2237 create_mangled_stack(lp_mangledstack());
2239 /* this forces service parameters to be flushed */
2240 become_service(-1,True);
2247 /****************************************************************************
2248 this prevents zombie child processes
2249 ****************************************************************************/
2250 static int sig_hup()
2252 BlockSignals(True,SIGHUP);
2253 DEBUG(0,("Got SIGHUP\n"));
2254 reload_services(False);
2255 #ifndef DONT_REINSTALL_SIG
2256 signal(SIGHUP,SIGNAL_CAST sig_hup);
2258 BlockSignals(False,SIGHUP);
2262 /****************************************************************************
2263 Setup the groups a user belongs to.
2264 ****************************************************************************/
2265 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2266 int **p_igroups, gid_t **p_groups)
2268 if (-1 == initgroups(user,gid))
2272 DEBUG(0,("Unable to initgroups!\n"));
2273 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2274 DEBUG(0,("This is probably a problem with the account %s\n",user));
2282 ngroups = getgroups(0,&grp);
2285 igroups = (int *)malloc(sizeof(int)*ngroups);
2286 for (i=0;i<ngroups;i++)
2287 igroups[i] = 0x42424242;
2288 ngroups = getgroups(ngroups,(gid_t *)igroups);
2290 if (igroups[0] == 0x42424242)
2293 *p_ngroups = ngroups;
2295 /* The following bit of code is very strange. It is due to the
2296 fact that some OSes use int* and some use gid_t* for
2297 getgroups, and some (like SunOS) use both, one in prototypes,
2298 and one in man pages and the actual code. Thus we detect it
2299 dynamically using some very ugly code */
2302 /* does getgroups return ints or gid_t ?? */
2303 static BOOL groups_use_ints = True;
2305 if (groups_use_ints &&
2307 SVAL(igroups,2) == 0x4242)
2308 groups_use_ints = False;
2310 for (i=0;groups_use_ints && i<ngroups;i++)
2311 if (igroups[i] == 0x42424242)
2312 groups_use_ints = False;
2314 if (groups_use_ints)
2316 *p_igroups = igroups;
2317 *p_groups = (gid_t *)igroups;
2321 gid_t *groups = (gid_t *)igroups;
2322 igroups = (int *)malloc(sizeof(int)*ngroups);
2323 for (i=0;i<ngroups;i++)
2324 igroups[i] = groups[i];
2325 *p_igroups = igroups;
2326 *p_groups = (gid_t *)groups;
2329 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2330 for (i=0;i<ngroups;i++)
2331 DEBUG(3,("%d ",igroups[i]));
2337 /****************************************************************************
2338 make a connection to a service
2339 ****************************************************************************/
2340 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2344 struct passwd *pass = NULL;
2345 connection_struct *pcon;
2348 static BOOL first_connection = True;
2352 snum = find_service(service);
2355 if (strequal(service,"IPC$"))
2357 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2361 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2365 if (strequal(service,HOMES_NAME))
2367 if (*user && Get_Pwnam(user,True))
2368 return(make_connection(user,user,password,pwlen,dev,vuid));
2370 if (validated_username(vuid))
2372 strcpy(user,validated_username(vuid));
2373 return(make_connection(user,user,password,pwlen,dev,vuid));
2377 if (!lp_snum_ok(snum) || !check_access(snum)) {
2381 /* you can only connect to the IPC$ service as an ipc device */
2382 if (strequal(service,"IPC$"))
2385 if (*dev == '?' || !*dev)
2387 if (lp_print_ok(snum))
2388 strcpy(dev,"LPT1:");
2393 /* if the request is as a printer and you can't print then refuse */
2395 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2396 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2400 /* lowercase the user name */
2403 /* add it as a possible user name */
2404 add_session_user(service);
2406 /* shall we let them in? */
2407 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2409 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2413 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2416 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2420 pcon = &Connections[cnum];
2421 bzero((char *)pcon,sizeof(*pcon));
2423 /* find out some info about the user */
2424 pass = Get_Pwnam(user,True);
2428 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2432 pcon->read_only = lp_readonly(snum);
2436 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2437 string_sub(list,"%S",service);
2439 if (user_in_list(user,list))
2440 pcon->read_only = True;
2442 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2443 string_sub(list,"%S",service);
2445 if (user_in_list(user,list))
2446 pcon->read_only = False;
2449 /* admin user check */
2450 if (user_in_list(user,lp_admin_users(snum)) &&
2453 pcon->admin_user = True;
2454 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2457 pcon->admin_user = False;
2459 pcon->force_user = force;
2461 pcon->uid = pass->pw_uid;
2462 pcon->gid = pass->pw_gid;
2463 pcon->num_files_open = 0;
2464 pcon->lastused = time(NULL);
2465 pcon->service = snum;
2467 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2468 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2469 pcon->dirptr = NULL;
2470 string_set(&pcon->dirpath,"");
2471 string_set(&pcon->user,user);
2474 if (*lp_force_group(snum))
2479 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2480 /* default service may be a group name */
2481 string_sub(gname,"%S",service);
2482 gptr = (struct group *)getgrnam(gname);
2486 pcon->gid = gptr->gr_gid;
2487 DEBUG(3,("Forced group %s\n",gname));
2490 DEBUG(1,("Couldn't find group %s\n",gname));
2494 if (*lp_force_user(snum))
2496 struct passwd *pass2;
2498 strcpy(fuser,lp_force_user(snum));
2499 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2502 pcon->uid = pass2->pw_uid;
2503 string_set(&pcon->user,fuser);
2505 pcon->force_user = True;
2506 DEBUG(3,("Forced user %s\n",fuser));
2509 DEBUG(1,("Couldn't find user %s\n",fuser));
2514 strcpy(s,lp_pathname(snum));
2515 standard_sub(cnum,s);
2516 string_set(&pcon->connectpath,s);
2517 DEBUG(3,("Connect path is %s\n",s));
2520 /* groups stuff added by ih */
2522 pcon->groups = NULL;
2526 /* Find all the groups this uid is in and store them. Used by become_user() */
2527 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2529 /* check number of connections */
2530 if (!claim_connection(cnum,
2531 lp_servicename(SNUM(cnum)),
2532 lp_max_connections(SNUM(cnum)),False))
2534 DEBUG(1,("too many connections - rejected\n"));
2538 if (lp_status(SNUM(cnum)))
2539 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2541 first_connection = False;
2546 /* execute any "root preexec = " line */
2547 if (*lp_rootpreexec(SNUM(cnum)))
2550 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2551 standard_sub(cnum,cmd);
2552 DEBUG(5,("cmd=%s\n",cmd));
2553 smbrun(cmd,NULL,False);
2556 if (!become_user(cnum,pcon->vuid))
2558 DEBUG(0,("Can't become connected user!\n"));
2560 if (!IS_IPC(cnum)) {
2561 yield_connection(cnum,
2562 lp_servicename(SNUM(cnum)),
2563 lp_max_connections(SNUM(cnum)));
2564 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2569 if (ChDir(pcon->connectpath) != 0)
2571 DEBUG(0,("Can't change directory to %s (%s)\n",
2572 pcon->connectpath,strerror(errno)));
2575 if (!IS_IPC(cnum)) {
2576 yield_connection(cnum,
2577 lp_servicename(SNUM(cnum)),
2578 lp_max_connections(SNUM(cnum)));
2579 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2584 string_set(&pcon->origpath,pcon->connectpath);
2586 #if SOFTLINK_OPTIMISATION
2587 /* resolve any soft links early */
2590 strcpy(s,pcon->connectpath);
2592 string_set(&pcon->connectpath,s);
2593 ChDir(pcon->connectpath);
2597 num_connections_open++;
2598 add_session_user(user);
2600 /* execute any "preexec = " line */
2601 if (*lp_preexec(SNUM(cnum)))
2604 strcpy(cmd,lp_preexec(SNUM(cnum)));
2605 standard_sub(cnum,cmd);
2606 smbrun(cmd,NULL,False);
2609 /* we've finished with the sensitive stuff */
2613 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2617 lp_servicename(SNUM(cnum)),user,
2627 /****************************************************************************
2628 find first available file slot
2629 ****************************************************************************/
2630 int find_free_file(void )
2633 /* we start at 1 here for an obscure reason I can't now remember,
2634 but I think is important :-) */
2635 for (i=1;i<MAX_OPEN_FILES;i++)
2638 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2642 /****************************************************************************
2643 find first available connection slot, starting from a random position.
2644 The randomisation stops problems with the server dieing and clients
2645 thinking the server is still available.
2646 ****************************************************************************/
2647 static int find_free_connection(int hash )
2651 hash = (hash % (MAX_CONNECTIONS-2))+1;
2655 for (i=hash+1;i!=hash;)
2657 if (!Connections[i].open && Connections[i].used == used)
2659 DEBUG(3,("found free connection number %d\n",i));
2663 if (i == MAX_CONNECTIONS)
2673 DEBUG(1,("ERROR! Out of connection structures\n"));
2678 /****************************************************************************
2679 reply for the core protocol
2680 ****************************************************************************/
2681 int reply_corep(char *outbuf)
2683 int outsize = set_message(outbuf,1,0,True);
2685 Protocol = PROTOCOL_CORE;
2691 /****************************************************************************
2692 reply for the coreplus protocol
2693 ****************************************************************************/
2694 int reply_coreplus(char *outbuf)
2696 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2697 int outsize = set_message(outbuf,13,0,True);
2698 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2699 readbraw and writebraw (possibly) */
2700 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2701 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2703 Protocol = PROTOCOL_COREPLUS;
2709 /****************************************************************************
2710 reply for the lanman 1.0 protocol
2711 ****************************************************************************/
2712 int reply_lanman1(char *outbuf)
2714 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2716 BOOL doencrypt = SMBENCRYPT();
2717 time_t t = time(NULL);
2718 /* We need to save and restore this as it can be destroyed
2719 if we call another server if security=server
2720 Thanks to Paul Nelson @ Thursby for pointing this out.
2722 uint16 mid = SVAL(outbuf, smb_mid);
2724 if (lp_security()>=SEC_USER) secword |= 1;
2725 if (doencrypt) secword |= 2;
2727 set_message(outbuf,13,doencrypt?8:0,True);
2728 SSVAL(outbuf,smb_vwv1,secword);
2730 /* Create a token value and add it to the outgoing packet. */
2732 generate_next_challenge(smb_buf(outbuf));
2735 Protocol = PROTOCOL_LANMAN1;
2737 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2738 DEBUG(3,("using password server validation\n"));
2740 if (doencrypt) set_challenge(smb_buf(outbuf));
2744 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2745 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2746 SSVAL(outbuf,smb_vwv2,max_recv);
2747 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2748 SSVAL(outbuf,smb_vwv4,1);
2749 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2750 readbraw writebraw (possibly) */
2751 SIVAL(outbuf,smb_vwv6,getpid());
2752 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2754 put_dos_date(outbuf,smb_vwv8,t);
2756 return (smb_len(outbuf)+4);
2760 /****************************************************************************
2761 reply for the lanman 2.0 protocol
2762 ****************************************************************************/
2763 int reply_lanman2(char *outbuf)
2765 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2767 BOOL doencrypt = SMBENCRYPT();
2768 time_t t = time(NULL);
2769 /* We need to save and restore this as it can be destroyed
2770 if we call another server if security=server
2771 Thanks to Paul Nelson @ Thursby for pointing this out.
2773 uint16 mid = SVAL(outbuf, smb_mid);
2775 if (lp_security()>=SEC_USER) secword |= 1;
2776 if (doencrypt) secword |= 2;
2778 set_message(outbuf,13,doencrypt?8:0,True);
2779 SSVAL(outbuf,smb_vwv1,secword);
2781 /* Create a token value and add it to the outgoing packet. */
2783 generate_next_challenge(smb_buf(outbuf));
2786 SIVAL(outbuf,smb_vwv6,getpid());
2788 Protocol = PROTOCOL_LANMAN2;
2790 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2791 DEBUG(3,("using password server validation\n"));
2793 if (doencrypt) set_challenge(smb_buf(outbuf));
2797 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2798 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2799 SSVAL(outbuf,smb_vwv2,max_recv);
2800 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2801 SSVAL(outbuf,smb_vwv4,1);
2802 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2803 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2804 put_dos_date(outbuf,smb_vwv8,t);
2806 return (smb_len(outbuf)+4);
2810 /****************************************************************************
2811 reply for the nt protocol
2812 ****************************************************************************/
2813 int reply_nt1(char *outbuf)
2815 /* dual names + lock_and_read + nt SMBs + remote API calls */
2816 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2818 other valid capabilities which we may support at some time...
2819 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2820 CAP_LARGE_FILES|CAP_LARGE_READX|
2821 CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2825 BOOL doencrypt = SMBENCRYPT();
2826 time_t t = time(NULL);
2829 char challenge_len = 8;
2830 /* We need to save and restore this as it can be destroyed
2831 if we call another server if security=server
2832 Thanks to Paul Nelson @ Thursby for pointing this out.
2834 uint16 mid = SVAL(outbuf, smb_mid);
2836 if (lp_readraw() && lp_writeraw())
2838 capabilities |= CAP_RAW_MODE;
2841 if (lp_security()>=SEC_USER) secword |= 1;
2842 if (doencrypt) secword |= 2;
2844 /* decide where (if) to put the encryption challenge, and
2845 follow it with the OEM'd domain name
2847 encrypt_len = doencrypt?challenge_len:0;
2849 data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2851 data_len = encrypt_len + strlen(myworkgroup) + 1;
2854 set_message(outbuf,17,data_len,True);
2857 /* put the OEM'd domain name */
2858 PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2860 strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2863 CVAL(outbuf,smb_vwv1) = secword;
2865 /* Create a token value and add it to the outgoing packet. */
2868 generate_next_challenge(smb_buf(outbuf));
2870 /* Tell the nt machine how long the challenge is. */
2871 SSVALS(outbuf,smb_vwv16+1,challenge_len);
2875 Protocol = PROTOCOL_NT1;
2877 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2878 DEBUG(3,("using password server validation\n"));
2880 if (doencrypt) set_challenge(smb_buf(outbuf));
2884 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2885 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2886 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2887 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2888 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2889 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2890 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2891 put_long_date(outbuf+smb_vwv11+1,t);
2892 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2893 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2895 return (smb_len(outbuf)+4);
2898 /* these are the protocol lists used for auto architecture detection:
2901 protocol [PC NETWORK PROGRAM 1.0]
2902 protocol [XENIX CORE]
2903 protocol [MICROSOFT NETWORKS 1.03]
2904 protocol [LANMAN1.0]
2905 protocol [Windows for Workgroups 3.1a]
2906 protocol [LM1.2X002]
2907 protocol [LANMAN2.1]
2908 protocol [NT LM 0.12]
2911 protocol [PC NETWORK PROGRAM 1.0]
2912 protocol [XENIX CORE]
2913 protocol [MICROSOFT NETWORKS 1.03]
2914 protocol [LANMAN1.0]
2915 protocol [Windows for Workgroups 3.1a]
2916 protocol [LM1.2X002]
2917 protocol [LANMAN2.1]
2918 protocol [NT LM 0.12]
2921 protocol [PC NETWORK PROGRAM 1.0]
2922 protocol [XENIX CORE]
2923 protocol [LANMAN1.0]
2924 protocol [LM1.2X002]
2925 protocol [LANMAN2.1]
2929 * Modified to recognize the architecture of the remote machine better.
2931 * This appears to be the matrix of which protocol is used by which
2933 Protocol WfWg Win95 WinNT OS/2
2934 PC NETWORK PROGRAM 1.0 1 1 1 1
2936 MICROSOFT NETWORKS 3.0 2 2
2938 MICROSOFT NETWORKS 1.03 3
2941 Windows for Workgroups 3.1a 5 5 5
2946 * tim@fsg.com 09/29/95
2949 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2950 #define ARCH_WIN95 0x2
2951 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2952 #define ARCH_WINNT 0x8
2953 #define ARCH_SAMBA 0x10
2955 #define ARCH_ALL 0x1F
2957 /* List of supported protocols, most desired first */
2961 int (*proto_reply_fn)(char *);
2963 } supported_protocols[] = {
2964 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2965 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2966 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2967 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2968 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2969 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2970 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2971 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2972 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2977 /****************************************************************************
2979 ****************************************************************************/
2980 static int reply_negprot(char *inbuf,char *outbuf)
2982 extern fstring remote_arch;
2983 int outsize = set_message(outbuf,1,0,True);
2988 int bcc = SVAL(smb_buf(inbuf),-2);
2989 int arch = ARCH_ALL;
2991 p = smb_buf(inbuf)+1;
2992 while (p < (smb_buf(inbuf) + bcc))
2995 DEBUG(3,("Requested protocol [%s]\n",p));
2996 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2997 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2998 else if (strcsequal(p,"DOS LM1.2X002"))
2999 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3000 else if (strcsequal(p,"DOS LANMAN2.1"))
3001 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3002 else if (strcsequal(p,"NT LM 0.12"))
3003 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3004 else if (strcsequal(p,"LANMAN2.1"))
3005 arch &= ( ARCH_WINNT | ARCH_OS2 );
3006 else if (strcsequal(p,"LM1.2X002"))
3007 arch &= ( ARCH_WINNT | ARCH_OS2 );
3008 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3010 else if (strcsequal(p,"XENIX CORE"))
3011 arch &= ( ARCH_WINNT | ARCH_OS2 );
3012 else if (strcsequal(p,"Samba")) {
3022 strcpy(remote_arch,"Samba");
3025 strcpy(remote_arch,"WfWg");
3028 strcpy(remote_arch,"Win95");
3031 strcpy(remote_arch,"WinNT");
3034 strcpy(remote_arch,"OS2");
3037 strcpy(remote_arch,"UNKNOWN");
3041 /* possibly reload - change of architecture */
3042 reload_services(True);
3044 /* a special case to stop password server loops */
3045 if (Index == 1 && strequal(remote_machine,myhostname) &&
3046 lp_security()==SEC_SERVER)
3047 exit_server("Password server loop!");
3049 /* Check for protocols, most desirable first */
3050 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3052 p = smb_buf(inbuf)+1;
3054 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3055 while (p < (smb_buf(inbuf) + bcc))
3057 if (strequal(p,supported_protocols[protocol].proto_name))
3066 SSVAL(outbuf,smb_vwv0,choice);
3068 extern fstring remote_proto;
3069 strcpy(remote_proto,supported_protocols[protocol].short_name);
3070 reload_services(True);
3071 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3072 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3075 DEBUG(0,("No protocol supported !\n"));
3077 SSVAL(outbuf,smb_vwv0,choice);
3079 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3085 /****************************************************************************
3086 close all open files for a connection
3087 ****************************************************************************/
3088 static void close_open_files(int cnum)
3091 for (i=0;i<MAX_OPEN_FILES;i++)
3092 if( Files[i].cnum == cnum && Files[i].open) {
3099 /****************************************************************************
3101 ****************************************************************************/
3102 void close_cnum(int cnum, uint16 vuid)
3104 DirCacheFlush(SNUM(cnum));
3108 if (!OPEN_CNUM(cnum))
3110 DEBUG(0,("Can't close cnum %d\n",cnum));
3114 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3116 remote_machine,client_addr(),
3117 lp_servicename(SNUM(cnum))));
3119 yield_connection(cnum,
3120 lp_servicename(SNUM(cnum)),
3121 lp_max_connections(SNUM(cnum)));
3123 if (lp_status(SNUM(cnum)))
3124 yield_connection(cnum,"STATUS.",MAXSTATUS);
3126 close_open_files(cnum);
3127 dptr_closecnum(cnum);
3129 /* execute any "postexec = " line */
3130 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3133 strcpy(cmd,lp_postexec(SNUM(cnum)));
3134 standard_sub(cnum,cmd);
3135 smbrun(cmd,NULL,False);
3140 /* execute any "root postexec = " line */
3141 if (*lp_rootpostexec(SNUM(cnum)))
3144 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3145 standard_sub(cnum,cmd);
3146 smbrun(cmd,NULL,False);
3149 Connections[cnum].open = False;
3150 num_connections_open--;
3151 if (Connections[cnum].ngroups && Connections[cnum].groups)
3153 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3154 free(Connections[cnum].groups);
3155 free(Connections[cnum].igroups);
3156 Connections[cnum].groups = NULL;
3157 Connections[cnum].igroups = NULL;
3158 Connections[cnum].ngroups = 0;
3161 string_set(&Connections[cnum].user,"");
3162 string_set(&Connections[cnum].dirpath,"");
3163 string_set(&Connections[cnum].connectpath,"");
3167 /****************************************************************************
3168 simple routines to do connection counting
3169 ****************************************************************************/
3170 BOOL yield_connection(int cnum,char *name,int max_connections)
3172 struct connect_record crec;
3175 int mypid = getpid();
3178 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3180 if (max_connections <= 0)
3183 bzero(&crec,sizeof(crec));
3185 strcpy(fname,lp_lockdir());
3186 standard_sub(cnum,fname);
3187 trim_string(fname,"","/");
3191 strcat(fname,".LCK");
3193 f = fopen(fname,"r+");
3196 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3200 fseek(f,0,SEEK_SET);
3202 /* find a free spot */
3203 for (i=0;i<max_connections;i++)
3205 if (fread(&crec,sizeof(crec),1,f) != 1)
3207 DEBUG(2,("Entry not found in lock file %s\n",fname));
3211 if (crec.pid == mypid && crec.cnum == cnum)
3215 if (crec.pid != mypid || crec.cnum != cnum)
3218 DEBUG(2,("Entry not found in lock file %s\n",fname));
3222 bzero((void *)&crec,sizeof(crec));
3224 /* remove our mark */
3225 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3226 fwrite(&crec,sizeof(crec),1,f) != 1)
3228 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3233 DEBUG(3,("Yield successful\n"));
3240 /****************************************************************************
3241 simple routines to do connection counting
3242 ****************************************************************************/
3243 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3245 struct connect_record crec;
3248 int snum = SNUM(cnum);
3252 if (max_connections <= 0)
3255 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3257 strcpy(fname,lp_lockdir());
3258 standard_sub(cnum,fname);
3259 trim_string(fname,"","/");
3261 if (!directory_exist(fname,NULL))
3266 strcat(fname,".LCK");
3268 if (!file_exist(fname,NULL))
3270 int oldmask = umask(022);
3271 f = fopen(fname,"w");
3276 total_recs = file_size(fname) / sizeof(crec);
3278 f = fopen(fname,"r+");
3282 DEBUG(1,("couldn't open lock file %s\n",fname));
3286 /* find a free spot */
3287 for (i=0;i<max_connections;i++)
3290 if (i>=total_recs ||
3291 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3292 fread(&crec,sizeof(crec),1,f) != 1)
3294 if (foundi < 0) foundi = i;
3298 if (Clear && crec.pid && !process_exists(crec.pid))
3300 fseek(f,i*sizeof(crec),SEEK_SET);
3301 bzero((void *)&crec,sizeof(crec));
3302 fwrite(&crec,sizeof(crec),1,f);
3303 if (foundi < 0) foundi = i;
3306 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3315 DEBUG(3,("no free locks in %s\n",fname));
3320 /* fill in the crec */
3321 bzero((void *)&crec,sizeof(crec));
3322 crec.magic = 0x280267;
3323 crec.pid = getpid();
3325 crec.uid = Connections[cnum].uid;
3326 crec.gid = Connections[cnum].gid;
3327 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3328 crec.start = time(NULL);
3330 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3331 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3334 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3335 fwrite(&crec,sizeof(crec),1,f) != 1)
3346 /*******************************************************************
3347 prepare to dump a core file - carefully!
3348 ********************************************************************/
3349 static BOOL dump_core(void)
3353 strcpy(dname,debugf);
3354 if ((p=strrchr(dname,'/'))) *p=0;
3355 strcat(dname,"/corefiles");
3357 sys_chown(dname,getuid(),getgid());
3359 if (chdir(dname)) return(False);
3362 #ifndef NO_GETRLIMIT
3366 getrlimit(RLIMIT_CORE, &rlp);
3367 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3368 setrlimit(RLIMIT_CORE, &rlp);
3369 getrlimit(RLIMIT_CORE, &rlp);
3370 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3376 DEBUG(0,("Dumping core in %s\n",dname));
3381 /****************************************************************************
3383 ****************************************************************************/
3384 void exit_server(char *reason)
3386 static int firsttime=1;
3389 if (!firsttime) exit(0);
3393 DEBUG(2,("Closing connections\n"));
3394 for (i=0;i<MAX_CONNECTIONS;i++)
3395 if (Connections[i].open)
3398 if (dcelogin_atmost_once)
3402 int oldlevel = DEBUGLEVEL;
3404 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3406 show_msg(last_inbuf);
3407 DEBUGLEVEL = oldlevel;
3408 DEBUG(0,("===============================================================\n"));
3410 if (dump_core()) return;
3414 #ifdef FAST_SHARE_MODES
3415 stop_share_mode_mgmt();
3416 #endif /* FAST_SHARE_MODES */
3418 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3422 /****************************************************************************
3423 do some standard substitutions in a string
3424 ****************************************************************************/
3425 void standard_sub(int cnum,char *s)
3427 if (!strchr(s,'%')) return;
3429 if (VALID_CNUM(cnum))
3431 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3432 string_sub(s,"%P",Connections[cnum].connectpath);
3433 string_sub(s,"%u",Connections[cnum].user);
3434 if (strstr(s,"%H")) {
3435 char *home = get_home_dir(Connections[cnum].user);
3436 if (home) string_sub(s,"%H",home);
3438 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3440 standard_sub_basic(s);
3444 These flags determine some of the permissions required to do an operation
3446 Note that I don't set NEED_WRITE on some write operations because they
3447 are used by some brain-dead clients when printing, and I don't want to
3448 force write permissions on print services.
3450 #define AS_USER (1<<0)
3451 #define NEED_WRITE (1<<1)
3452 #define TIME_INIT (1<<2)
3453 #define CAN_IPC (1<<3)
3454 #define AS_GUEST (1<<5)
3458 define a list of possible SMB messages and their corresponding
3459 functions. Any message that has a NULL function is unimplemented -
3460 please feel free to contribute implementations!
3462 struct smb_message_struct
3476 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3477 {SMBtcon,"SMBtcon",reply_tcon,0},
3478 {SMBtdis,"SMBtdis",reply_tdis,0},
3479 {SMBexit,"SMBexit",reply_exit,0},
3480 {SMBioctl,"SMBioctl",reply_ioctl,0},
3481 {SMBecho,"SMBecho",reply_echo,0},
3482 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3483 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3484 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3485 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3486 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3487 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3488 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3489 {SMBopen,"SMBopen",reply_open,AS_USER},
3491 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3492 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3493 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3495 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3496 {SMBread,"SMBread",reply_read,AS_USER},
3497 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3498 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3499 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3500 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3501 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3502 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3504 /* this is a Pathworks specific call, allowing the
3505 changing of the root path */
3506 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3508 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3509 {SMBflush,"SMBflush",reply_flush,AS_USER},
3510 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3511 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3512 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3513 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3514 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3515 {SMBlock,"SMBlock",reply_lock,AS_USER},
3516 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3518 /* CORE+ PROTOCOL FOLLOWS */
3520 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3521 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3522 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3523 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3524 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3526 /* LANMAN1.0 PROTOCOL FOLLOWS */
3528 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3529 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3530 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3531 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3532 {SMBwritec,"SMBwritec",NULL,AS_USER},
3533 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3534 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3535 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3536 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3537 {SMBioctls,"SMBioctls",NULL,AS_USER},
3538 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3539 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3541 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3542 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3543 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3544 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3546 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3547 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3548 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3550 /* LANMAN2.0 PROTOCOL FOLLOWS */
3551 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3552 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3553 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3554 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3556 /* messaging routines */
3557 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3558 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3559 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3560 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3562 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3564 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3565 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3566 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3567 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3570 /****************************************************************************
3571 return a string containing the function name of a SMB command
3572 ****************************************************************************/
3573 char *smb_fn_name(int type)
3575 static char *unknown_name = "SMBunknown";
3576 static int num_smb_messages =
3577 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3580 for (match=0;match<num_smb_messages;match++)
3581 if (smb_messages[match].code == type)
3584 if (match == num_smb_messages)
3585 return(unknown_name);
3587 return(smb_messages[match].name);
3591 /****************************************************************************
3592 do a switch on the message type, and return the response size
3593 ****************************************************************************/
3594 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3598 static int num_smb_messages =
3599 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3603 struct timeval msg_start_time;
3604 struct timeval msg_end_time;
3605 static unsigned long total_time = 0;
3607 GetTimeOfDay(&msg_start_time);
3614 last_message = type;
3616 /* make sure this is an SMB packet */
3617 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3619 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3623 for (match=0;match<num_smb_messages;match++)
3624 if (smb_messages[match].code == type)
3627 if (match == num_smb_messages)
3629 DEBUG(0,("Unknown message type %d!\n",type));
3630 outsize = reply_unknown(inbuf,outbuf);
3634 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3635 if (smb_messages[match].fn)
3637 int cnum = SVAL(inbuf,smb_tid);
3638 int flags = smb_messages[match].flags;
3639 uint16 session_tag = SVAL(inbuf,smb_uid);
3641 /* does this protocol need to be run as root? */
3642 if (!(flags & AS_USER))
3645 /* does this protocol need to be run as the connected user? */
3646 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3647 if (flags & AS_GUEST)
3650 return(ERROR(ERRSRV,ERRinvnid));
3652 /* this code is to work around a bug is MS client 3 without
3653 introducing a security hole - it needs to be able to do
3654 print queue checks as guest if it isn't logged in properly */
3655 if (flags & AS_USER)
3658 /* does it need write permission? */
3659 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3660 return(ERROR(ERRSRV,ERRaccess));
3662 /* ipc services are limited */
3663 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3664 return(ERROR(ERRSRV,ERRaccess));
3666 /* load service specific parameters */
3667 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3668 return(ERROR(ERRSRV,ERRaccess));
3670 /* does this protocol need to be run as guest? */
3671 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3672 return(ERROR(ERRSRV,ERRaccess));
3676 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3680 outsize = reply_unknown(inbuf,outbuf);
3685 GetTimeOfDay(&msg_end_time);
3686 if (!(smb_messages[match].flags & TIME_INIT))
3688 smb_messages[match].time = 0;
3689 smb_messages[match].flags |= TIME_INIT;
3692 unsigned long this_time =
3693 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3694 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3695 smb_messages[match].time += this_time;
3696 total_time += this_time;
3698 DEBUG(2,("TIME %s %d usecs %g pct\n",
3699 smb_fn_name(type),smb_messages[match].time,
3700 (100.0*smb_messages[match].time) / total_time));
3707 /****************************************************************************
3708 construct a chained reply and add it to the already made reply
3709 **************************************************************************/
3710 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3712 static char *orig_inbuf;
3713 static char *orig_outbuf;
3714 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3715 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3716 char *inbuf2, *outbuf2;
3718 char inbuf_saved[smb_wct];
3719 char outbuf_saved[smb_wct];
3720 extern int chain_size;
3721 int wct = CVAL(outbuf,smb_wct);
3722 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3724 /* maybe its not chained */
3725 if (smb_com2 == 0xFF) {
3726 CVAL(outbuf,smb_vwv0) = 0xFF;
3730 if (chain_size == 0) {
3731 /* this is the first part of the chain */
3733 orig_outbuf = outbuf;
3736 /* we need to tell the client where the next part of the reply will be */
3737 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3738 CVAL(outbuf,smb_vwv0) = smb_com2;
3740 /* remember how much the caller added to the chain, only counting stuff
3741 after the parameter words */
3742 chain_size += outsize - smb_wct;
3744 /* work out pointers into the original packets. The
3745 headers on these need to be filled in */
3746 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3747 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3749 /* remember the original command type */
3750 smb_com1 = CVAL(orig_inbuf,smb_com);
3752 /* save the data which will be overwritten by the new headers */
3753 memcpy(inbuf_saved,inbuf2,smb_wct);
3754 memcpy(outbuf_saved,outbuf2,smb_wct);
3756 /* give the new packet the same header as the last part of the SMB */
3757 memmove(inbuf2,inbuf,smb_wct);
3759 /* create the in buffer */
3760 CVAL(inbuf2,smb_com) = smb_com2;
3762 /* create the out buffer */
3763 bzero(outbuf2,smb_size);
3764 set_message(outbuf2,0,0,True);
3765 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3767 memcpy(outbuf2+4,inbuf2+4,4);
3768 CVAL(outbuf2,smb_rcls) = SUCCESS;
3769 CVAL(outbuf2,smb_reh) = 0;
3770 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3772 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3773 SSVAL(outbuf2,smb_err,SUCCESS);
3774 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3775 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3776 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3777 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3779 DEBUG(3,("Chained message\n"));
3782 /* process the request */
3783 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3784 bufsize-chain_size);
3786 /* copy the new reply and request headers over the old ones, but
3787 preserve the smb_com field */
3788 memmove(orig_outbuf,outbuf2,smb_wct);
3789 CVAL(orig_outbuf,smb_com) = smb_com1;
3791 /* restore the saved data, being careful not to overwrite any
3792 data from the reply header */
3793 memcpy(inbuf2,inbuf_saved,smb_wct);
3795 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3796 if (ofs < 0) ofs = 0;
3797 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3805 /****************************************************************************
3806 construct a reply to the incoming packet
3807 ****************************************************************************/
3808 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3810 int type = CVAL(inbuf,smb_com);
3812 int msg_type = CVAL(inbuf,0);
3813 extern int chain_size;
3815 smb_last_time = time(NULL);
3820 bzero(outbuf,smb_size);
3823 return(reply_special(inbuf,outbuf));
3825 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3826 set_message(outbuf,0,0,True);
3828 memcpy(outbuf+4,inbuf+4,4);
3829 CVAL(outbuf,smb_rcls) = SUCCESS;
3830 CVAL(outbuf,smb_reh) = 0;
3831 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3833 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3834 SSVAL(outbuf,smb_err,SUCCESS);
3835 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3836 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3837 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3838 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3840 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3842 outsize += chain_size;
3845 smb_setlen(outbuf,outsize - 4);
3850 /****************************************************************************
3851 process commands from the client
3852 ****************************************************************************/
3853 static void process(void)
3855 static int trans_num = 0;
3859 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3860 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3861 if ((InBuffer == NULL) || (OutBuffer == NULL))
3864 InBuffer += SMB_ALIGNMENT;
3865 OutBuffer += SMB_ALIGNMENT;
3868 DEBUG(3,("priming nmbd\n"));
3871 ip = *interpret_addr2("localhost");
3872 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3874 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3884 int deadtime = lp_deadtime()*60;
3886 int last_keepalive=0;
3889 deadtime = DEFAULT_SMBD_TIMEOUT;
3891 if (lp_readprediction())
3892 do_read_prediction();
3896 for (counter=SMBD_SELECT_LOOP;
3897 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3898 counter += SMBD_SELECT_LOOP)
3902 BOOL allidle = True;
3903 extern int keepalive;
3905 if (smb_read_error == READ_EOF) {
3906 DEBUG(3,("end of file from client\n"));
3910 if (smb_read_error == READ_ERROR) {
3911 DEBUG(3,("receive_smb error (%s) exiting\n",
3918 /* become root again if waiting */
3921 /* check for smb.conf reload */
3922 if (!(counter%SMBD_RELOAD_CHECK))
3923 reload_services(True);
3926 /* check the share modes every 10 secs */
3927 if (!(counter%SHARE_MODES_CHECK))
3928 check_share_modes();
3930 /* clean the share modes every 5 minutes */
3931 if (!(counter%SHARE_MODES_CLEAN))
3932 clean_share_modes();
3935 /* automatic timeout if all connections are closed */
3936 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3937 DEBUG(2,("%s Closing idle connection\n",timestring()));
3941 if (keepalive && (counter-last_keepalive)>keepalive) {
3942 extern int password_client;
3943 if (!send_keepalive(Client)) {
3944 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3947 /* also send a keepalive to the password server if its still
3949 if (password_client != -1)
3950 send_keepalive(password_client);
3951 last_keepalive = counter;
3954 /* check for connection timeouts */
3955 for (i=0;i<MAX_CONNECTIONS;i++)
3956 if (Connections[i].open)
3958 /* close dirptrs on connections that are idle */
3959 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3962 if (Connections[i].num_files_open > 0 ||
3963 (t-Connections[i].lastused)<deadtime)
3967 if (allidle && num_connections_open>0) {
3968 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3973 msg_type = CVAL(InBuffer,0);
3974 msg_flags = CVAL(InBuffer,1);
3975 type = CVAL(InBuffer,smb_com);
3977 len = smb_len(InBuffer);
3979 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3983 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3986 if(trans_num == 1 && VT_Check(InBuffer)) {
3996 nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
3999 if (CVAL(OutBuffer,0) == 0)
4000 show_msg(OutBuffer);
4002 if (nread != smb_len(OutBuffer) + 4)
4004 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4006 smb_len(OutBuffer)));
4009 send_smb(Client,OutBuffer);
4016 /****************************************************************************
4017 initialise connect, service and file structs
4018 ****************************************************************************/
4019 static void init_structs(void )
4022 get_myname(myhostname,NULL);
4024 for (i=0;i<MAX_CONNECTIONS;i++)
4026 Connections[i].open = False;
4027 Connections[i].num_files_open=0;
4028 Connections[i].lastused=0;
4029 Connections[i].used=False;
4030 string_init(&Connections[i].user,"");
4031 string_init(&Connections[i].dirpath,"");
4032 string_init(&Connections[i].connectpath,"");
4033 string_init(&Connections[i].origpath,"");
4036 for (i=0;i<MAX_OPEN_FILES;i++)
4038 Files[i].open = False;
4039 string_init(&Files[i].name,"");
4043 for (i=0;i<MAX_OPEN_FILES;i++)
4045 file_fd_struct *fd_ptr = &FileFd[i];
4046 fd_ptr->ref_count = 0;
4047 fd_ptr->dev = (int32)-1;
4048 fd_ptr->inode = (int32)-1;
4050 fd_ptr->fd_readonly = -1;
4051 fd_ptr->fd_writeonly = -1;
4052 fd_ptr->real_open_flags = -1;
4058 /****************************************************************************
4059 usage on the program
4060 ****************************************************************************/
4061 static void usage(char *pname)
4063 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4065 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4066 printf("Version %s\n",VERSION);
4067 printf("\t-D become a daemon\n");
4068 printf("\t-p port listen on the specified port\n");
4069 printf("\t-d debuglevel set the debuglevel\n");
4070 printf("\t-l log basename. Basename for log/debug files\n");
4071 printf("\t-s services file. Filename of services file\n");
4072 printf("\t-P passive only\n");
4073 printf("\t-a overwrite log file, don't append\n");
4078 /****************************************************************************
4080 ****************************************************************************/
4081 int main(int argc,char *argv[])
4083 extern BOOL append_log;
4084 /* shall I run as a daemon */
4085 BOOL is_daemon = False;
4086 int port = SMB_PORT;
4088 extern char *optarg;
4089 char pidFile[100] = { 0 };
4091 #ifdef NEED_AUTH_PARAMETERS
4092 set_auth_parameters(argc,argv);
4103 strcpy(debugf,SMBLOGFILE);
4105 setup_logging(argv[0],False);
4107 charset_initialise(-1);
4109 /* make absolutely sure we run as root - to handle cases whre people
4110 are crazy enough to have it setuid */
4120 fault_setup(exit_server);
4121 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4123 /* we want total control over the permissions on created files,
4124 so set our umask to 0 */
4131 /* this is for people who can't start the program correctly */
4132 while (argc > 1 && (*argv[1] != '-'))
4138 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4142 strncpy(pidFile, optarg, sizeof(pidFile));
4145 strcpy(user_socket_options,optarg);
4148 strcpy(scope,optarg);
4152 extern BOOL passive;
4157 strcpy(servicesf,optarg);
4160 strcpy(debugf,optarg);
4164 extern BOOL append_log;
4165 append_log = !append_log;
4175 DEBUGLEVEL = atoi(optarg);
4178 port = atoi(optarg);
4191 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4192 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4194 #ifndef NO_GETRLIMIT
4195 #ifdef RLIMIT_NOFILE
4198 getrlimit(RLIMIT_NOFILE, &rlp);
4199 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4200 setrlimit(RLIMIT_NOFILE, &rlp);
4201 getrlimit(RLIMIT_NOFILE, &rlp);
4202 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4208 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4209 getuid(),getgid(),geteuid(),getegid()));
4211 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4213 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4219 if (!reload_services(False))
4222 charset_initialise(lp_client_code_page());
4224 strcpy(myworkgroup, lp_workgroup());
4226 #ifndef NO_SIGNAL_TEST
4227 signal(SIGHUP,SIGNAL_CAST sig_hup);
4230 DEBUG(3,("%s loaded services\n",timestring()));
4232 if (!is_daemon && !is_a_socket(0))
4234 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4240 DEBUG(3,("%s becoming a daemon\n",timestring()));
4249 if ((fd = open(pidFile,
4250 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4252 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4255 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4257 DEBUG(0,("ERROR: smbd is already running\n"));
4260 sprintf(buf, "%u\n", (unsigned int) getpid());
4261 if (write(fd, buf, strlen(buf)) < 0)
4263 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4266 /* Leave pid file open & locked for the duration... */
4269 if (!open_sockets(is_daemon,port))
4272 #ifdef FAST_SHARE_MODES
4273 if (!start_share_mode_mgmt())
4275 #endif /* FAST_SHARE_MODES */
4277 /* possibly reload the services file. */
4278 reload_services(True);
4280 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4284 if (sys_chroot(lp_rootdir()) == 0)
4285 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4291 exit_server("normal exit");