2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 pstring servicesf = CONFIGFILE;
29 pstring OriginalDir ="/";
30 extern pstring debugf;
31 extern pstring sesssetup_user;
33 char *InBuffer = NULL;
34 char *OutBuffer = NULL;
35 char *last_inbuf = NULL;
40 BOOL share_mode_pending = False;
42 /* have I done a become_user? */
47 /* the last message the was processed */
48 int last_message = -1;
50 /* a useful macro to debug the last message processed */
51 #define LAST_MESSAGE() smb_fn_name(last_message)
54 extern int DEBUGLEVEL;
55 extern int case_default;
56 extern BOOL case_sensitive;
57 extern BOOL case_preserve;
58 extern BOOL use_mangled_map;
59 extern BOOL short_case_preserve;
60 extern BOOL case_mangle;
61 extern time_t smb_last_time;
63 extern pstring user_socket_options;
65 connection_struct Connections[MAX_CONNECTIONS];
66 files_struct Files[MAX_OPEN_FILES];
70 int maxxmit = BUFFER_SIZE;
74 /* a fnum to use when chaining */
77 /* number of open connections */
78 static int num_connections_open = 0;
80 extern fstring remote_machine;
83 /* these can be set by some functions to override the error codes */
84 int unix_ERR_class=SUCCESS;
88 extern int extra_time_offset;
90 extern pstring myhostname;
91 extern struct in_addr myip;
94 static int find_free_connection(int hash);
97 extern void generate_next_challenge(char *challenge);
98 extern void set_challenge(char *challenge);
101 /* for readability... */
102 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
103 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
104 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
105 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
106 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
110 /****************************************************************************
111 change a dos mode to a unix mode
112 base permission for files:
113 everybody gets read bit set
114 dos readonly is represented in unix by removing everyone's write bit
115 dos archive is represented in unix by the user's execute bit
116 dos system is represented in unix by the group's execute bit
117 dos hidden is represented in unix by the other's execute bit
118 base permission for directories:
119 dos directory is represented in unix by unix's dir bit and the exec bit
120 ****************************************************************************/
121 mode_t unix_mode(int cnum,int dosmode)
123 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
125 if ( !IS_DOS_READONLY(dosmode) )
126 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
128 if (IS_DOS_DIR(dosmode))
129 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
131 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
134 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
137 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
140 result &= CREATE_MODE(cnum);
145 /****************************************************************************
146 change a unix mode to a dos mode
147 ****************************************************************************/
148 int dos_mode(int cnum,char *path,struct stat *sbuf)
153 if (!CAN_WRITE(cnum) || !((sbuf->st_mode & S_IWOTH) ||
154 Connections[cnum].admin_user ||
155 ((sbuf->st_mode & S_IWUSR) &&
156 Connections[cnum].uid==sbuf->st_uid) ||
157 ((sbuf->st_mode & S_IWGRP) &&
158 in_group(sbuf->st_gid,Connections[cnum].gid,
159 Connections[cnum].ngroups,
160 Connections[cnum].igroups))))
163 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
164 if (!((sbuf->st_mode & S_IWOTH) ||
165 Connections[cnum].admin_user ||
166 ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid==sbuf->st_uid) ||
167 ((sbuf->st_mode & S_IWGRP) &&
168 in_group(sbuf->st_gid,Connections[cnum].gid,
169 Connections[cnum].ngroups,Connections[cnum].igroups))))
172 if ((sbuf->st_mode & S_IWUSR) == 0)
177 if ((sbuf->st_mode & S_IXUSR) != 0)
180 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
183 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
186 if (S_ISDIR(sbuf->st_mode))
187 result = aDIR | (result & aRONLY);
190 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
194 /* hide files with a name starting with a . */
195 if (lp_hide_dot_files(SNUM(cnum)))
197 char *p = strrchr(path,'/');
203 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
211 /*******************************************************************
212 chmod a file - but preserve some bits
213 ********************************************************************/
214 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
223 if (sys_stat(fname,st)) return(-1);
226 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
228 if (dos_mode(cnum,fname,st) == dosmode) return(0);
230 unixmode = unix_mode(cnum,dosmode);
232 /* preserve the s bits */
233 mask |= (S_ISUID | S_ISGID);
235 /* preserve the t bit */
240 /* possibly preserve the x bits */
241 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
242 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
243 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
245 unixmode |= (st->st_mode & mask);
247 /* if we previously had any r bits set then leave them alone */
248 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
249 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
253 /* if we previously had any w bits set then leave them alone
254 if the new mode is not rdonly */
255 if (!IS_DOS_READONLY(dosmode) &&
256 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
257 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
261 return(chmod(fname,unixmode));
265 /****************************************************************************
266 check if two filenames are equal
268 this needs to be careful about whether we are case sensitive
269 ****************************************************************************/
270 static BOOL fname_equal(char *name1, char *name2)
272 int l1 = strlen(name1);
273 int l2 = strlen(name2);
275 /* handle filenames ending in a single dot */
276 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
280 ret = fname_equal(name1,name2);
285 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
289 ret = fname_equal(name1,name2);
294 /* now normal filename handling */
296 return(strcmp(name1,name2) == 0);
298 return(strequal(name1,name2));
302 /****************************************************************************
303 mangle the 2nd name and check if it is then equal to the first name
304 ****************************************************************************/
305 static BOOL mangled_equal(char *name1, char *name2)
312 strcpy(tmpname,name2);
313 mangle_name_83(tmpname);
315 return(strequal(name1,tmpname));
319 /****************************************************************************
320 scan a directory to find a filename, matching without case sensitivity
322 If the name looks like a mangled name then try via the mangling functions
323 ****************************************************************************/
324 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
331 mangled = is_mangled(name);
333 /* handle null paths */
337 if (docache && (dname = DirCacheCheck(path,name,snum))) {
343 check_mangled_stack(name);
345 /* open the directory */
346 if (!(cur_dir = OpenDir(path)))
348 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
352 /* now scan for matching names */
353 while ((dname = ReadDirName(cur_dir)))
356 (strequal(dname,".") || strequal(dname,"..")))
360 if (!name_map_mangle(name2,False,snum)) continue;
362 if ((mangled && mangled_equal(name,name2))
363 || fname_equal(name, name2))
365 /* we've found the file, change it's name and return */
366 if (docache) DirCacheAdd(path,name,dname,snum);
377 /****************************************************************************
378 This routine is called to convert names from the dos namespace to unix
379 namespace. It needs to handle any case conversions, mangling, format
382 We assume that we have already done a chdir() to the right "root" directory
385 The function will return False if some part of the name except for the last
386 part cannot be resolved
387 ****************************************************************************/
388 BOOL unix_convert(char *name,int cnum)
396 /* convert to basic unix format - removing \ chars and cleaning it up */
398 unix_clean_name(name);
400 if (!case_sensitive &&
401 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
404 /* names must be relative to the root of the service - trim any leading /.
405 also trim trailing /'s */
406 trim_string(name,"/","/");
408 /* check if it's a printer file */
409 if (Connections[cnum].printer)
411 if ((! *name) || strchr(name,'/') || !is_8_3(name))
415 sprintf(name2,"%.6s.XXXXXX",remote_machine);
416 /* sanitise the name */
417 for (s=name2 ; *s ; s++)
418 if (!issafe(*s)) *s = '_';
419 strcpy(name,(char *)mktemp(name2));
424 /* stat the name - if it exists then we are all done! */
425 if (sys_stat(name,&st) == 0)
428 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
430 /* a special case - if we don't have any mangling chars and are case
431 sensitive then searching won't help */
432 if (case_sensitive && !is_mangled(name) &&
433 !lp_strip_dot() && !use_mangled_map)
436 /* now we need to recursively match the name against the real
437 directory structure */
440 while (strncmp(start,"./",2) == 0)
443 /* now match each part of the path name separately, trying the names
444 as is first, then trying to scan the directory for matching names */
445 for (;start;start = (end?end+1:(char *)NULL))
447 /* pinpoint the end of this section of the filename */
448 end = strchr(start, '/');
450 /* chop the name at this point */
453 /* check if the name exists up to this point */
454 if (sys_stat(name, &st) == 0)
456 /* it exists. it must either be a directory or this must be
457 the last part of the path for it to be OK */
458 if (end && !(st.st_mode & S_IFDIR))
460 /* an intermediate part of the name isn't a directory */
461 DEBUG(5,("Not a dir %s\n",start));
472 /* remember the rest of the pathname so it can be restored
474 if (end) strcpy(rest,end+1);
477 /* try to find this part of the path in the directory */
478 if (strchr(start,'?') || strchr(start,'*') ||
479 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
483 /* an intermediate part of the name can't be found */
484 DEBUG(5,("Intermediate not found %s\n",start));
489 /* just the last part of the name doesn't exist */
490 /* we may need to strupper() or strlower() it in case
491 this conversion is being used for file creation
493 /* if the filename is of mixed case then don't normalise it */
494 if (!case_preserve &&
495 (!strhasupper(start) || !strhaslower(start)))
498 /* check on the mangled stack to see if we can recover the
499 base of the filename */
500 if (is_mangled(start))
501 check_mangled_stack(start);
503 DEBUG(5,("New file %s\n",start));
507 /* restore the rest of the string */
510 strcpy(start+strlen(start)+1,rest);
511 end = start + strlen(start);
515 /* add to the dirpath that we have resolved so far */
516 if (*dirpath) strcat(dirpath,"/");
517 strcat(dirpath,start);
519 /* restore the / that we wiped out earlier */
523 /* the name has been resolved */
524 DEBUG(5,("conversion finished %s\n",name));
533 /****************************************************************************
534 try to get the disk space from disk quotas (LINUX version)
535 ****************************************************************************/
537 If you didn't make the symlink to the quota package, too bad :(
539 #include "quota/quotactl.c"
540 #include "quota/hasquota.c"
541 static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
553 /* find the block device file */
555 if ( stat(path, &S) == -1 )
560 fp = setmntent(MOUNTED,"r");
563 while ((mnt = getmntent(fp)) != (struct mntent *) 0) {
564 if ( stat(mnt->mnt_dir,&S) == -1 )
566 if (S.st_dev == devno) {
576 qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
578 if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA))
581 if (!hasquota(mnt, USRQUOTA, &qfpathname))
584 euser_id = geteuid();
587 if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) {
588 if ((fd = open(qfpathname, O_RDONLY)) < 0) {
592 lseek(fd, (long) dqoff(euser_id), L_SET);
593 switch (read(fd, &D, sizeof(struct dqblk))) {
595 memset((caddr_t)&D, 0, sizeof(struct dqblk));
597 case sizeof(struct dqblk): /* OK */
608 if (D.dqb_bsoftlimit==0)
610 if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit))
613 *dsize = D.dqb_curblocks;
616 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
617 *dsize = D.dqb_bsoftlimit;
623 /****************************************************************************
624 try to get the disk space from disk quotas
625 ****************************************************************************/
626 static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
628 uid_t user_id, euser_id;
633 /* find the block device file */
634 if ((stat(path, &S)<0) ||
635 (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
637 euser_id = geteuid();
640 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
642 setresuid(euser_id,-1,-1);
644 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
646 if (setresuid(user_id,-1,-1))
647 DEBUG(5,("Unable to reset uid to %d\n", user_id));
649 /* Use softlimit to determine disk space, except when it has been exceeded */
656 *dsize =D.dqb_curblocks;
661 /* Use softlimit to determine disk space, except when it has been exceeded */
662 if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit))
665 *dsize = D.dqb_curblocks;
668 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
669 *dsize = D.dqb_bsoftlimit;
674 /****************************************************************************
675 try to get the disk space from disk quotas (CRAY VERSION)
676 ****************************************************************************/
677 static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
683 static dev_t devno_cached = 0 ;
684 static char name[MNTMAXSTR] ;
685 struct q_request request ;
686 struct qf_header header ;
687 static int quota_default = 0 ;
690 if ( stat(path,&sbuf) == -1 )
693 devno = sbuf.st_dev ;
695 if ( devno != devno_cached ) {
697 devno_cached = devno ;
699 if ((fd = setmntent(KMTAB)) == NULL)
704 while ((mnt = getmntent(fd)) != NULL) {
706 if ( stat(mnt->mnt_dir,&sbuf) == -1 )
709 if (sbuf.st_dev == devno) {
718 strcpy(name,mnt->mnt_dir) ;
725 request.qf_magic = QF_MAGIC ;
726 request.qf_entry.id = geteuid() ;
728 if (quotactl(name, Q_GETQUOTA, &request) == -1)
731 if ( ! request.user )
734 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
736 if ( ! quota_default ) {
738 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
741 quota_default = header.user_h.def_fq ;
744 *dfree = quota_default ;
746 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
752 *dfree = request.qf_entry.user_q.f_quota ;
756 *dsize = request.qf_entry.user_q.f_use ;
764 *bsize = 4096 ; /* Cray blocksize */
774 /****************************************************************************
775 normalise for DOS usage
776 ****************************************************************************/
777 static void disk_norm(int *bsize,int *dfree,int *dsize)
779 /* check if the disk is beyond the max disk size */
780 int maxdisksize = lp_maxdisksize();
782 /* convert to blocks - and don't overflow */
783 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
784 if (*dsize > maxdisksize) *dsize = maxdisksize;
785 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
790 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
795 if (*bsize > WORDMAX )
798 if (*dsize > WORDMAX)
800 if (*dfree > WORDMAX)
807 /****************************************************************************
808 return number of 1K blocks available on a path and total number
809 ****************************************************************************/
810 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
812 char *df_command = lp_dfree_command();
826 if (disk_quotas(path, bsize, dfree, dsize))
828 disk_norm(bsize,dfree,dsize);
829 return(((*bsize)/1024)*(*dfree));
834 /* possibly use system() to get the result */
835 if (df_command && *df_command)
841 sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
842 sprintf(syscmd,"%s %s",df_command,path);
843 standard_sub_basic(syscmd);
845 ret = smbrun(syscmd,outfile);
846 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
849 FILE *f = fopen(outfile,"r");
855 fscanf(f,"%d %d %d",dsize,dfree,bsize);
859 DEBUG(0,("Can't open %s\n",outfile));
863 disk_norm(bsize,dfree,dsize);
864 return(((*bsize)/1024)*(*dfree));
868 DEBUG(1,("Warning - no statfs function\n"));
872 if (statfs(path,&fs,sizeof(fs),0) != 0)
875 if (statvfs(path, &fs))
878 if (statfs(path,&fs,sizeof(fs)) == -1)
880 if (statfs(path,&fs) == -1)
882 #endif /* USE_STATVFS */
885 DEBUG(3,("dfree call failed code errno=%d\n",errno));
889 return(((*bsize)/1024)*(*dfree));
894 *dfree = fs.fd_req.bfree;
895 *dsize = fs.fd_req.btot;
898 *bsize = fs.f_frsize;
901 /* eg: osf1 has f_fsize = fundamental filesystem block size,
902 f_bsize = optimal transfer block size (MX: 94-04-19) */
907 #endif /* USE_STATVFS */
912 *dfree = fs.f_bavail;
914 *dsize = fs.f_blocks;
917 #if defined(SCO) || defined(ISC) || defined(MIPS)
921 /* handle rediculous bsize values - some OSes are broken */
922 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
924 disk_norm(bsize,dfree,dsize);
930 DEBUG(0,("dfree seems to be broken on your system\n"));
931 *dsize = 20*1024*1024/(*bsize);
932 *dfree = MAX(1,*dfree);
934 return(((*bsize)/1024)*(*dfree));
939 /****************************************************************************
940 wrap it to get filenames right
941 ****************************************************************************/
942 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
944 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
949 /****************************************************************************
950 check a filename - possibly caling reducename
952 This is called by every routine before it allows an operation on a filename.
953 It does any final confirmation necessary to ensure that the filename is
954 a valid one for the user to access.
955 ****************************************************************************/
956 BOOL check_name(char *name,int cnum)
962 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
964 DEBUG(5,("check_name on %s failed\n",name));
969 /****************************************************************************
970 check a filename - possibly caling reducename
971 ****************************************************************************/
972 static void check_for_pipe(char *fname)
974 /* special case of pipe opens */
978 if (strstr(s,"pipe/"))
980 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
981 unix_ERR_class = ERRSRV;
982 unix_ERR_code = ERRaccess;
987 /****************************************************************************
989 ****************************************************************************/
990 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
994 Files[fnum].open = False;
998 strcpy(fname,fname1);
1000 /* check permissions */
1001 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1003 DEBUG(3,("Permission denied opening %s\n",fname));
1004 check_for_pipe(fname);
1008 /* this handles a bug in Win95 - it doesn't say to create the file when it
1010 if (Connections[cnum].printer)
1014 if (flags == O_WRONLY)
1015 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1018 #if UTIME_WORKAROUND
1019 /* XXXX - is this OK?? */
1020 /* this works around a utime bug but can cause other problems */
1021 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1026 Files[fnum].fd = sys_open(fname,flags,mode);
1028 if ((Files[fnum].fd>=0) &&
1029 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1033 strcpy(dname,fname);
1034 p = strrchr(dname,'/');
1036 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1037 lp_minprintspace(SNUM(cnum))) {
1038 close(Files[fnum].fd);
1039 Files[fnum].fd = -1;
1047 /* Fix for files ending in '.' */
1048 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
1049 (strchr(fname,'.')==NULL))
1052 Files[fnum].fd = sys_open(fname,flags,mode);
1055 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
1056 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
1059 char *p = strrchr(fname, '/');
1061 if (p == fname) /* name is "/xxx" */
1063 max_len = pathconf("/", _PC_NAME_MAX);
1066 else if ((p == NULL) || (p == fname))
1069 max_len = pathconf(".", _PC_NAME_MAX);
1074 max_len = pathconf(fname, _PC_NAME_MAX);
1078 if (strlen(p) > max_len)
1080 char tmp = p[max_len];
1083 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
1089 if (Files[fnum].fd < 0)
1091 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1092 fname,strerror(errno),flags));
1093 check_for_pipe(fname);
1097 if (Files[fnum].fd >= 0)
1100 Connections[cnum].num_files_open++;
1101 fstat(Files[fnum].fd,&st);
1102 Files[fnum].mode = st.st_mode;
1103 Files[fnum].open_time = time(NULL);
1104 Files[fnum].size = 0;
1105 Files[fnum].pos = -1;
1106 Files[fnum].open = True;
1107 Files[fnum].mmap_ptr = NULL;
1108 Files[fnum].mmap_size = 0;
1109 Files[fnum].can_lock = True;
1110 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1111 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1112 Files[fnum].share_mode = 0;
1113 Files[fnum].share_pending = False;
1114 Files[fnum].print_file = Connections[cnum].printer;
1115 Files[fnum].modified = False;
1116 Files[fnum].cnum = cnum;
1117 string_set(&Files[fnum].name,fname);
1118 Files[fnum].wbmpx_ptr = NULL;
1121 * If the printer is marked as postscript output a leading
1122 * file identifier to ensure the file is treated as a raw
1124 * This has a similar effect as CtrlD=0 in WIN.INI file.
1125 * tim@fsg.com 09/06/94
1127 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1128 Files[fnum].can_write)
1130 DEBUG(3,("Writing postscript line\n"));
1131 write_file(fnum,"%!\n",3);
1134 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1135 timestring(),Connections[cnum].user,fname,
1136 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1137 Connections[cnum].num_files_open,fnum));
1142 /* mmap it if read-only */
1143 if (!Files[fnum].can_write)
1145 Files[fnum].mmap_size = file_size(fname);
1146 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1147 PROT_READ,MAP_SHARED,Files[fnum].fd,0);
1149 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1151 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1152 Files[fnum].mmap_ptr = NULL;
1158 /*******************************************************************
1160 ********************************************************************/
1161 void sync_file(int fnum)
1164 fsync(Files[fnum].fd);
1168 /****************************************************************************
1169 run a file if it is a magic script
1170 ****************************************************************************/
1171 static void check_magic(int fnum,int cnum)
1173 if (!*lp_magicscript(SNUM(cnum)))
1176 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1180 if (!(p = strrchr(Files[fnum].name,'/')))
1181 p = Files[fnum].name;
1185 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1191 pstring magic_output;
1193 strcpy(fname,Files[fnum].name);
1195 if (*lp_magicoutput(SNUM(cnum)))
1196 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1198 sprintf(magic_output,"%s.out",fname);
1201 ret = smbrun(fname,magic_output);
1202 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1208 /****************************************************************************
1209 close a file - possibly invalidating the read prediction
1210 ****************************************************************************/
1211 void close_file(int fnum)
1213 int cnum = Files[fnum].cnum;
1214 invalidate_read_prediction(Files[fnum].fd);
1215 Files[fnum].open = False;
1216 Connections[cnum].num_files_open--;
1217 if(Files[fnum].wbmpx_ptr)
1219 free((char *)Files[fnum].wbmpx_ptr);
1220 Files[fnum].wbmpx_ptr = NULL;
1224 if(Files[fnum].mmap_ptr)
1226 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1227 Files[fnum].mmap_ptr = NULL;
1231 if (lp_share_modes(SNUM(cnum)))
1232 del_share_mode(fnum);
1234 close(Files[fnum].fd);
1236 /* NT uses smbclose to start a print - weird */
1237 if (Files[fnum].print_file)
1240 /* check for magic scripts */
1241 check_magic(fnum,cnum);
1243 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1244 timestring(),Connections[cnum].user,Files[fnum].name,
1245 Connections[cnum].num_files_open));
1248 enum {AFAIL,AREAD,AWRITE,AALL};
1250 /*******************************************************************
1251 reproduce the share mode access table
1252 ********************************************************************/
1253 static int access_table(int new_deny,int old_deny,int old_mode,
1254 int share_pid,char *fname)
1256 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1258 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1259 if (old_deny == new_deny && share_pid == getpid())
1262 if (old_mode == 0) return(AREAD);
1264 /* the new smbpub.zip spec says that if the file extension is
1265 .com, .dll, .exe or .sym then allow the open. I will force
1266 it to read-only as this seems sensible although the spec is
1267 a little unclear on this. */
1268 if ((fname = strrchr(fname,'.'))) {
1269 if (strequal(fname,".com") ||
1270 strequal(fname,".dll") ||
1271 strequal(fname,".exe") ||
1272 strequal(fname,".sym"))
1282 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1283 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1284 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1287 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1288 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1289 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1292 if (old_deny==DENY_WRITE) return(AREAD);
1293 if (old_deny==DENY_READ) return(AWRITE);
1294 if (old_deny==DENY_NONE) return(AALL);
1300 /*******************************************************************
1301 check if the share mode on a file allows it to be deleted or unlinked
1302 return True if sharing doesn't prevent the operation
1303 ********************************************************************/
1304 BOOL check_file_sharing(int cnum,char *fname)
1307 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1309 if (!pid || !share_mode) return(True);
1311 if (share_mode == DENY_DOS)
1312 return(pid == getpid());
1314 /* XXXX exactly what share mode combinations should be allowed for
1315 deleting/renaming? */
1319 /****************************************************************************
1321 Helper for open_file_shared.
1322 Truncate a file after checking locking; close file if locked.
1323 **************************************************************************/
1324 static void truncate_unless_locked(int fnum, int cnum)
1326 if (Files[fnum].can_write){
1327 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1330 unix_ERR_class = ERRDOS;
1331 unix_ERR_code = ERRlock;
1334 ftruncate(Files[fnum].fd,0);
1339 /****************************************************************************
1340 open a file with a share mode
1341 ****************************************************************************/
1342 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1343 int mode,int *Access,int *action)
1347 int deny_mode = (share_mode>>4)&7;
1349 BOOL file_existed = file_exist(fname,&sbuf);
1350 BOOL fcbopen = False;
1353 Files[fnum].open = False;
1354 Files[fnum].fd = -1;
1356 /* this is for OS/2 EAs - try and say we don't support them */
1357 if (strstr(fname,".+,;=[].")) {
1358 unix_ERR_class = ERRDOS;
1359 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1363 if ((ofun & 0x3) == 0 && file_existed) {
1370 if ((ofun & 0x3) == 2)
1373 /* note that we ignore the append flag as
1374 append does not mean the same thing under dos and unix */
1376 switch (share_mode&0xF)
1393 if (flags != O_RDONLY && file_existed &&
1394 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1402 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1403 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1408 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1410 if (lp_share_modes(SNUM(cnum))) {
1414 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1417 /* someone else has a share lock on it, check to see
1419 int old_open_mode = old_share&0xF;
1420 int old_deny_mode = (old_share>>4)&7;
1422 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1423 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1424 deny_mode,old_deny_mode,old_open_mode,fname));
1426 unix_ERR_class = ERRDOS;
1427 unix_ERR_code = ERRbadshare;
1432 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1435 if ((access_allowed == AFAIL) ||
1436 (access_allowed == AREAD && flags == O_WRONLY) ||
1437 (access_allowed == AWRITE && flags == O_RDONLY)) {
1438 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1439 deny_mode,old_deny_mode,old_open_mode,
1443 unix_ERR_class = ERRDOS;
1444 unix_ERR_code = ERRbadshare;
1448 if (access_allowed == AREAD)
1451 if (access_allowed == AWRITE)
1457 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1458 flags,flags2,mode));
1460 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
1461 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1463 open_file(fnum,cnum,fname,flags,mode);
1466 if (Files[fnum].open) {
1480 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1481 Files[fnum].share_pending = True;
1484 (*Access) = open_mode;
1488 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1489 if (!file_existed) *action = 2;
1490 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1494 share_mode_pending = True;
1496 if ((flags2&O_TRUNC) && file_existed)
1497 truncate_unless_locked(fnum,cnum);
1503 /*******************************************************************
1504 check for files that we should now set our share modes on
1505 ********************************************************************/
1506 static void check_share_modes(void)
1509 for (i=0;i<MAX_OPEN_FILES;i++)
1510 if(Files[i].open && Files[i].share_pending) {
1511 if (lp_share_modes(SNUM(Files[i].cnum))) {
1513 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1515 set_share_mode(i,Files[i].share_mode);
1516 Files[i].share_pending = False;
1519 Files[i].share_pending = False;
1525 /****************************************************************************
1526 seek a file. Try to avoid the seek if possible
1527 ****************************************************************************/
1528 int seek_file(int fnum,int pos)
1531 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1534 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1535 return(Files[fnum].pos);
1538 /****************************************************************************
1540 ****************************************************************************/
1541 int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
1545 if (!Files[fnum].can_write)
1547 ret = read_predict(Files[fnum].fd,
1555 mincnt = MAX(mincnt-ret,0);
1560 if (Files[fnum].mmap_ptr)
1562 int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1565 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1569 mincnt = MAX(mincnt-num,0);
1578 if (seek_file(fnum,pos) != pos)
1580 DEBUG(3,("Failed to seek to %d\n",pos));
1585 ret += read_with_timeout(Files[fnum].fd,
1596 /****************************************************************************
1598 ****************************************************************************/
1599 int write_file(int fnum,char *data,int n)
1601 if (!Files[fnum].can_write) {
1606 if (!Files[fnum].modified) {
1608 Files[fnum].modified = True;
1609 if (fstat(Files[fnum].fd,&st) == 0) {
1610 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1611 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1612 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1617 return(write_data(Files[fnum].fd,data,n));
1621 static int old_umask = 022;
1623 /****************************************************************************
1624 load parameters specific to a connection/service
1625 ****************************************************************************/
1626 BOOL become_service(int cnum,BOOL do_chdir)
1628 extern char magic_char;
1629 static int last_cnum = -1;
1632 if (!OPEN_CNUM(cnum))
1638 Connections[cnum].lastused = smb_last_time;
1643 ChDir(Connections[cnum].connectpath) != 0 &&
1644 ChDir(Connections[cnum].origpath) != 0)
1646 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1647 Connections[cnum].connectpath,cnum));
1651 if (cnum == last_cnum)
1656 case_default = lp_defaultcase(snum);
1657 case_preserve = lp_preservecase(snum);
1658 short_case_preserve = lp_shortpreservecase(snum);
1659 case_mangle = lp_casemangle(snum);
1660 case_sensitive = lp_casesensitive(snum);
1661 magic_char = lp_magicchar(snum);
1662 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1667 /****************************************************************************
1668 become the specified uid
1669 ****************************************************************************/
1670 static BOOL become_uid(int uid)
1672 if (initial_uid != 0)
1677 /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
1680 priv.pv_priv[0] = 0;
1681 priv.pv_priv[1] = 0;
1682 if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
1683 &priv, sizeof(priv_t)) < 0 ||
1684 setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 ||
1685 seteuid((uid_t)uid) < 0)
1686 DEBUG(1,("Can't set uid (AIX3)"));
1691 if (setresuid(-1,uid,-1) != 0)
1693 if ((seteuid(uid) != 0) &&
1697 DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
1698 uid,getuid(), geteuid()));
1700 DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
1704 if (((uid == -1) || (uid == 65535)) && geteuid() != uid)
1706 DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
1714 /****************************************************************************
1715 become the specified gid
1716 ****************************************************************************/
1717 static BOOL become_gid(int gid)
1719 if (initial_uid != 0)
1723 if (setresgid(-1,gid,-1) != 0)
1725 if (setgid(gid) != 0)
1728 DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
1729 gid,getgid(),getegid()));
1731 DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
1739 /****************************************************************************
1740 become the specified uid and gid
1741 ****************************************************************************/
1742 static BOOL become_id(int uid,int gid)
1744 return(become_gid(gid) && become_uid(uid));
1747 /****************************************************************************
1748 become the guest user
1749 ****************************************************************************/
1750 static BOOL become_guest(void)
1753 static struct passwd *pass=NULL;
1755 if (initial_uid != 0)
1759 pass = Get_Pwnam(lp_guestaccount(-1),True);
1760 if (!pass) return(False);
1762 ret = become_id(pass->pw_uid,pass->pw_gid);
1765 DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
1767 last_user.cnum = -2;
1772 /*******************************************************************
1773 check if a username is OK
1774 ********************************************************************/
1775 static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
1778 for (i=0;i<Connections[cnum].uid_cache.entries;i++)
1779 if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True);
1781 if (!user_ok(vuser->name,snum)) return(False);
1783 i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
1784 Connections[cnum].uid_cache.list[i] = vuser->uid;
1786 if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
1787 Connections[cnum].uid_cache.entries++;
1793 /****************************************************************************
1794 become the user of a connection number
1795 ****************************************************************************/
1796 BOOL become_user(int cnum, int uid)
1804 if (last_user.cnum == cnum && last_user.uid == uid) {
1805 DEBUG(4,("Skipping become_user - already user\n"));
1811 if (!OPEN_CNUM(cnum)) {
1812 DEBUG(2,("Connection %d not open\n",cnum));
1816 snum = Connections[cnum].service;
1818 if (Connections[cnum].force_user ||
1819 lp_security() == SEC_SHARE ||
1820 !(vuser = get_valid_user_struct(uid)) ||
1821 !check_user_ok(cnum,vuser,snum)) {
1822 uid = Connections[cnum].uid;
1823 gid = Connections[cnum].gid;
1824 groups = Connections[cnum].groups;
1825 ngroups = Connections[cnum].ngroups;
1828 DEBUG(2,("Invalid vuid used %d\n",uid));
1832 if(!*lp_force_group(snum))
1835 gid = Connections[cnum].gid;
1836 groups = vuser->user_groups;
1837 ngroups = vuser->user_ngroups;
1840 if (initial_uid == 0)
1842 if (!become_gid(gid)) return(False);
1844 #ifndef NO_SETGROUPS
1845 if (!IS_IPC(cnum)) {
1846 /* groups stuff added by ih/wreu */
1848 if (setgroups(ngroups,groups)<0)
1849 DEBUG(0,("setgroups call failed!\n"));
1853 if (!Connections[cnum].admin_user && !become_uid(uid))
1857 new_umask = 0777 & ~CREATE_MODE(cnum);
1858 old_umask = umask(new_umask);
1860 last_user.cnum = cnum;
1861 last_user.uid = uid;
1863 DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
1864 getuid(),geteuid(),getgid(),getegid(),new_umask));
1869 /****************************************************************************
1870 unbecome the user of a connection number
1871 ****************************************************************************/
1872 BOOL unbecome_user(void )
1874 if (last_user.cnum == -1)
1881 if (initial_uid == 0)
1884 setresuid(-1,getuid(),-1);
1885 setresgid(-1,getgid(),-1);
1887 if (seteuid(initial_uid) != 0)
1888 setuid(initial_uid);
1889 setgid(initial_gid);
1893 if (initial_uid == 0)
1894 DEBUG(2,("Running with no EID\n"));
1895 initial_uid = getuid();
1896 initial_gid = getgid();
1898 if (geteuid() != initial_uid)
1900 DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
1901 initial_uid = geteuid();
1903 if (getegid() != initial_gid)
1905 DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
1906 initial_gid = getegid();
1910 if (ChDir(OriginalDir) != 0)
1911 DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
1912 timestring(),OriginalDir));
1914 DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
1915 getuid(),geteuid(),getgid(),getegid()));
1917 last_user.cnum = -1;
1922 /****************************************************************************
1923 find a service entry
1924 ****************************************************************************/
1925 int find_service(char *service)
1929 string_sub(service,"\\","/");
1931 iService = lp_servicenumber(service);
1933 /* now handle the special case of a home directory */
1936 char *phome_dir = get_home_dir(service);
1937 DEBUG(3,("checking for home directory %s gave %s\n",service,
1938 phome_dir?phome_dir:"(NULL)"));
1942 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1944 lp_add_home(service,iHomeService,phome_dir);
1945 iService = lp_servicenumber(service);
1950 /* If we still don't have a service, attempt to add it as a printer. */
1953 int iPrinterService;
1955 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1959 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1961 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1963 DEBUG(3,("%s is a valid printer name\n", service));
1964 DEBUG(3,("adding %s as a printer service\n", service));
1965 lp_add_printer(service,iPrinterService);
1966 iService = lp_servicenumber(service);
1968 DEBUG(0,("failed to add %s as a printer service!\n", service));
1971 DEBUG(3,("%s is not a valid printer name\n", service));
1975 /* just possibly it's a default service? */
1978 char *defservice = lp_defaultservice();
1979 if (defservice && *defservice && !strequal(defservice,service)) {
1980 iService = find_service(defservice);
1981 if (iService >= 0) {
1982 string_sub(service,"_","/");
1983 iService = lp_add_service(service,iService);
1989 if (!VALID_SNUM(iService))
1991 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1996 DEBUG(3,("find_service() failed to find service %s\n", service));
2002 /****************************************************************************
2003 create an error packet from a cached error.
2004 ****************************************************************************/
2005 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
2007 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
2009 int32 eclass = wbmpx->wr_errclass;
2010 int32 err = wbmpx->wr_error;
2012 /* We can now delete the auxiliary struct */
2013 free((char *)wbmpx);
2014 Files[fnum].wbmpx_ptr = NULL;
2015 return error_packet(inbuf,outbuf,eclass,err,line);
2024 } unix_smb_errmap[] =
2026 {EPERM,ERRDOS,ERRnoaccess},
2027 {EACCES,ERRDOS,ERRnoaccess},
2028 {ENOENT,ERRDOS,ERRbadfile},
2029 {EIO,ERRHRD,ERRgeneral},
2030 {EBADF,ERRSRV,ERRsrverror},
2031 {EINVAL,ERRSRV,ERRsrverror},
2032 {EEXIST,ERRDOS,ERRfilexists},
2033 {ENFILE,ERRDOS,ERRnofids},
2034 {EMFILE,ERRDOS,ERRnofids},
2035 {ENOSPC,ERRHRD,ERRdiskfull},
2037 {EDQUOT,ERRHRD,ERRdiskfull},
2040 {ENOTEMPTY,ERRDOS,ERRnoaccess},
2043 {EXDEV,ERRDOS,ERRdiffdevice},
2045 {EROFS,ERRHRD,ERRnowrite},
2050 /****************************************************************************
2051 create an error packet from errno
2052 ****************************************************************************/
2053 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
2055 int eclass=def_class;
2059 if (unix_ERR_class != SUCCESS)
2061 eclass = unix_ERR_class;
2062 ecode = unix_ERR_code;
2063 unix_ERR_class = SUCCESS;
2068 while (unix_smb_errmap[i].smbclass != 0)
2070 if (unix_smb_errmap[i].unixerror == errno)
2072 eclass = unix_smb_errmap[i].smbclass;
2073 ecode = unix_smb_errmap[i].smbcode;
2080 return(error_packet(inbuf,outbuf,eclass,ecode,line));
2084 /****************************************************************************
2085 create an error packet. Normally called using the ERROR() macro
2086 ****************************************************************************/
2087 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2089 int outsize = set_message(outbuf,0,0,True);
2091 cmd = CVAL(inbuf,smb_com);
2093 CVAL(outbuf,smb_rcls) = error_class;
2094 SSVAL(outbuf,smb_err,error_code);
2096 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2099 (int)CVAL(inbuf,smb_com),
2100 smb_fn_name(CVAL(inbuf,smb_com)),
2105 DEBUG(3,("error string = %s\n",strerror(errno)));
2111 #ifndef SIGCLD_IGNORE
2112 /****************************************************************************
2113 this prevents zombie child processes
2114 ****************************************************************************/
2115 static int sig_cld()
2117 static int depth = 0;
2120 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2127 DEBUG(5,("got SIGCLD\n"));
2130 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2134 /* Stevens, Adv. Unix Prog. says that on system V you must call
2135 wait before reinstalling the signal handler, because the kernel
2136 calls the handler from within the signal-call when there is a
2137 child that has exited. This would lead to an infinite recursion
2138 if done vice versa. */
2140 #ifndef DONT_REINSTALL_SIG
2141 #ifdef SIGCLD_IGNORE
2142 signal(SIGCLD, SIG_IGN);
2144 signal(SIGCLD, SIGNAL_CAST sig_cld);
2149 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2152 BlockSignals(False);
2157 /****************************************************************************
2158 this is called when the client exits abruptly
2159 **************************************************************************/
2160 static int sig_pipe()
2162 exit_server("Got sigpipe\n");
2166 /****************************************************************************
2167 open the socket communication
2168 ****************************************************************************/
2169 static BOOL open_sockets(BOOL is_daemon,int port)
2176 struct sockaddr addr;
2177 int in_addrlen = sizeof(addr);
2180 #ifdef SIGCLD_IGNORE
2181 signal(SIGCLD, SIG_IGN);
2183 signal(SIGCLD, SIGNAL_CAST sig_cld);
2186 /* open an incoming socket */
2187 s = open_socket_in(SOCK_STREAM, port, 0);
2191 /* ready to listen */
2192 if (listen(s, 5) == -1)
2194 DEBUG(0,("listen: %s",strerror(errno)));
2199 /* now accept incoming connections - forking a new process
2200 for each incoming connection */
2201 DEBUG(2,("waiting for a connection\n"));
2204 Client = accept(s,&addr,&in_addrlen);
2206 if (Client == -1 && errno == EINTR)
2211 DEBUG(0,("accept: %s",strerror(errno)));
2215 #ifdef NO_FORK_DEBUG
2216 #ifndef NO_SIGNAL_TEST
2217 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2218 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2222 if (Client != -1 && fork()==0)
2224 #ifndef NO_SIGNAL_TEST
2225 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2226 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2228 /* close the listening socket */
2231 /* close our standard file descriptors */
2234 set_socket_options(Client,"SO_KEEPALIVE");
2235 set_socket_options(Client,user_socket_options);
2239 close(Client); /* The parent doesn't need this socket */
2245 /* We will abort gracefully when the client or remote system
2247 #ifndef NO_SIGNAL_TEST
2248 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2252 /* close our standard file descriptors */
2255 set_socket_options(Client,"SO_KEEPALIVE");
2256 set_socket_options(Client,user_socket_options);
2263 /****************************************************************************
2264 check if a snum is in use
2265 ****************************************************************************/
2266 BOOL snum_used(int snum)
2269 for (i=0;i<MAX_CONNECTIONS;i++)
2270 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2275 /****************************************************************************
2276 reload the services file
2277 **************************************************************************/
2278 BOOL reload_services(BOOL test)
2285 strcpy(fname,lp_configfile());
2286 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2288 strcpy(servicesf,fname);
2295 if (test && !lp_file_list_changed())
2298 lp_killunused(snum_used);
2300 ret = lp_load(servicesf,False);
2302 /* perhaps the config filename is now set */
2304 reload_services(True);
2311 set_socket_options(Client,"SO_KEEPALIVE");
2312 set_socket_options(Client,user_socket_options);
2316 create_mangled_stack(lp_mangledstack());
2318 /* this forces service parameters to be flushed */
2319 become_service(-1,True);
2326 /****************************************************************************
2327 this prevents zombie child processes
2328 ****************************************************************************/
2329 static int sig_hup()
2332 DEBUG(0,("Got SIGHUP\n"));
2333 reload_services(False);
2334 #ifndef DONT_REINSTALL_SIG
2335 signal(SIGHUP,SIGNAL_CAST sig_hup);
2337 BlockSignals(False);
2341 /****************************************************************************
2342 Setup the groups a user belongs to.
2343 ****************************************************************************/
2344 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2345 int **p_igroups, gid_t **p_groups)
2347 if (-1 == initgroups(user,gid))
2351 DEBUG(0,("Unable to initgroups!\n"));
2352 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2353 DEBUG(0,("This is probably a problem with the account %s\n",user));
2361 ngroups = getgroups(0,&grp);
2364 igroups = (int *)malloc(sizeof(int)*ngroups);
2365 for (i=0;i<ngroups;i++)
2366 igroups[i] = 0x42424242;
2367 ngroups = getgroups(ngroups,(gid_t *)igroups);
2369 if (igroups[0] == 0x42424242)
2372 *p_ngroups = ngroups;
2374 /* The following bit of code is very strange. It is due to the
2375 fact that some OSes use int* and some use gid_t* for
2376 getgroups, and some (like SunOS) use both, one in prototypes,
2377 and one in man pages and the actual code. Thus we detect it
2378 dynamically using some very ugly code */
2381 /* does getgroups return ints or gid_t ?? */
2382 static BOOL groups_use_ints = True;
2384 if (groups_use_ints &&
2386 SVAL(igroups,2) == 0x4242)
2387 groups_use_ints = False;
2389 for (i=0;groups_use_ints && i<ngroups;i++)
2390 if (igroups[i] == 0x42424242)
2391 groups_use_ints = False;
2393 if (groups_use_ints)
2395 *p_igroups = igroups;
2396 *p_groups = (gid_t *)igroups;
2400 gid_t *groups = (gid_t *)igroups;
2401 igroups = (int *)malloc(sizeof(int)*ngroups);
2402 for (i=0;i<ngroups;i++)
2403 igroups[i] = groups[i];
2404 *p_igroups = igroups;
2405 *p_groups = (gid_t *)groups;
2408 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2409 for (i=0;i<ngroups;i++)
2410 DEBUG(3,("%d ",igroups[i]));
2416 /****************************************************************************
2417 make a connection to a service
2418 ****************************************************************************/
2419 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
2423 struct passwd *pass = NULL;
2424 connection_struct *pcon;
2427 static BOOL first_connection = True;
2431 snum = find_service(service);
2434 if (strequal(service,"IPC$"))
2436 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2440 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2444 if (strequal(service,HOMES_NAME))
2446 if (*user && Get_Pwnam(user,True))
2447 return(make_connection(user,user,password,pwlen,dev,vuid));
2449 if (validated_username(vuid))
2451 strcpy(user,validated_username(vuid));
2452 return(make_connection(user,user,password,pwlen,dev,vuid));
2456 if (!lp_snum_ok(snum) || !check_access(snum)) {
2460 /* you can only connect to the IPC$ service as an ipc device */
2461 if (strequal(service,"IPC$"))
2464 if (*dev == '?' || !*dev)
2466 if (lp_print_ok(snum))
2467 strcpy(dev,"LPT1:");
2472 /* if the request is as a printer and you can't print then refuse */
2474 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2475 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2479 /* lowercase the user name */
2482 /* add it as a possible user name */
2483 add_session_user(service);
2485 /* shall we let them in? */
2486 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2488 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2492 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2495 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2499 pcon = &Connections[cnum];
2500 bzero((char *)pcon,sizeof(*pcon));
2502 /* find out some info about the user */
2503 pass = Get_Pwnam(user,True);
2507 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2511 pcon->read_only = lp_readonly(snum);
2515 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2516 string_sub(list,"%S",service);
2518 if (user_in_list(user,list))
2519 pcon->read_only = True;
2521 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2522 string_sub(list,"%S",service);
2524 if (user_in_list(user,list))
2525 pcon->read_only = False;
2528 /* admin user check */
2529 if (user_in_list(user,lp_admin_users(snum)) &&
2532 pcon->admin_user = True;
2533 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2536 pcon->admin_user = False;
2538 pcon->force_user = force;
2539 pcon->uid = pass->pw_uid;
2540 pcon->gid = pass->pw_gid;
2541 pcon->num_files_open = 0;
2542 pcon->lastused = time(NULL);
2543 pcon->service = snum;
2545 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2546 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2547 pcon->dirptr = NULL;
2548 string_set(&pcon->dirpath,"");
2549 string_set(&pcon->user,user);
2552 if (*lp_force_group(snum))
2554 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2557 pcon->gid = gptr->gr_gid;
2558 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2561 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2565 if (*lp_force_user(snum))
2567 struct passwd *pass2;
2569 strcpy(fuser,lp_force_user(snum));
2570 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2573 pcon->uid = pass2->pw_uid;
2574 string_set(&pcon->user,fuser);
2576 pcon->force_user = True;
2577 DEBUG(3,("Forced user %s\n",fuser));
2580 DEBUG(1,("Couldn't find user %s\n",fuser));
2585 strcpy(s,lp_pathname(snum));
2586 standard_sub(cnum,s);
2587 string_set(&pcon->connectpath,s);
2588 DEBUG(3,("Connect path is %s\n",s));
2591 /* groups stuff added by ih */
2593 pcon->groups = NULL;
2597 /* Find all the groups this uid is in and store them. Used by become_user() */
2598 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2600 /* check number of connections */
2601 if (!claim_connection(cnum,
2602 lp_servicename(SNUM(cnum)),
2603 lp_max_connections(SNUM(cnum)),False))
2605 DEBUG(1,("too many connections - rejected\n"));
2609 if (lp_status(SNUM(cnum)))
2610 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2612 first_connection = False;
2617 /* execute any "root preexec = " line */
2618 if (*lp_rootpreexec(SNUM(cnum)))
2621 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2622 standard_sub(cnum,cmd);
2623 DEBUG(5,("cmd=%s\n",cmd));
2627 if (!become_user(cnum,pcon->uid))
2629 DEBUG(0,("Can't become connected user!\n"));
2631 if (!IS_IPC(cnum)) {
2632 yield_connection(cnum,
2633 lp_servicename(SNUM(cnum)),
2634 lp_max_connections(SNUM(cnum)));
2635 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2640 if (ChDir(pcon->connectpath) != 0)
2642 DEBUG(0,("Can't change directory to %s\n",pcon->connectpath));
2645 if (!IS_IPC(cnum)) {
2646 yield_connection(cnum,
2647 lp_servicename(SNUM(cnum)),
2648 lp_max_connections(SNUM(cnum)));
2649 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2654 string_set(&pcon->origpath,pcon->connectpath);
2656 #if SOFTLINK_OPTIMISATION
2657 /* resolve any soft links early */
2660 strcpy(s,pcon->connectpath);
2662 string_set(&pcon->connectpath,s);
2663 ChDir(pcon->connectpath);
2667 num_connections_open++;
2668 add_session_user(user);
2670 /* execute any "preexec = " line */
2671 if (*lp_preexec(SNUM(cnum)))
2674 strcpy(cmd,lp_preexec(SNUM(cnum)));
2675 standard_sub(cnum,cmd);
2679 /* we've finished with the sensitive stuff */
2683 extern struct from_host Client_info;
2684 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2686 Client_info.name,Client_info.addr,
2687 lp_servicename(SNUM(cnum)),user,
2697 /****************************************************************************
2698 find first available file slot
2699 ****************************************************************************/
2700 int find_free_file(void )
2703 for (i=1;i<MAX_OPEN_FILES;i++)
2706 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2710 /****************************************************************************
2711 find first available connection slot, starting from a random position.
2712 The randomisation stops problems with the server dieing and clients
2713 thinking the server is still available.
2714 ****************************************************************************/
2715 static int find_free_connection(int hash )
2719 hash = (hash % (MAX_CONNECTIONS-2))+1;
2723 for (i=hash+1;i!=hash;)
2725 if (!Connections[i].open && Connections[i].used == used)
2727 DEBUG(3,("found free connection number %d\n",i));
2731 if (i == MAX_CONNECTIONS)
2741 DEBUG(1,("ERROR! Out of connection structures\n"));
2746 /****************************************************************************
2747 reply for the core protocol
2748 ****************************************************************************/
2749 int reply_corep(char *outbuf)
2751 int outsize = set_message(outbuf,1,0,True);
2753 Protocol = PROTOCOL_CORE;
2759 /****************************************************************************
2760 reply for the coreplus protocol
2761 ****************************************************************************/
2762 int reply_coreplus(char *outbuf)
2764 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2765 int outsize = set_message(outbuf,13,0,True);
2766 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2767 readbraw and writebraw (possibly) */
2768 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2769 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2771 Protocol = PROTOCOL_COREPLUS;
2777 /****************************************************************************
2778 reply for the lanman 1.0 protocol
2779 ****************************************************************************/
2780 int reply_lanman1(char *outbuf)
2782 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2784 BOOL doencrypt = SMBENCRYPT();
2785 time_t t = time(NULL);
2787 if (lp_security()>=SEC_USER) secword |= 1;
2788 if (doencrypt) secword |= 2;
2790 set_message(outbuf,13,doencrypt?8:0,True);
2791 SSVAL(outbuf,smb_vwv1,secword);
2793 /* Create a token value and add it to the outgoing packet. */
2795 generate_next_challenge(smb_buf(outbuf));
2798 Protocol = PROTOCOL_LANMAN1;
2800 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2801 DEBUG(3,("using password server validation\n"));
2803 if (doencrypt) set_challenge(smb_buf(outbuf));
2807 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2808 SSVAL(outbuf,smb_vwv2,maxxmit);
2809 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2810 SSVAL(outbuf,smb_vwv4,1);
2811 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2812 readbraw writebraw (possibly) */
2813 SIVAL(outbuf,smb_vwv6,getpid());
2814 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2816 put_dos_date(outbuf,smb_vwv8,t);
2818 return (smb_len(outbuf)+4);
2822 /****************************************************************************
2823 reply for the lanman 2.0 protocol
2824 ****************************************************************************/
2825 int reply_lanman2(char *outbuf)
2827 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2829 BOOL doencrypt = SMBENCRYPT();
2830 time_t t = time(NULL);
2832 if (lp_security()>=SEC_USER) secword |= 1;
2833 if (doencrypt) secword |= 2;
2835 set_message(outbuf,13,doencrypt?8:0,True);
2836 SSVAL(outbuf,smb_vwv1,secword);
2838 /* Create a token value and add it to the outgoing packet. */
2840 generate_next_challenge(smb_buf(outbuf));
2843 SIVAL(outbuf,smb_vwv6,getpid());
2845 Protocol = PROTOCOL_LANMAN2;
2847 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2848 DEBUG(3,("using password server validation\n"));
2850 if (doencrypt) set_challenge(smb_buf(outbuf));
2854 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2855 SSVAL(outbuf,smb_vwv2,maxxmit);
2856 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2857 SSVAL(outbuf,smb_vwv4,1);
2858 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2859 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2860 put_dos_date(outbuf,smb_vwv8,t);
2862 return (smb_len(outbuf)+4);
2865 /****************************************************************************
2866 reply for the nt protocol
2867 ****************************************************************************/
2868 int reply_nt1(char *outbuf)
2870 int capabilities=0x300; /* has dual names + lock_and_read */
2872 BOOL doencrypt = SMBENCRYPT();
2874 if (lp_security()>=SEC_USER) secword |= 1;
2875 if (doencrypt) secword |= 2;
2877 set_message(outbuf,17,doencrypt?8:0,True);
2878 CVAL(outbuf,smb_vwv1) = secword;
2880 /* Create a token value and add it to the outgoing packet. */
2882 generate_next_challenge(smb_buf(outbuf));
2883 /* Tell the nt machine how long the challenge is. */
2884 SSVALS(outbuf,smb_vwv16+1,8);
2888 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2890 Protocol = PROTOCOL_NT1;
2892 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2893 DEBUG(3,("using password server validation\n"));
2895 if (doencrypt) set_challenge(smb_buf(outbuf));
2899 if (lp_readraw() && lp_writeraw())
2902 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2903 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2904 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2905 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2906 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2907 put_long_date(outbuf+smb_vwv11+1,time(NULL));
2908 SSVALS(outbuf,smb_vwv15+1,TimeDiff(time(NULL))/60);
2910 return (smb_len(outbuf)+4);
2914 /* these are the protocol lists used for auto architecture detection:
2917 protocol [PC NETWORK PROGRAM 1.0]
2918 protocol [XENIX CORE]
2919 protocol [MICROSOFT NETWORKS 1.03]
2920 protocol [LANMAN1.0]
2921 protocol [Windows for Workgroups 3.1a]
2922 protocol [LM1.2X002]
2923 protocol [LANMAN2.1]
2924 protocol [NT LM 0.12]
2927 protocol [PC NETWORK PROGRAM 1.0]
2928 protocol [XENIX CORE]
2929 protocol [MICROSOFT NETWORKS 1.03]
2930 protocol [LANMAN1.0]
2931 protocol [Windows for Workgroups 3.1a]
2932 protocol [LM1.2X002]
2933 protocol [LANMAN2.1]
2934 protocol [NT LM 0.12]
2937 protocol [PC NETWORK PROGRAM 1.0]
2938 protocol [XENIX CORE]
2939 protocol [LANMAN1.0]
2940 protocol [LM1.2X002]
2941 protocol [LANMAN2.1]
2945 * Modified to recognize the architecture of the remote machine better.
2947 * This appears to be the matrix of which protocol is used by which
2949 Protocol WfWg Win95 WinNT OS/2
2950 PC NETWORK PROGRAM 1.0 1 1 1 1
2952 MICROSOFT NETWORKS 3.0 2 2
2954 MICROSOFT NETWORKS 1.03 3
2957 Windows for Workgroups 3.1a 5 5 5
2962 * tim@fsg.com 09/29/95
2965 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2966 #define ARCH_WIN95 0x2
2967 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2968 #define ARCH_WINNT 0x8
2969 #define ARCH_SAMBA 0x10
2971 #define ARCH_ALL 0x1F
2973 /* List of supported protocols, most desired first */
2977 int (*proto_reply_fn)(char *);
2979 } supported_protocols[] = {
2980 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2981 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2982 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2983 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2984 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2985 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2986 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2987 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2988 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2993 /****************************************************************************
2995 ****************************************************************************/
2996 static int reply_negprot(char *inbuf,char *outbuf)
2998 extern fstring remote_arch;
2999 int outsize = set_message(outbuf,1,0,True);
3004 int bcc = SVAL(smb_buf(inbuf),-2);
3005 int arch = ARCH_ALL;
3007 p = smb_buf(inbuf)+1;
3008 while (p < (smb_buf(inbuf) + bcc))
3011 DEBUG(3,("Requested protocol [%s]\n",p));
3012 if (strcsequal(p,"Windows for Workgroups 3.1a"))
3013 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3014 else if (strcsequal(p,"DOS LM1.2X002"))
3015 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3016 else if (strcsequal(p,"DOS LANMAN2.1"))
3017 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3018 else if (strcsequal(p,"NT LM 0.12"))
3019 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3020 else if (strcsequal(p,"LANMAN2.1"))
3021 arch &= ( ARCH_WINNT | ARCH_OS2 );
3022 else if (strcsequal(p,"LM1.2X002"))
3023 arch &= ( ARCH_WINNT | ARCH_OS2 );
3024 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3026 else if (strcsequal(p,"XENIX CORE"))
3027 arch &= ( ARCH_WINNT | ARCH_OS2 );
3028 else if (strcsequal(p,"Samba")) {
3038 strcpy(remote_arch,"Samba");
3041 strcpy(remote_arch,"WfWg");
3044 strcpy(remote_arch,"Win95");
3047 strcpy(remote_arch,"WinNT");
3050 strcpy(remote_arch,"OS2");
3053 strcpy(remote_arch,"UNKNOWN");
3057 /* possibly reload - change of architecture */
3058 reload_services(True);
3060 /* a special case to stop password server loops */
3061 if (Index == 1 && strequal(remote_machine,myhostname) &&
3062 lp_security()==SEC_SERVER)
3063 exit_server("Password server loop!");
3065 /* Check for protocols, most desirable first */
3066 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3068 p = smb_buf(inbuf)+1;
3070 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3071 while (p < (smb_buf(inbuf) + bcc))
3073 if (strequal(p,supported_protocols[protocol].proto_name))
3082 SSVAL(outbuf,smb_vwv0,choice);
3084 extern fstring remote_proto;
3085 strcpy(remote_proto,supported_protocols[protocol].short_name);
3086 reload_services(True);
3087 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3088 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3091 DEBUG(0,("No protocol supported !\n"));
3093 SSVAL(outbuf,smb_vwv0,choice);
3095 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3101 /****************************************************************************
3102 parse a connect packet
3103 ****************************************************************************/
3104 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
3106 char *p = smb_buf(buf) + 1;
3109 DEBUG(4,("parsing connect string %s\n",p));
3111 p2 = strrchr(p,'\\');
3115 strcpy(service,p2+1);
3120 *pwlen = strlen(password);
3127 p = strchr(service,'%');
3136 /****************************************************************************
3137 close all open files for a connection
3138 ****************************************************************************/
3139 static void close_open_files(int cnum)
3142 for (i=0;i<MAX_OPEN_FILES;i++)
3143 if( Files[i].cnum == cnum && Files[i].open) {
3150 /****************************************************************************
3152 ****************************************************************************/
3153 void close_cnum(int cnum, int uid)
3155 extern struct from_host Client_info;
3157 DirCacheFlush(SNUM(cnum));
3161 if (!OPEN_CNUM(cnum))
3163 DEBUG(0,("Can't close cnum %d\n",cnum));
3167 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3169 Client_info.name,Client_info.addr,
3170 lp_servicename(SNUM(cnum))));
3172 yield_connection(cnum,
3173 lp_servicename(SNUM(cnum)),
3174 lp_max_connections(SNUM(cnum)));
3176 if (lp_status(SNUM(cnum)))
3177 yield_connection(cnum,"STATUS.",MAXSTATUS);
3179 close_open_files(cnum);
3180 dptr_closecnum(cnum);
3182 /* execute any "postexec = " line */
3183 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
3186 strcpy(cmd,lp_postexec(SNUM(cnum)));
3187 standard_sub(cnum,cmd);
3193 /* execute any "root postexec = " line */
3194 if (*lp_rootpostexec(SNUM(cnum)))
3197 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3198 standard_sub(cnum,cmd);
3202 Connections[cnum].open = False;
3203 num_connections_open--;
3204 if (Connections[cnum].ngroups && Connections[cnum].groups)
3206 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3207 free(Connections[cnum].groups);
3208 free(Connections[cnum].igroups);
3209 Connections[cnum].groups = NULL;
3210 Connections[cnum].igroups = NULL;
3211 Connections[cnum].ngroups = 0;
3214 string_set(&Connections[cnum].user,"");
3215 string_set(&Connections[cnum].dirpath,"");
3216 string_set(&Connections[cnum].connectpath,"");
3220 /****************************************************************************
3221 simple routines to do connection counting
3222 ****************************************************************************/
3223 BOOL yield_connection(int cnum,char *name,int max_connections)
3225 struct connect_record crec;
3228 int mypid = getpid();
3231 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3233 if (max_connections <= 0)
3236 bzero(&crec,sizeof(crec));
3238 strcpy(fname,lp_lockdir());
3239 standard_sub(cnum,fname);
3240 trim_string(fname,"","/");
3244 strcat(fname,".LCK");
3246 f = fopen(fname,"r+");
3249 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3253 fseek(f,0,SEEK_SET);
3255 /* find a free spot */
3256 for (i=0;i<max_connections;i++)
3258 if (fread(&crec,sizeof(crec),1,f) != 1)
3260 DEBUG(2,("Entry not found in lock file %s\n",fname));
3264 if (crec.pid == mypid && crec.cnum == cnum)
3268 if (crec.pid != mypid || crec.cnum != cnum)
3271 DEBUG(2,("Entry not found in lock file %s\n",fname));
3275 bzero((void *)&crec,sizeof(crec));
3277 /* remove our mark */
3278 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3279 fwrite(&crec,sizeof(crec),1,f) != 1)
3281 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3286 DEBUG(3,("Yield successful\n"));
3293 /****************************************************************************
3294 simple routines to do connection counting
3295 ****************************************************************************/
3296 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3298 struct connect_record crec;
3301 int snum = SNUM(cnum);
3305 if (max_connections <= 0)
3308 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3310 strcpy(fname,lp_lockdir());
3311 standard_sub(cnum,fname);
3312 trim_string(fname,"","/");
3314 if (!directory_exist(fname,NULL))
3319 strcat(fname,".LCK");
3321 if (!file_exist(fname,NULL))
3323 f = fopen(fname,"w");
3327 total_recs = file_size(fname) / sizeof(crec);
3329 f = fopen(fname,"r+");
3333 DEBUG(1,("couldn't open lock file %s\n",fname));
3337 /* find a free spot */
3338 for (i=0;i<max_connections;i++)
3341 if (i>=total_recs ||
3342 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3343 fread(&crec,sizeof(crec),1,f) != 1)
3345 if (foundi < 0) foundi = i;
3349 if (Clear && crec.pid && !process_exists(crec.pid))
3351 fseek(f,i*sizeof(crec),SEEK_SET);
3352 bzero((void *)&crec,sizeof(crec));
3353 fwrite(&crec,sizeof(crec),1,f);
3354 if (foundi < 0) foundi = i;
3357 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3366 DEBUG(3,("no free locks in %s\n",fname));
3371 /* fill in the crec */
3372 bzero((void *)&crec,sizeof(crec));
3373 crec.magic = 0x280267;
3374 crec.pid = getpid();
3376 crec.uid = Connections[cnum].uid;
3377 crec.gid = Connections[cnum].gid;
3378 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3379 crec.start = time(NULL);
3382 extern struct from_host Client_info;
3383 StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
3384 StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
3388 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3389 fwrite(&crec,sizeof(crec),1,f) != 1)
3400 /*******************************************************************
3401 prepare to dump a core file - carefully!
3402 ********************************************************************/
3403 static BOOL dump_core(void)
3407 strcpy(dname,debugf);
3408 if ((p=strrchr(dname,'/'))) *p=0;
3409 strcat(dname,"/corefiles");
3411 sys_chown(dname,getuid(),getgid());
3413 if (chdir(dname)) return(False);
3416 #ifndef NO_GETRLIMIT
3420 getrlimit(RLIMIT_CORE, &rlp);
3421 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3422 setrlimit(RLIMIT_CORE, &rlp);
3423 getrlimit(RLIMIT_CORE, &rlp);
3424 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3430 DEBUG(0,("Dumping core in %s\n",dname));
3435 /****************************************************************************
3437 ****************************************************************************/
3438 void exit_server(char *reason)
3440 static int firsttime=1;
3443 if (!firsttime) exit(0);
3447 DEBUG(2,("Closing connections\n"));
3448 for (i=0;i<MAX_CONNECTIONS;i++)
3449 if (Connections[i].open)
3452 if (dcelogin_atmost_once)
3456 int oldlevel = DEBUGLEVEL;
3458 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3460 show_msg(last_inbuf);
3461 DEBUGLEVEL = oldlevel;
3462 DEBUG(0,("===============================================================\n"));
3464 if (dump_core()) return;
3467 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3471 /****************************************************************************
3472 do some standard substitutions in a string
3473 ****************************************************************************/
3474 void standard_sub(int cnum,char *s)
3476 if (!strchr(s,'%')) return;
3478 if (VALID_CNUM(cnum))
3480 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3481 string_sub(s,"%P",Connections[cnum].connectpath);
3482 string_sub(s,"%u",Connections[cnum].user);
3483 if (strstr(s,"%H")) {
3484 char *home = get_home_dir(Connections[cnum].user);
3485 if (home) string_sub(s,"%H",home);
3487 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3489 standard_sub_basic(s);
3493 These flags determine some of the permissions required to do an operation
3495 Note that I don't set NEED_WRITE on some write operations because they
3496 are used by some brain-dead clients when printing, and I don't want to
3497 force write permissions on print services.
3499 #define AS_USER (1<<0)
3500 #define NEED_WRITE (1<<1)
3501 #define TIME_INIT (1<<2)
3502 #define CAN_IPC (1<<3)
3503 #define AS_GUEST (1<<5)
3507 define a list of possible SMB messages and their corresponding
3508 functions. Any message that has a NULL function is unimplemented -
3509 please feel free to contribute implementations!
3511 struct smb_message_struct
3525 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3526 {SMBtcon,"SMBtcon",reply_tcon,0},
3527 {SMBtdis,"SMBtdis",reply_tdis,0},
3528 {SMBexit,"SMBexit",reply_exit,0},
3529 {SMBioctl,"SMBioctl",reply_ioctl,0},
3530 {SMBecho,"SMBecho",reply_echo,0},
3531 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3532 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3533 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0},
3534 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3535 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3536 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3537 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3538 {SMBopen,"SMBopen",reply_open,AS_USER},
3540 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3541 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3542 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3544 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3545 {SMBread,"SMBread",reply_read,AS_USER},
3546 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3547 {SMBclose,"SMBclose",reply_close,AS_USER},
3548 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3549 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3550 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3551 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3553 /* this is a Pathworks specific call, allowing the
3554 changing of the root path */
3555 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3557 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3558 {SMBflush,"SMBflush",reply_flush,AS_USER},
3559 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3560 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3561 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3562 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
3563 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3564 {SMBlock,"SMBlock",reply_lock,AS_USER},
3565 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3567 /* CORE+ PROTOCOL FOLLOWS */
3569 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3570 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3571 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3572 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3573 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3575 /* LANMAN1.0 PROTOCOL FOLLOWS */
3577 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3578 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3579 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3580 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3581 {SMBwritec,"SMBwritec",NULL,AS_USER},
3582 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3583 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3584 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3585 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3586 {SMBioctls,"SMBioctls",NULL,AS_USER},
3587 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3588 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3590 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
3591 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3592 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3593 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3595 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3596 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3597 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3599 /* LANMAN2.0 PROTOCOL FOLLOWS */
3600 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3601 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3602 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3603 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3605 /* messaging routines */
3606 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3607 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3608 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3609 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3611 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3613 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3614 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3615 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3616 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3619 /****************************************************************************
3620 return a string containing the function name of a SMB command
3621 ****************************************************************************/
3622 char *smb_fn_name(int type)
3624 static char *unknown_name = "SMBunknown";
3625 static int num_smb_messages =
3626 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3629 for (match=0;match<num_smb_messages;match++)
3630 if (smb_messages[match].code == type)
3633 if (match == num_smb_messages)
3634 return(unknown_name);
3636 return(smb_messages[match].name);
3640 /****************************************************************************
3641 do a switch on the message type, and return the response size
3642 ****************************************************************************/
3643 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3647 static int num_smb_messages =
3648 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3652 struct timeval msg_start_time;
3653 struct timeval msg_end_time;
3654 static unsigned long total_time = 0;
3656 GetTimeOfDay(&msg_start_time);
3663 last_message = type;
3665 /* make sure this is an SMB packet */
3666 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3668 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3672 for (match=0;match<num_smb_messages;match++)
3673 if (smb_messages[match].code == type)
3676 if (match == num_smb_messages)
3678 DEBUG(0,("Unknown message type %d!\n",type));
3679 outsize = reply_unknown(inbuf,outbuf);
3683 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3684 if (smb_messages[match].fn)
3686 int cnum = SVAL(inbuf,smb_tid);
3687 int flags = smb_messages[match].flags;
3688 int uid = SVAL(inbuf,smb_uid);
3690 /* does this protocol need to be run as root? */
3691 if (!(flags & AS_USER))
3694 /* does this protocol need to be run as the connected user? */
3695 if ((flags & AS_USER) && !become_user(cnum,uid))
3696 return(ERROR(ERRSRV,ERRinvnid));
3698 /* does it need write permission? */
3699 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3700 return(ERROR(ERRSRV,ERRaccess));
3702 /* ipc services are limited */
3703 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3704 return(ERROR(ERRSRV,ERRaccess));
3706 /* load service specific parameters */
3707 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3708 return(ERROR(ERRSRV,ERRaccess));
3710 /* does this protocol need to be run as guest? */
3711 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3712 return(ERROR(ERRSRV,ERRaccess));
3716 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3720 outsize = reply_unknown(inbuf,outbuf);
3725 GetTimeOfDay(&msg_end_time);
3726 if (!(smb_messages[match].flags & TIME_INIT))
3728 smb_messages[match].time = 0;
3729 smb_messages[match].flags |= TIME_INIT;
3732 unsigned long this_time =
3733 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3734 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3735 smb_messages[match].time += this_time;
3736 total_time += this_time;
3738 DEBUG(2,("TIME %s %d usecs %g pct\n",
3739 smb_fn_name(type),smb_messages[match].time,
3740 (100.0*smb_messages[match].time) / total_time));
3747 /****************************************************************************
3748 construct a chained reply and add it to the already made reply
3750 inbuf points to the original message start.
3751 inbuf2 points to the smb_wct part of the secondary message
3752 type is the type of the secondary message
3753 outbuf points to the original outbuffer
3754 outbuf2 points to the smb_wct field of the new outbuffer
3755 size is the total length of the incoming message (from inbuf1)
3756 bufsize is the total buffer size
3758 return how many bytes were added to the response
3759 ****************************************************************************/
3760 int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
3764 static BOOL in_chain = False;
3765 static char *last_outbuf=NULL;
3766 BOOL was_inchain = in_chain;
3767 int insize_remaining;
3768 static int insize_deleted;
3771 chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3773 outbuf = last_outbuf;
3779 inbuf2 -= insize_deleted;
3780 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3781 insize_deleted += size - (insize_remaining + smb_wct);
3784 last_outbuf = outbuf;
3787 /* allocate some space for the in and out buffers of the chained message */
3788 ibuf = (char *)malloc(size + SAFETY_MARGIN);
3789 obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
3793 DEBUG(0,("Out of memory in chain reply\n"));
3794 return(ERROR(ERRSRV,ERRnoresource));
3797 ibuf += SMB_ALIGNMENT;
3798 obuf += SMB_ALIGNMENT;
3800 /* create the in buffer */
3801 memcpy(ibuf,inbuf,smb_wct);
3802 memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
3803 CVAL(ibuf,smb_com) = type;
3805 /* create the out buffer */
3806 bzero(obuf,smb_size);
3808 set_message(obuf,0,0,True);
3809 CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3811 memcpy(obuf+4,ibuf+4,4);
3812 CVAL(obuf,smb_rcls) = SUCCESS;
3813 CVAL(obuf,smb_reh) = 0;
3814 CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
3816 SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
3817 SSVAL(obuf,smb_err,SUCCESS);
3818 SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
3819 SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
3820 SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
3821 SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
3823 DEBUG(3,("Chained message\n"));
3826 /* process the request */
3827 outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3828 bufsize-chain_size);
3830 /* copy the new reply header over the old one, but preserve
3831 the smb_com field */
3832 memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
3834 /* and copy the data from the reply to the right spot */
3835 memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3837 /* free the allocated buffers */
3838 if (ibuf) free(ibuf-SMB_ALIGNMENT);
3839 if (obuf) free(obuf-SMB_ALIGNMENT);
3841 in_chain = was_inchain;
3843 /* return how much extra has been added to the packet */
3844 return(outsize - smb_wct);
3849 /****************************************************************************
3850 construct a reply to the incoming packet
3851 ****************************************************************************/
3852 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3854 int type = CVAL(inbuf,smb_com);
3856 int msg_type = CVAL(inbuf,0);
3858 smb_last_time = time(NULL);
3862 bzero(outbuf,smb_size);
3865 return(reply_special(inbuf,outbuf));
3867 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3868 set_message(outbuf,0,0,True);
3870 memcpy(outbuf+4,inbuf+4,4);
3871 CVAL(outbuf,smb_rcls) = SUCCESS;
3872 CVAL(outbuf,smb_reh) = 0;
3873 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3875 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3876 SSVAL(outbuf,smb_err,SUCCESS);
3877 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3878 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3879 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3880 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3882 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3885 smb_setlen(outbuf,outsize - 4);
3890 /****************************************************************************
3891 process commands from the client
3892 ****************************************************************************/
3895 static int trans_num = 0;
3897 extern struct from_host Client_info;
3900 fromhost(Client,&Client_info);
3902 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3903 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3904 if ((InBuffer == NULL) || (OutBuffer == NULL))
3907 InBuffer += SMB_ALIGNMENT;
3908 OutBuffer += SMB_ALIGNMENT;
3911 DEBUG(3,("priming nmbd\n"));
3914 ip = *interpret_addr2("localhost");
3915 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3917 send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM);
3921 last_user.cnum = -1;
3929 int deadtime = lp_deadtime()*60;
3931 int last_keepalive=0;
3934 deadtime = DEFAULT_SMBD_TIMEOUT;
3936 if (lp_readprediction())
3937 do_read_prediction();
3940 extern pstring share_del_pending;
3941 if (*share_del_pending) {
3943 if (!unlink(share_del_pending))
3944 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3946 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3947 share_del_pending[0] = 0;
3951 if (share_mode_pending) {
3953 check_share_modes();
3954 share_mode_pending=False;
3959 for (counter=SMBD_SELECT_LOOP;
3960 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3961 counter += SMBD_SELECT_LOOP)
3965 BOOL allidle = True;
3966 extern int keepalive;
3968 /* check for socket failure */
3969 if (errno == EBADF) {
3970 DEBUG(3,("%s Bad file descriptor - exiting\n",timestring()));
3976 /* become root again if waiting */
3979 /* check for smb.conf reload */
3980 if (!(counter%SMBD_RELOAD_CHECK))
3981 reload_services(True);
3983 /* check the share modes every 10 secs */
3984 if (!(counter%SHARE_MODES_CHECK))
3985 check_share_modes();
3987 /* clean the share modes every 5 minutes */
3988 if (!(counter%SHARE_MODES_CLEAN))
3989 clean_share_files();
3991 /* automatic timeout if all connections are closed */
3992 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3993 DEBUG(2,("%s Closing idle connection\n",timestring()));
3997 if (keepalive && (counter-last_keepalive)>keepalive) {
3998 if (!send_keepalive(Client)) {
3999 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
4002 last_keepalive = counter;
4005 /* check for connection timeouts */
4006 for (i=0;i<MAX_CONNECTIONS;i++)
4007 if (Connections[i].open)
4009 /* close dirptrs on connections that are idle */
4010 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4013 if (Connections[i].num_files_open > 0 ||
4014 (t-Connections[i].lastused)<deadtime)
4018 if (allidle && num_connections_open>0) {
4019 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4024 msg_type = CVAL(InBuffer,0);
4025 msg_flags = CVAL(InBuffer,1);
4026 type = CVAL(InBuffer,smb_com);
4028 len = smb_len(InBuffer);
4030 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
4034 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4037 if(trans_num == 1 && VT_Check(InBuffer)) {
4047 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
4050 if (CVAL(OutBuffer,0) == 0)
4051 show_msg(OutBuffer);
4053 if (nread != smb_len(OutBuffer) + 4)
4055 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4057 smb_len(OutBuffer)));
4060 send_smb(Client,OutBuffer);
4067 /****************************************************************************
4068 initialise connect, service and file structs
4069 ****************************************************************************/
4070 static void init_structs(void )
4073 get_myname(myhostname,&myip);
4075 for (i=0;i<MAX_CONNECTIONS;i++)
4077 Connections[i].open = False;
4078 Connections[i].num_files_open=0;
4079 Connections[i].lastused=0;
4080 Connections[i].used=False;
4081 string_init(&Connections[i].user,"");
4082 string_init(&Connections[i].dirpath,"");
4083 string_init(&Connections[i].connectpath,"");
4084 string_init(&Connections[i].origpath,"");
4087 for (i=0;i<MAX_OPEN_FILES;i++)
4089 Files[i].open = False;
4090 string_init(&Files[i].name,"");
4096 /****************************************************************************
4097 usage on the program
4098 ****************************************************************************/
4099 void usage(char *pname)
4101 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4103 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4104 printf("Version %s\n",VERSION);
4105 printf("\t-D become a daemon\n");
4106 printf("\t-p port listen on the specified port\n");
4107 printf("\t-d debuglevel set the debuglevel\n");
4108 printf("\t-l log basename. Basename for log/debug files\n");
4109 printf("\t-s services file. Filename of services file\n");
4110 printf("\t-P passive only\n");
4111 printf("\t-a overwrite log file, don't append\n");
4116 /****************************************************************************
4118 ****************************************************************************/
4119 int main(int argc,char *argv[])
4121 extern BOOL append_log;
4122 /* shall I run as a daemon */
4123 BOOL is_daemon = False;
4126 extern char *optarg;
4128 #ifdef NEED_AUTH_PARAMETERS
4129 set_auth_parameters(argc,argv);
4140 strcpy(debugf,SMBLOGFILE);
4142 setup_logging(argv[0],False);
4144 charset_initialise();
4146 /* make absolutely sure we run as root - to handle cases whre people
4147 are crazy enough to have it setuid */
4157 fault_setup(exit_server);
4159 umask(0777 & ~DEF_CREATE_MASK);
4161 initial_uid = geteuid();
4162 initial_gid = getegid();
4164 if (initial_gid != 0 && initial_uid == 0)
4174 initial_uid = geteuid();
4175 initial_gid = getegid();
4178 /* this is for people who can't start the program correctly */
4179 while (argc > 1 && (*argv[1] != '-'))
4185 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
4189 strcpy(user_socket_options,optarg);
4192 strcpy(scope,optarg);
4196 extern BOOL passive;
4201 strcpy(servicesf,optarg);
4204 strcpy(debugf,optarg);
4208 extern BOOL append_log;
4209 append_log = !append_log;
4219 DEBUGLEVEL = atoi(optarg);
4222 port = atoi(optarg);
4235 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4236 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4240 #ifndef NO_GETRLIMIT
4241 #ifdef RLIMIT_NOFILE
4244 getrlimit(RLIMIT_NOFILE, &rlp);
4245 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4246 setrlimit(RLIMIT_NOFILE, &rlp);
4247 getrlimit(RLIMIT_NOFILE, &rlp);
4248 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4254 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4255 getuid(),getgid(),geteuid(),getegid()));
4257 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4259 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4265 if (!reload_services(False))
4268 #ifndef NO_SIGNAL_TEST
4269 signal(SIGHUP,SIGNAL_CAST sig_hup);
4272 DEBUG(3,("%s loaded services\n",timestring()));
4274 if (!is_daemon && !is_a_socket(0))
4276 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4282 DEBUG(3,("%s becoming a daemon\n",timestring()));
4286 if (!open_sockets(is_daemon,port))
4289 /* possibly reload the services file. */
4290 reload_services(True);
4292 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4296 if (sys_chroot(lp_rootdir()) == 0)
4297 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4303 exit_server("normal exit");