Makefile: Added cleandir target.
[Samba.git] / source / smbd / server.c
blob09c8fccb5c4fa4dac836cb9b9ce4c38c009eafc9
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
22 #include "includes.h"
23 #include "trans2.h"
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
29 char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
33 int am_parent = 1;
34 int atexit_set = 0;
36 BOOL share_mode_pending = False;
38 /* the last message the was processed */
39 int last_message = -1;
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
44 extern pstring scope;
45 extern int DEBUGLEVEL;
46 extern int case_default;
47 extern BOOL case_sensitive;
48 extern BOOL case_preserve;
49 extern BOOL use_mangled_map;
50 extern BOOL short_case_preserve;
51 extern BOOL case_mangle;
52 extern time_t smb_last_time;
54 extern int smb_read_error;
56 extern pstring user_socket_options;
58 connection_struct Connections[MAX_CONNECTIONS];
59 files_struct Files[MAX_OPEN_FILES];
62 * Indirection for file fd's. Needed as POSIX locking
63 * is based on file/process, not fd/process.
65 file_fd_struct FileFd[MAX_OPEN_FILES];
66 int max_file_fd_used = 0;
68 extern int Protocol;
70 int maxxmit = BUFFER_SIZE;
72 /* a fnum to use when chaining */
73 int chain_fnum = -1;
75 /* number of open connections */
76 static int num_connections_open = 0;
78 extern fstring remote_machine;
80 pstring OriginalDir;
82 /* these can be set by some functions to override the error codes */
83 int unix_ERR_class=SUCCESS;
84 int unix_ERR_code=0;
87 extern int extra_time_offset;
89 extern pstring myhostname;
91 static int find_free_connection(int hash);
93 /* for readability... */
94 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
95 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
96 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
97 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
98 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
100 /****************************************************************************
101 when exiting, take the whole family
102 ****************************************************************************/
103 void *dflt_sig(void)
105 exit_server("caught signal");
107 /****************************************************************************
108 Send a SIGTERM to our process group.
109 *****************************************************************************/
110 void killkids(void)
112 if(am_parent) kill(0,SIGTERM);
115 /****************************************************************************
116 change a dos mode to a unix mode
117 base permission for files:
118 everybody gets read bit set
119 dos readonly is represented in unix by removing everyone's write bit
120 dos archive is represented in unix by the user's execute bit
121 dos system is represented in unix by the group's execute bit
122 dos hidden is represented in unix by the other's execute bit
123 base permission for directories:
124 dos directory is represented in unix by unix's dir bit and the exec bit
125 ****************************************************************************/
126 mode_t unix_mode(int cnum,int dosmode)
128 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
130 if ( !IS_DOS_READONLY(dosmode) )
131 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
133 if (IS_DOS_DIR(dosmode)) {
134 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
135 result &= (lp_dir_mode(SNUM(cnum)) | 0700);
136 } else {
137 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
138 result |= S_IXUSR;
140 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
141 result |= S_IXGRP;
143 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
144 result |= S_IXOTH;
146 result &= CREATE_MODE(cnum);
148 return(result);
152 /****************************************************************************
153 change a unix mode to a dos mode
154 ****************************************************************************/
155 int dos_mode(int cnum,char *path,struct stat *sbuf)
157 int result = 0;
158 extern struct current_user current_user;
160 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
161 if (!((sbuf->st_mode & S_IWOTH) ||
162 Connections[cnum].admin_user ||
163 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
164 ((sbuf->st_mode & S_IWGRP) &&
165 in_group(sbuf->st_gid,current_user.gid,
166 current_user.ngroups,current_user.igroups))))
167 result |= aRONLY;
168 } else {
169 if ((sbuf->st_mode & S_IWUSR) == 0)
170 result |= aRONLY;
173 if ((sbuf->st_mode & S_IXUSR) != 0)
174 result |= aARCH;
176 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
177 result |= aSYSTEM;
179 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
180 result |= aHIDDEN;
182 if (S_ISDIR(sbuf->st_mode))
183 result = aDIR | (result & aRONLY);
185 #if LINKS_READ_ONLY
186 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
187 result |= aRONLY;
188 #endif
190 /* hide files with a name starting with a . */
191 if (lp_hide_dot_files(SNUM(cnum)))
193 char *p = strrchr(path,'/');
194 if (p)
195 p++;
196 else
197 p = path;
199 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
200 result |= aHIDDEN;
203 return(result);
207 /*******************************************************************
208 chmod a file - but preserve some bits
209 ********************************************************************/
210 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
212 struct stat st1;
213 int mask=0;
214 int tmp;
215 int unixmode;
217 if (!st) {
218 st = &st1;
219 if (sys_stat(fname,st)) return(-1);
222 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
224 if (dos_mode(cnum,fname,st) == dosmode) return(0);
226 unixmode = unix_mode(cnum,dosmode);
228 /* preserve the s bits */
229 mask |= (S_ISUID | S_ISGID);
231 /* preserve the t bit */
232 #ifdef S_ISVTX
233 mask |= S_ISVTX;
234 #endif
236 /* possibly preserve the x bits */
237 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
238 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
239 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
241 unixmode |= (st->st_mode & mask);
243 /* if we previously had any r bits set then leave them alone */
244 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
245 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
246 unixmode |= tmp;
249 /* if we previously had any w bits set then leave them alone
250 if the new mode is not rdonly */
251 if (!IS_DOS_READONLY(dosmode) &&
252 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
253 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
254 unixmode |= tmp;
257 return(sys_chmod(fname,unixmode));
261 /****************************************************************************
262 check if two filenames are equal
264 this needs to be careful about whether we are case sensitive
265 ****************************************************************************/
266 static BOOL fname_equal(char *name1, char *name2)
268 int l1 = strlen(name1);
269 int l2 = strlen(name2);
271 /* handle filenames ending in a single dot */
272 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
274 BOOL ret;
275 name1[l1-1] = 0;
276 ret = fname_equal(name1,name2);
277 name1[l1-1] = '.';
278 return(ret);
281 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
283 BOOL ret;
284 name2[l2-1] = 0;
285 ret = fname_equal(name1,name2);
286 name2[l2-1] = '.';
287 return(ret);
290 /* now normal filename handling */
291 if (case_sensitive)
292 return(strcmp(name1,name2) == 0);
294 return(strequal(name1,name2));
298 /****************************************************************************
299 mangle the 2nd name and check if it is then equal to the first name
300 ****************************************************************************/
301 static BOOL mangled_equal(char *name1, char *name2)
303 pstring tmpname;
305 if (is_8_3(name2, True))
306 return(False);
308 strcpy(tmpname,name2);
309 mangle_name_83(tmpname);
311 return(strequal(name1,tmpname));
315 /****************************************************************************
316 scan a directory to find a filename, matching without case sensitivity
318 If the name looks like a mangled name then try via the mangling functions
319 ****************************************************************************/
320 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
322 void *cur_dir;
323 char *dname;
324 BOOL mangled;
325 pstring name2;
327 mangled = is_mangled(name);
329 /* handle null paths */
330 if (*path == 0)
331 path = ".";
333 if (docache && (dname = DirCacheCheck(path,name,snum))) {
334 strcpy(name, dname);
335 return(True);
338 if (mangled)
339 check_mangled_stack(name);
341 /* open the directory */
342 if (!(cur_dir = OpenDir(path)))
344 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
345 return(False);
348 /* now scan for matching names */
349 while ((dname = ReadDirName(cur_dir)))
351 if (*dname == '.' &&
352 (strequal(dname,".") || strequal(dname,"..")))
353 continue;
355 strcpy(name2,dname);
356 if (!name_map_mangle(name2,False,snum)) continue;
358 if ((mangled && mangled_equal(name,name2))
359 || fname_equal(name, name2))
361 /* we've found the file, change it's name and return */
362 if (docache) DirCacheAdd(path,name,dname,snum);
363 strcpy(name, dname);
364 CloseDir(cur_dir);
365 return(True);
369 CloseDir(cur_dir);
370 return(False);
373 /****************************************************************************
374 This routine is called to convert names from the dos namespace to unix
375 namespace. It needs to handle any case conversions, mangling, format
376 changes etc.
378 We assume that we have already done a chdir() to the right "root" directory
379 for this service.
381 The function will return False if some part of the name except for the last
382 part cannot be resolved
384 If the saved_last_component != 0, then the unmodified last component
385 of the pathname is returned there. This is used in an exceptional
386 case in reply_mv (so far). If saved_last_component == 0 then nothing
387 is returned there.
388 ****************************************************************************/
389 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
391 struct stat st;
392 char *start, *end;
393 pstring dirpath;
395 *dirpath = 0;
396 if(saved_last_component)
397 *saved_last_component = 0;
399 /* convert to basic unix format - removing \ chars and cleaning it up */
400 unix_format(name);
401 unix_clean_name(name);
403 /* names must be relative to the root of the service - trim any leading /.
404 also trim trailing /'s */
405 trim_string(name,"/","/");
408 * Ensure saved_last_component is valid even if file exists.
410 if(saved_last_component) {
411 end = strrchr(name, '/');
412 if(end)
413 strcpy(saved_last_component, end + 1);
414 else
415 strcpy(saved_last_component, name);
418 if (!case_sensitive &&
419 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
420 strnorm(name);
422 /* check if it's a printer file */
423 if (Connections[cnum].printer)
425 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
427 char *s;
428 fstring name2;
429 sprintf(name2,"%.6s.XXXXXX",remote_machine);
430 /* sanitise the name */
431 for (s=name2 ; *s ; s++)
432 if (!issafe(*s)) *s = '_';
433 strcpy(name,(char *)mktemp(name2));
435 return(True);
438 /* stat the name - if it exists then we are all done! */
439 if (sys_stat(name,&st) == 0)
440 return(True);
442 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
444 /* a special case - if we don't have any mangling chars and are case
445 sensitive then searching won't help */
446 if (case_sensitive && !is_mangled(name) &&
447 !lp_strip_dot() && !use_mangled_map)
448 return(False);
450 /* now we need to recursively match the name against the real
451 directory structure */
453 start = name;
454 while (strncmp(start,"./",2) == 0)
455 start += 2;
457 /* now match each part of the path name separately, trying the names
458 as is first, then trying to scan the directory for matching names */
459 for (;start;start = (end?end+1:(char *)NULL))
461 /* pinpoint the end of this section of the filename */
462 end = strchr(start, '/');
464 /* chop the name at this point */
465 if (end) *end = 0;
467 if(saved_last_component != 0)
468 strcpy(saved_last_component, end ? end + 1 : start);
470 /* check if the name exists up to this point */
471 if (sys_stat(name, &st) == 0)
473 /* it exists. it must either be a directory or this must be
474 the last part of the path for it to be OK */
475 if (end && !(st.st_mode & S_IFDIR))
477 /* an intermediate part of the name isn't a directory */
478 DEBUG(5,("Not a dir %s\n",start));
479 *end = '/';
480 return(False);
483 else
485 pstring rest;
487 *rest = 0;
489 /* remember the rest of the pathname so it can be restored
490 later */
491 if (end) strcpy(rest,end+1);
493 /* try to find this part of the path in the directory */
494 if (strchr(start,'?') || strchr(start,'*') ||
495 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
497 if (end)
499 /* an intermediate part of the name can't be found */
500 DEBUG(5,("Intermediate not found %s\n",start));
501 *end = '/';
502 return(False);
505 /* just the last part of the name doesn't exist */
506 /* we may need to strupper() or strlower() it in case
507 this conversion is being used for file creation
508 purposes */
509 /* if the filename is of mixed case then don't normalise it */
510 if (!case_preserve &&
511 (!strhasupper(start) || !strhaslower(start)))
512 strnorm(start);
514 /* check on the mangled stack to see if we can recover the
515 base of the filename */
516 if (is_mangled(start))
517 check_mangled_stack(start);
519 DEBUG(5,("New file %s\n",start));
520 return(True);
523 /* restore the rest of the string */
524 if (end)
526 strcpy(start+strlen(start)+1,rest);
527 end = start + strlen(start);
531 /* add to the dirpath that we have resolved so far */
532 if (*dirpath) strcat(dirpath,"/");
533 strcat(dirpath,start);
535 /* restore the / that we wiped out earlier */
536 if (end) *end = '/';
539 /* the name has been resolved */
540 DEBUG(5,("conversion finished %s\n",name));
541 return(True);
545 /****************************************************************************
546 normalise for DOS usage
547 ****************************************************************************/
548 static void disk_norm(int *bsize,int *dfree,int *dsize)
550 /* check if the disk is beyond the max disk size */
551 int maxdisksize = lp_maxdisksize();
552 if (maxdisksize) {
553 /* convert to blocks - and don't overflow */
554 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
555 if (*dsize > maxdisksize) *dsize = maxdisksize;
556 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
557 applications getting
558 div by 0 errors */
561 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
563 *dfree /= 2;
564 *dsize /= 2;
565 *bsize *= 2;
566 if (*bsize > WORDMAX )
568 *bsize = WORDMAX;
569 if (*dsize > WORDMAX)
570 *dsize = WORDMAX;
571 if (*dfree > WORDMAX)
572 *dfree = WORDMAX;
573 break;
578 /****************************************************************************
579 return number of 1K blocks available on a path and total number
580 ****************************************************************************/
581 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
583 char *df_command = lp_dfree_command();
584 #ifndef NO_STATFS
585 #ifdef USE_STATVFS
586 struct statvfs fs;
587 #else
588 #ifdef ULTRIX
589 struct fs_data fs;
590 #else
591 struct statfs fs;
592 #endif
593 #endif
594 #endif
596 #ifdef QUOTAS
597 if (disk_quotas(path, bsize, dfree, dsize))
599 disk_norm(bsize,dfree,dsize);
600 return(((*bsize)/1024)*(*dfree));
602 #endif
605 /* possibly use system() to get the result */
606 if (df_command && *df_command)
608 int ret;
609 pstring syscmd;
610 pstring outfile;
612 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
613 sprintf(syscmd,"%s %s",df_command,path);
614 standard_sub_basic(syscmd);
616 ret = smbrun(syscmd,outfile,False);
617 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
620 FILE *f = fopen(outfile,"r");
621 *dsize = 0;
622 *dfree = 0;
623 *bsize = 1024;
624 if (f)
626 fscanf(f,"%d %d %d",dsize,dfree,bsize);
627 fclose(f);
629 else
630 DEBUG(0,("Can't open %s\n",outfile));
633 unlink(outfile);
634 disk_norm(bsize,dfree,dsize);
635 return(((*bsize)/1024)*(*dfree));
638 #ifdef NO_STATFS
639 DEBUG(1,("Warning - no statfs function\n"));
640 return(1);
641 #else
642 #ifdef STATFS4
643 if (statfs(path,&fs,sizeof(fs),0) != 0)
644 #else
645 #ifdef USE_STATVFS
646 if (statvfs(path, &fs))
647 #else
648 #ifdef STATFS3
649 if (statfs(path,&fs,sizeof(fs)) == -1)
650 #else
651 if (statfs(path,&fs) == -1)
652 #endif /* STATFS3 */
653 #endif /* USE_STATVFS */
654 #endif /* STATFS4 */
656 DEBUG(3,("dfree call failed code errno=%d\n",errno));
657 *bsize = 1024;
658 *dfree = 1;
659 *dsize = 1;
660 return(((*bsize)/1024)*(*dfree));
663 #ifdef ULTRIX
664 *bsize = 1024;
665 *dfree = fs.fd_req.bfree;
666 *dsize = fs.fd_req.btot;
667 #else
668 #ifdef USE_STATVFS
669 *bsize = fs.f_frsize;
670 #else
671 #ifdef USE_F_FSIZE
672 /* eg: osf1 has f_fsize = fundamental filesystem block size,
673 f_bsize = optimal transfer block size (MX: 94-04-19) */
674 *bsize = fs.f_fsize;
675 #else
676 *bsize = fs.f_bsize;
677 #endif /* STATFS3 */
678 #endif /* USE_STATVFS */
680 #ifdef STATFS4
681 *dfree = fs.f_bfree;
682 #else
683 *dfree = fs.f_bavail;
684 #endif /* STATFS4 */
685 *dsize = fs.f_blocks;
686 #endif /* ULTRIX */
688 #if defined(SCO) || defined(ISC) || defined(MIPS)
689 *bsize = 512;
690 #endif
692 /* handle rediculous bsize values - some OSes are broken */
693 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
695 disk_norm(bsize,dfree,dsize);
697 if (*bsize < 256)
698 *bsize = 512;
699 if ((*dsize)<1)
701 DEBUG(0,("dfree seems to be broken on your system\n"));
702 *dsize = 20*1024*1024/(*bsize);
703 *dfree = MAX(1,*dfree);
705 return(((*bsize)/1024)*(*dfree));
706 #endif
710 /****************************************************************************
711 wrap it to get filenames right
712 ****************************************************************************/
713 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
715 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
720 /****************************************************************************
721 check a filename - possibly caling reducename
723 This is called by every routine before it allows an operation on a filename.
724 It does any final confirmation necessary to ensure that the filename is
725 a valid one for the user to access.
726 ****************************************************************************/
727 BOOL check_name(char *name,int cnum)
729 BOOL ret;
731 errno = 0;
733 if( is_vetoed_path(name))
735 DEBUG(5,("file path name %s vetoed\n",name));
736 return(0);
739 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
740 if (!ret)
741 DEBUG(5,("check_name on %s failed\n",name));
743 return(ret);
746 /****************************************************************************
747 check a filename - possibly caling reducename
748 ****************************************************************************/
749 static void check_for_pipe(char *fname)
751 /* special case of pipe opens */
752 char s[10];
753 StrnCpy(s,fname,9);
754 strlower(s);
755 if (strstr(s,"pipe/"))
757 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
758 unix_ERR_class = ERRSRV;
759 unix_ERR_code = ERRaccess;
763 /****************************************************************************
764 fd support routines - attempt to do a sys_open
765 ****************************************************************************/
767 int fd_attempt_open(char *fname, int flags, int mode)
769 int fd = sys_open(fname,flags,mode);
771 /* Fix for files ending in '.' */
772 if((fd == -1) && (errno == ENOENT) &&
773 (strchr(fname,'.')==NULL))
775 strcat(fname,".");
776 fd = sys_open(fname,flags,mode);
779 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
780 if ((fd == -1) && (errno == ENAMETOOLONG))
782 int max_len;
783 char *p = strrchr(fname, '/');
785 if (p == fname) /* name is "/xxx" */
787 max_len = pathconf("/", _PC_NAME_MAX);
788 p++;
790 else if ((p == NULL) || (p == fname))
792 p = fname;
793 max_len = pathconf(".", _PC_NAME_MAX);
795 else
797 *p = '\0';
798 max_len = pathconf(fname, _PC_NAME_MAX);
799 *p = '/';
800 p++;
802 if (strlen(p) > max_len)
804 char tmp = p[max_len];
806 p[max_len] = '\0';
807 if ((fd = sys_open(fname,flags,mode)) == -1)
808 p[max_len] = tmp;
811 #endif
812 return fd;
815 /****************************************************************************
816 fd support routines - attempt to find an already open file by dev
817 and inode - increments the ref_count of the returned file_fd_struct *.
818 ****************************************************************************/
819 file_fd_struct *fd_get_already_open(struct stat *sbuf)
821 int i;
822 file_fd_struct *fd_ptr;
824 if(sbuf == 0)
825 return 0;
827 for(i = 0; i <= max_file_fd_used; i++) {
828 fd_ptr = &FileFd[i];
829 if((fd_ptr->ref_count > 0) &&
830 (((int32)sbuf->st_dev) == fd_ptr->dev) &&
831 (((int32)sbuf->st_ino) == fd_ptr->inode)) {
832 fd_ptr->ref_count++;
833 DEBUG(3,
834 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
835 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
836 return fd_ptr;
839 return 0;
842 /****************************************************************************
843 fd support routines - attempt to find a empty slot in the FileFd array.
844 Increments the ref_count of the returned entry.
845 ****************************************************************************/
846 file_fd_struct *fd_get_new()
848 int i;
849 file_fd_struct *fd_ptr;
851 for(i = 0; i < MAX_OPEN_FILES; i++) {
852 fd_ptr = &FileFd[i];
853 if(fd_ptr->ref_count == 0) {
854 fd_ptr->dev = (int32)-1;
855 fd_ptr->inode = (int32)-1;
856 fd_ptr->fd = -1;
857 fd_ptr->fd_readonly = -1;
858 fd_ptr->fd_writeonly = -1;
859 fd_ptr->real_open_flags = -1;
860 fd_ptr->ref_count++;
861 /* Increment max used counter if neccessary, cuts down
862 on search time when re-using */
863 if(i > max_file_fd_used)
864 max_file_fd_used = i;
865 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
866 i, fd_ptr->dev, fd_ptr->inode));
867 return fd_ptr;
870 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
871 n"));
872 return 0;
875 /****************************************************************************
876 fd support routines - attempt to re-open an already open fd as O_RDWR.
877 Save the already open fd (we cannot close due to POSIX file locking braindamage.
878 ****************************************************************************/
880 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
882 int fd = sys_open( fname, O_RDWR, mode);
884 if(fd == -1)
885 return;
887 if(fd_ptr->real_open_flags == O_RDONLY)
888 fd_ptr->fd_readonly = fd_ptr->fd;
889 if(fd_ptr->real_open_flags == O_WRONLY)
890 fd_ptr->fd_writeonly = fd_ptr->fd;
892 fd_ptr->fd = fd;
893 fd_ptr->real_open_flags = O_RDWR;
896 /****************************************************************************
897 fd support routines - attempt to close the file referenced by this fd.
898 Decrements the ref_count and returns it.
899 ****************************************************************************/
900 int fd_attempt_close(file_fd_struct *fd_ptr)
902 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
903 fd_ptr - &FileFd[0],
904 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
905 fd_ptr->real_open_flags,
906 fd_ptr->ref_count));
907 if(fd_ptr->ref_count > 0) {
908 fd_ptr->ref_count--;
909 if(fd_ptr->ref_count == 0) {
910 if(fd_ptr->fd != -1)
911 close(fd_ptr->fd);
912 if(fd_ptr->fd_readonly != -1)
913 close(fd_ptr->fd_readonly);
914 if(fd_ptr->fd_writeonly != -1)
915 close(fd_ptr->fd_writeonly);
916 fd_ptr->fd = -1;
917 fd_ptr->fd_readonly = -1;
918 fd_ptr->fd_writeonly = -1;
919 fd_ptr->real_open_flags = -1;
920 fd_ptr->dev = -1;
921 fd_ptr->inode = -1;
924 return fd_ptr->ref_count;
927 /****************************************************************************
928 open a file
929 ****************************************************************************/
930 void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
932 extern struct current_user current_user;
933 pstring fname;
934 struct stat statbuf;
935 file_fd_struct *fd_ptr;
937 Files[fnum].open = False;
938 Files[fnum].fd_ptr = 0;
939 errno = EPERM;
941 strcpy(fname,fname1);
943 /* check permissions */
944 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
946 DEBUG(3,("Permission denied opening %s\n",fname));
947 check_for_pipe(fname);
948 return;
951 /* this handles a bug in Win95 - it doesn't say to create the file when it
952 should */
953 if (Connections[cnum].printer)
954 flags |= O_CREAT;
957 if (flags == O_WRONLY)
958 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
961 #if UTIME_WORKAROUND
962 /* XXXX - is this OK?? */
963 /* this works around a utime bug but can cause other problems */
964 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
965 sys_unlink(fname);
966 #endif
969 * Ensure we have a valid struct stat so we can search the
970 * open fd table.
972 if(sbuf == 0) {
973 if(stat(fname, &statbuf) < 0) {
974 if(errno != ENOENT) {
975 DEBUG(3,("Error doing stat on file %s (%s)\n",
976 fname,strerror(errno)));
978 check_for_pipe(fname);
979 return;
981 sbuf = 0;
982 } else {
983 sbuf = &statbuf;
988 * Check to see if we have this file already
989 * open. If we do, just use the already open fd and increment the
990 * reference count (fd_get_already_open increments the ref_count).
992 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
994 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
996 /* File was already open. */
997 if((flags & O_CREAT) && (flags & O_EXCL)) {
998 fd_ptr->ref_count--;
999 errno = EEXIST;
1000 return;
1004 * If not opened O_RDWR try
1005 * and do that here - a chmod may have been done
1006 * between the last open and now.
1008 if(fd_ptr->real_open_flags != O_RDWR)
1009 fd_attempt_reopen(fname, mode, fd_ptr);
1012 * Ensure that if we wanted write access
1013 * it has been opened for write, and if we wanted read it
1014 * was open for read.
1016 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1017 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1018 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1019 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1020 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1021 check_for_pipe(fname);
1022 fd_ptr->ref_count--;
1023 return;
1027 * If O_TRUNC was set, ensure we truncate the file.
1028 * open_file_shared explicitly clears this flag before
1029 * calling open_file, so we can safely do this here.
1031 if(flags & O_TRUNC)
1032 ftruncate(fd_ptr->fd, 0);
1034 } else {
1035 int open_flags;
1036 /* We need to allocate a new file_fd_struct (this increments the
1037 ref_count). */
1038 if((fd_ptr = fd_get_new()) == 0)
1039 return;
1041 * Whatever the requested flags, attempt read/write access,
1042 * as we don't know what flags future file opens may require.
1043 * If this fails, try again with the required flags.
1044 * Even if we open read/write when only read access was
1045 * requested the setting of the can_write flag in
1046 * the file_struct will protect us from errant
1047 * write requests. We never need to worry about O_APPEND
1048 * as this is not set anywhere in Samba.
1050 fd_ptr->real_open_flags = O_RDWR;
1051 /* Set the flags as needed without the read/write modes. */
1052 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1053 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1055 * On some systems opening a file for R/W access on a read only
1056 * filesystems sets errno to EROFS.
1058 #ifdef EROFS
1059 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1060 #else /* No EROFS */
1061 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1062 #endif /* EROFS */
1063 if(flags & O_WRONLY) {
1064 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1065 fd_ptr->real_open_flags = O_WRONLY;
1066 } else {
1067 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1068 fd_ptr->real_open_flags = O_RDONLY;
1073 if ((fd_ptr->fd >=0) &&
1074 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1075 pstring dname;
1076 int dum1,dum2,dum3;
1077 char *p;
1078 strcpy(dname,fname);
1079 p = strrchr(dname,'/');
1080 if (p) *p = 0;
1081 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1082 lp_minprintspace(SNUM(cnum))) {
1083 fd_attempt_close(fd_ptr);
1084 Files[fnum].fd_ptr = 0;
1085 if(fd_ptr->ref_count == 0)
1086 sys_unlink(fname);
1087 errno = ENOSPC;
1088 return;
1092 if (fd_ptr->fd < 0)
1094 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1095 fname,strerror(errno),flags));
1096 /* Ensure the ref_count is decremented. */
1097 fd_attempt_close(fd_ptr);
1098 check_for_pipe(fname);
1099 return;
1102 if (fd_ptr->fd >= 0)
1104 if(sbuf == 0) {
1105 /* Do the fstat */
1106 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1107 /* Error - backout !! */
1108 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1109 fd_ptr->fd, fname,strerror(errno)));
1110 /* Ensure the ref_count is decremented. */
1111 fd_attempt_close(fd_ptr);
1112 return;
1114 sbuf = &statbuf;
1116 /* Set the correct entries in fd_ptr. */
1117 fd_ptr->dev = (int32)sbuf->st_dev;
1118 fd_ptr->inode = (int32)sbuf->st_ino;
1120 Files[fnum].fd_ptr = fd_ptr;
1121 Connections[cnum].num_files_open++;
1122 Files[fnum].mode = sbuf->st_mode;
1123 GetTimeOfDay(&Files[fnum].open_time);
1124 Files[fnum].uid = current_user.id;
1125 Files[fnum].size = 0;
1126 Files[fnum].pos = -1;
1127 Files[fnum].open = True;
1128 Files[fnum].mmap_ptr = NULL;
1129 Files[fnum].mmap_size = 0;
1130 Files[fnum].can_lock = True;
1131 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1132 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1133 Files[fnum].share_mode = 0;
1134 Files[fnum].share_pending = False;
1135 Files[fnum].print_file = Connections[cnum].printer;
1136 Files[fnum].modified = False;
1137 Files[fnum].cnum = cnum;
1138 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1139 Files[fnum].wbmpx_ptr = NULL;
1142 * If the printer is marked as postscript output a leading
1143 * file identifier to ensure the file is treated as a raw
1144 * postscript file.
1145 * This has a similar effect as CtrlD=0 in WIN.INI file.
1146 * tim@fsg.com 09/06/94
1148 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1149 Files[fnum].can_write)
1151 DEBUG(3,("Writing postscript line\n"));
1152 write_file(fnum,"%!\n",3);
1155 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1156 timestring(),Connections[cnum].user,fname,
1157 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1158 Connections[cnum].num_files_open,fnum));
1162 #if USE_MMAP
1163 /* mmap it if read-only */
1164 if (!Files[fnum].can_write)
1166 Files[fnum].mmap_size = file_size(fname);
1167 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1168 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1170 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1172 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1173 Files[fnum].mmap_ptr = NULL;
1176 #endif
1179 /*******************************************************************
1180 sync a file
1181 ********************************************************************/
1182 void sync_file(int fnum)
1184 #ifndef NO_FSYNC
1185 fsync(Files[fnum].fd_ptr->fd);
1186 #endif
1189 /****************************************************************************
1190 run a file if it is a magic script
1191 ****************************************************************************/
1192 static void check_magic(int fnum,int cnum)
1194 if (!*lp_magicscript(SNUM(cnum)))
1195 return;
1197 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1200 char *p;
1201 if (!(p = strrchr(Files[fnum].name,'/')))
1202 p = Files[fnum].name;
1203 else
1204 p++;
1206 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1207 return;
1211 int ret;
1212 pstring magic_output;
1213 pstring fname;
1214 strcpy(fname,Files[fnum].name);
1216 if (*lp_magicoutput(SNUM(cnum)))
1217 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1218 else
1219 sprintf(magic_output,"%s.out",fname);
1221 chmod(fname,0755);
1222 ret = smbrun(fname,magic_output,False);
1223 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1224 unlink(fname);
1229 /****************************************************************************
1230 close a file - possibly invalidating the read prediction
1231 ****************************************************************************/
1232 void close_file(int fnum)
1234 int cnum = Files[fnum].cnum;
1235 invalidate_read_prediction(Files[fnum].fd_ptr->fd);
1236 Files[fnum].open = False;
1237 Connections[cnum].num_files_open--;
1238 if(Files[fnum].wbmpx_ptr)
1240 free((char *)Files[fnum].wbmpx_ptr);
1241 Files[fnum].wbmpx_ptr = NULL;
1244 #if USE_MMAP
1245 if(Files[fnum].mmap_ptr)
1247 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1248 Files[fnum].mmap_ptr = NULL;
1250 #endif
1252 if (lp_share_modes(SNUM(cnum)))
1253 del_share_mode(fnum);
1255 fd_attempt_close(Files[fnum].fd_ptr);
1257 /* NT uses smbclose to start a print - weird */
1258 if (Files[fnum].print_file)
1259 print_file(fnum);
1261 /* check for magic scripts */
1262 check_magic(fnum,cnum);
1264 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1265 timestring(),Connections[cnum].user,Files[fnum].name,
1266 Connections[cnum].num_files_open));
1269 enum {AFAIL,AREAD,AWRITE,AALL};
1271 /*******************************************************************
1272 reproduce the share mode access table
1273 ********************************************************************/
1274 static int access_table(int new_deny,int old_deny,int old_mode,
1275 int share_pid,char *fname)
1277 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1279 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1280 if (old_deny == new_deny && share_pid == getpid())
1281 return(AALL);
1283 if (old_mode == 0) return(AREAD);
1285 /* the new smbpub.zip spec says that if the file extension is
1286 .com, .dll, .exe or .sym then allow the open. I will force
1287 it to read-only as this seems sensible although the spec is
1288 a little unclear on this. */
1289 if ((fname = strrchr(fname,'.'))) {
1290 if (strequal(fname,".com") ||
1291 strequal(fname,".dll") ||
1292 strequal(fname,".exe") ||
1293 strequal(fname,".sym"))
1294 return(AREAD);
1297 return(AFAIL);
1300 switch (new_deny)
1302 case DENY_WRITE:
1303 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1304 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1305 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1306 return(AFAIL);
1307 case DENY_READ:
1308 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1309 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1310 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1311 return(AFAIL);
1312 case DENY_NONE:
1313 if (old_deny==DENY_WRITE) return(AREAD);
1314 if (old_deny==DENY_READ) return(AWRITE);
1315 if (old_deny==DENY_NONE) return(AALL);
1316 return(AFAIL);
1318 return(AFAIL);
1321 /*******************************************************************
1322 check if the share mode on a file allows it to be deleted or unlinked
1323 return True if sharing doesn't prevent the operation
1324 ********************************************************************/
1325 BOOL check_file_sharing(int cnum,char *fname)
1327 int pid=0;
1328 int share_mode = get_share_mode_byname(cnum,fname,&pid);
1330 if (!pid || !share_mode) return(True);
1332 if (share_mode == DENY_DOS)
1333 return(pid == getpid());
1335 /* XXXX exactly what share mode combinations should be allowed for
1336 deleting/renaming? */
1337 return(False);
1340 /****************************************************************************
1341 C. Hoch 11/22/95
1342 Helper for open_file_shared.
1343 Truncate a file after checking locking; close file if locked.
1344 **************************************************************************/
1345 static void truncate_unless_locked(int fnum, int cnum)
1347 if (Files[fnum].can_write){
1348 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1349 close_file(fnum);
1350 errno = EACCES;
1351 unix_ERR_class = ERRDOS;
1352 unix_ERR_code = ERRlock;
1354 else
1355 ftruncate(Files[fnum].fd_ptr->fd,0);
1360 /****************************************************************************
1361 open a file with a share mode
1362 ****************************************************************************/
1363 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1364 int mode,int *Access,int *action)
1366 int flags=0;
1367 int flags2=0;
1368 int deny_mode = (share_mode>>4)&7;
1369 struct stat sbuf;
1370 BOOL file_existed = file_exist(fname,&sbuf);
1371 BOOL fcbopen = False;
1372 int share_pid=0;
1374 Files[fnum].open = False;
1375 Files[fnum].fd_ptr = 0;
1377 /* this is for OS/2 EAs - try and say we don't support them */
1378 if (strstr(fname,".+,;=[].")) {
1379 unix_ERR_class = ERRDOS;
1380 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1381 return;
1384 if ((ofun & 0x3) == 0 && file_existed) {
1385 errno = EEXIST;
1386 return;
1389 if (ofun & 0x10)
1390 flags2 |= O_CREAT;
1391 if ((ofun & 0x3) == 2)
1392 flags2 |= O_TRUNC;
1394 /* note that we ignore the append flag as
1395 append does not mean the same thing under dos and unix */
1397 switch (share_mode&0xF)
1399 case 1:
1400 flags = O_WRONLY;
1401 break;
1402 case 0xF:
1403 fcbopen = True;
1404 flags = O_RDWR;
1405 break;
1406 case 2:
1407 flags = O_RDWR;
1408 break;
1409 default:
1410 flags = O_RDONLY;
1411 break;
1414 if (flags != O_RDONLY && file_existed &&
1415 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1416 if (!fcbopen) {
1417 errno = EACCES;
1418 return;
1420 flags = O_RDONLY;
1423 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1424 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1425 errno = EINVAL;
1426 return;
1429 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1431 if (lp_share_modes(SNUM(cnum))) {
1432 int old_share=0;
1434 if (file_existed)
1435 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1437 if (share_pid) {
1438 /* someone else has a share lock on it, check to see
1439 if we can too */
1440 int old_open_mode = old_share&0xF;
1441 int old_deny_mode = (old_share>>4)&7;
1443 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
1444 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1445 deny_mode,old_deny_mode,old_open_mode,fname));
1446 errno = EACCES;
1447 unix_ERR_class = ERRDOS;
1448 unix_ERR_code = ERRbadshare;
1449 return;
1453 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1454 share_pid,fname);
1456 if ((access_allowed == AFAIL) ||
1457 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1458 (access_allowed == AREAD && flags == O_WRONLY) ||
1459 (access_allowed == AWRITE && flags == O_RDONLY)) {
1460 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1461 deny_mode,old_deny_mode,old_open_mode,
1462 share_pid,fname,
1463 access_allowed));
1464 errno = EACCES;
1465 unix_ERR_class = ERRDOS;
1466 unix_ERR_code = ERRbadshare;
1467 return;
1470 if (access_allowed == AREAD)
1471 flags = O_RDONLY;
1473 if (access_allowed == AWRITE)
1474 flags = O_WRONLY;
1479 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1480 flags,flags2,mode));
1482 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1483 if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
1484 flags = O_RDONLY;
1485 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1488 if (Files[fnum].open) {
1489 int open_mode=0;
1490 switch (flags) {
1491 case O_RDONLY:
1492 open_mode = 0;
1493 break;
1494 case O_RDWR:
1495 open_mode = 2;
1496 break;
1497 case O_WRONLY:
1498 open_mode = 1;
1499 break;
1502 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1503 Files[fnum].share_pending = True;
1505 if (Access) {
1506 (*Access) = open_mode;
1509 if (action) {
1510 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1511 if (!file_existed) *action = 2;
1512 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1515 if (!share_pid)
1516 share_mode_pending = True;
1518 if ((flags2&O_TRUNC) && file_existed)
1519 truncate_unless_locked(fnum,cnum);
1525 /*******************************************************************
1526 check for files that we should now set our share modes on
1527 ********************************************************************/
1528 static void check_share_modes(void)
1530 int i;
1531 for (i=0;i<MAX_OPEN_FILES;i++)
1532 if(Files[i].open && Files[i].share_pending) {
1533 if (lp_share_modes(SNUM(Files[i].cnum))) {
1534 int pid=0;
1535 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1536 if (!pid) {
1537 set_share_mode(i,Files[i].share_mode);
1538 Files[i].share_pending = False;
1540 } else {
1541 Files[i].share_pending = False;
1547 /****************************************************************************
1548 seek a file. Try to avoid the seek if possible
1549 ****************************************************************************/
1550 int seek_file(int fnum,int pos)
1552 int offset = 0;
1553 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1554 offset = 3;
1556 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1557 return(Files[fnum].pos);
1560 /****************************************************************************
1561 read from a file
1562 ****************************************************************************/
1563 int read_file(int fnum,char *data,int pos,int n)
1565 int ret=0,readret;
1567 if (!Files[fnum].can_write)
1569 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1571 data += ret;
1572 n -= ret;
1573 pos += ret;
1576 #if USE_MMAP
1577 if (Files[fnum].mmap_ptr)
1579 int num = MIN(n,Files[fnum].mmap_size-pos);
1580 if (num > 0)
1582 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1583 data += num;
1584 pos += num;
1585 n -= num;
1586 ret += num;
1589 #endif
1591 if (n <= 0)
1592 return(ret);
1594 if (seek_file(fnum,pos) != pos)
1596 DEBUG(3,("Failed to seek to %d\n",pos));
1597 return(ret);
1600 if (n > 0) {
1601 readret = read(Files[fnum].fd_ptr->fd,data,n);
1602 if (readret > 0) ret += readret;
1605 return(ret);
1609 /****************************************************************************
1610 write to a file
1611 ****************************************************************************/
1612 int write_file(int fnum,char *data,int n)
1614 if (!Files[fnum].can_write) {
1615 errno = EPERM;
1616 return(0);
1619 if (!Files[fnum].modified) {
1620 struct stat st;
1621 Files[fnum].modified = True;
1622 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1623 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1624 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1625 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1630 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1634 /****************************************************************************
1635 load parameters specific to a connection/service
1636 ****************************************************************************/
1637 BOOL become_service(int cnum,BOOL do_chdir)
1639 extern char magic_char;
1640 static int last_cnum = -1;
1641 int snum;
1643 if (!OPEN_CNUM(cnum))
1645 last_cnum = -1;
1646 return(False);
1649 Connections[cnum].lastused = smb_last_time;
1651 snum = SNUM(cnum);
1653 if (do_chdir &&
1654 ChDir(Connections[cnum].connectpath) != 0 &&
1655 ChDir(Connections[cnum].origpath) != 0)
1657 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1658 Connections[cnum].connectpath,cnum));
1659 return(False);
1662 if (cnum == last_cnum)
1663 return(True);
1665 last_cnum = cnum;
1667 case_default = lp_defaultcase(snum);
1668 case_preserve = lp_preservecase(snum);
1669 short_case_preserve = lp_shortpreservecase(snum);
1670 case_mangle = lp_casemangle(snum);
1671 case_sensitive = lp_casesensitive(snum);
1672 magic_char = lp_magicchar(snum);
1673 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1674 return(True);
1678 /****************************************************************************
1679 find a service entry
1680 ****************************************************************************/
1681 int find_service(char *service)
1683 int iService;
1685 string_sub(service,"\\","/");
1687 iService = lp_servicenumber(service);
1689 /* now handle the special case of a home directory */
1690 if (iService < 0)
1692 char *phome_dir = get_home_dir(service);
1693 DEBUG(3,("checking for home directory %s gave %s\n",service,
1694 phome_dir?phome_dir:"(NULL)"));
1695 if (phome_dir)
1697 int iHomeService;
1698 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1700 lp_add_home(service,iHomeService,phome_dir);
1701 iService = lp_servicenumber(service);
1706 /* If we still don't have a service, attempt to add it as a printer. */
1707 if (iService < 0)
1709 int iPrinterService;
1711 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1713 char *pszTemp;
1715 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1716 pszTemp = PRINTCAP;
1717 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1719 DEBUG(3,("%s is a valid printer name\n", service));
1720 DEBUG(3,("adding %s as a printer service\n", service));
1721 lp_add_printer(service,iPrinterService);
1722 iService = lp_servicenumber(service);
1723 if (iService < 0)
1724 DEBUG(0,("failed to add %s as a printer service!\n", service));
1726 else
1727 DEBUG(3,("%s is not a valid printer name\n", service));
1731 /* just possibly it's a default service? */
1732 if (iService < 0)
1734 char *defservice = lp_defaultservice();
1735 if (defservice && *defservice && !strequal(defservice,service)) {
1736 iService = find_service(defservice);
1737 if (iService >= 0) {
1738 string_sub(service,"_","/");
1739 iService = lp_add_service(service,iService);
1744 if (iService >= 0)
1745 if (!VALID_SNUM(iService))
1747 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1748 iService = -1;
1751 if (iService < 0)
1752 DEBUG(3,("find_service() failed to find service %s\n", service));
1754 return (iService);
1758 /****************************************************************************
1759 create an error packet from a cached error.
1760 ****************************************************************************/
1761 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1763 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1765 int32 eclass = wbmpx->wr_errclass;
1766 int32 err = wbmpx->wr_error;
1768 /* We can now delete the auxiliary struct */
1769 free((char *)wbmpx);
1770 Files[fnum].wbmpx_ptr = NULL;
1771 return error_packet(inbuf,outbuf,eclass,err,line);
1775 struct
1777 int unixerror;
1778 int smbclass;
1779 int smbcode;
1780 } unix_smb_errmap[] =
1782 {EPERM,ERRDOS,ERRnoaccess},
1783 {EACCES,ERRDOS,ERRnoaccess},
1784 {ENOENT,ERRDOS,ERRbadfile},
1785 {EIO,ERRHRD,ERRgeneral},
1786 {EBADF,ERRSRV,ERRsrverror},
1787 {EINVAL,ERRSRV,ERRsrverror},
1788 {EEXIST,ERRDOS,ERRfilexists},
1789 {ENFILE,ERRDOS,ERRnofids},
1790 {EMFILE,ERRDOS,ERRnofids},
1791 {ENOSPC,ERRHRD,ERRdiskfull},
1792 #ifdef EDQUOT
1793 {EDQUOT,ERRHRD,ERRdiskfull},
1794 #endif
1795 #ifdef ENOTEMPTY
1796 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1797 #endif
1798 #ifdef EXDEV
1799 {EXDEV,ERRDOS,ERRdiffdevice},
1800 #endif
1801 {EROFS,ERRHRD,ERRnowrite},
1802 {0,0,0}
1806 /****************************************************************************
1807 create an error packet from errno
1808 ****************************************************************************/
1809 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1811 int eclass=def_class;
1812 int ecode=def_code;
1813 int i=0;
1815 if (unix_ERR_class != SUCCESS)
1817 eclass = unix_ERR_class;
1818 ecode = unix_ERR_code;
1819 unix_ERR_class = SUCCESS;
1820 unix_ERR_code = 0;
1822 else
1824 while (unix_smb_errmap[i].smbclass != 0)
1826 if (unix_smb_errmap[i].unixerror == errno)
1828 eclass = unix_smb_errmap[i].smbclass;
1829 ecode = unix_smb_errmap[i].smbcode;
1830 break;
1832 i++;
1836 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1840 /****************************************************************************
1841 create an error packet. Normally called using the ERROR() macro
1842 ****************************************************************************/
1843 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1845 int outsize = set_message(outbuf,0,0,True);
1846 int cmd;
1847 cmd = CVAL(inbuf,smb_com);
1849 CVAL(outbuf,smb_rcls) = error_class;
1850 SSVAL(outbuf,smb_err,error_code);
1852 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1853 timestring(),
1854 line,
1855 (int)CVAL(inbuf,smb_com),
1856 smb_fn_name(CVAL(inbuf,smb_com)),
1857 error_class,
1858 error_code));
1860 if (errno != 0)
1861 DEBUG(3,("error string = %s\n",strerror(errno)));
1863 return(outsize);
1867 #ifndef SIGCLD_IGNORE
1868 /****************************************************************************
1869 this prevents zombie child processes
1870 ****************************************************************************/
1871 static int sig_cld()
1873 static int depth = 0;
1874 if (depth != 0)
1876 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1877 depth=0;
1878 return(0);
1880 depth++;
1882 BlockSignals(True,SIGCLD);
1883 DEBUG(5,("got SIGCLD\n"));
1885 #ifdef USE_WAITPID
1886 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1887 #endif
1889 /* Stop zombies */
1890 /* Stevens, Adv. Unix Prog. says that on system V you must call
1891 wait before reinstalling the signal handler, because the kernel
1892 calls the handler from within the signal-call when there is a
1893 child that has exited. This would lead to an infinite recursion
1894 if done vice versa. */
1896 #ifndef DONT_REINSTALL_SIG
1897 #ifdef SIGCLD_IGNORE
1898 signal(SIGCLD, SIG_IGN);
1899 #else
1900 signal(SIGCLD, SIGNAL_CAST sig_cld);
1901 #endif
1902 #endif
1904 #ifndef USE_WAITPID
1905 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1906 #endif
1907 depth--;
1908 BlockSignals(False,SIGCLD);
1909 return 0;
1911 #endif
1913 /****************************************************************************
1914 this is called when the client exits abruptly
1915 **************************************************************************/
1916 static int sig_pipe()
1918 extern int password_client;
1919 BlockSignals(True,SIGPIPE);
1921 if (password_client != -1) {
1922 DEBUG(3,("lost connection to password server\n"));
1923 close(password_client);
1924 password_client = -1;
1925 #ifndef DONT_REINSTALL_SIG
1926 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1927 #endif
1928 BlockSignals(False,SIGPIPE);
1929 return 0;
1932 exit_server("Got sigpipe\n");
1933 return(0);
1936 /****************************************************************************
1937 open the socket communication
1938 ****************************************************************************/
1939 static BOOL open_sockets(BOOL is_daemon,int port)
1941 extern int Client;
1943 if (is_daemon)
1945 int s;
1946 struct sockaddr addr;
1947 int in_addrlen = sizeof(addr);
1949 /* Stop zombies */
1950 #ifdef SIGCLD_IGNORE
1951 signal(SIGCLD, SIG_IGN);
1952 #else
1953 signal(SIGCLD, SIGNAL_CAST sig_cld);
1954 #endif
1956 /* open an incoming socket */
1957 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
1958 if (s == -1)
1959 return(False);
1961 /* ready to listen */
1962 if (listen(s, 5) == -1)
1964 DEBUG(0,("listen: %s",strerror(errno)));
1965 close(s);
1966 return False;
1969 if(atexit_set == 0)
1970 atexit(killkids);
1972 /* now accept incoming connections - forking a new process
1973 for each incoming connection */
1974 DEBUG(2,("waiting for a connection\n"));
1975 while (1)
1977 Client = accept(s,&addr,&in_addrlen);
1979 if (Client == -1 && errno == EINTR)
1980 continue;
1982 if (Client == -1)
1984 DEBUG(0,("accept: %s",strerror(errno)));
1985 continue;
1988 #ifdef NO_FORK_DEBUG
1989 #ifndef NO_SIGNAL_TEST
1990 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1991 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
1992 #endif
1993 return True;
1994 #else
1995 if (Client != -1 && fork()==0)
1997 #ifndef NO_SIGNAL_TEST
1998 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
1999 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2000 #endif
2001 /* close the listening socket */
2002 close(s);
2004 /* close our standard file descriptors */
2005 close_low_fds();
2006 am_parent = 0;
2008 set_socket_options(Client,"SO_KEEPALIVE");
2009 set_socket_options(Client,user_socket_options);
2011 return True;
2013 close(Client); /* The parent doesn't need this socket */
2014 #endif
2017 else
2019 /* We will abort gracefully when the client or remote system
2020 goes away */
2021 #ifndef NO_SIGNAL_TEST
2022 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2023 #endif
2024 Client = dup(0);
2026 /* close our standard file descriptors */
2027 close_low_fds();
2029 set_socket_options(Client,"SO_KEEPALIVE");
2030 set_socket_options(Client,user_socket_options);
2033 return True;
2037 /****************************************************************************
2038 check if a snum is in use
2039 ****************************************************************************/
2040 BOOL snum_used(int snum)
2042 int i;
2043 for (i=0;i<MAX_CONNECTIONS;i++)
2044 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2045 return(True);
2046 return(False);
2049 /****************************************************************************
2050 reload the services file
2051 **************************************************************************/
2052 BOOL reload_services(BOOL test)
2054 BOOL ret;
2056 if (lp_loaded())
2058 pstring fname;
2059 strcpy(fname,lp_configfile());
2060 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2062 strcpy(servicesf,fname);
2063 test = False;
2067 reopen_logs();
2069 if (test && !lp_file_list_changed())
2070 return(True);
2072 lp_killunused(snum_used);
2074 ret = lp_load(servicesf,False);
2076 /* perhaps the config filename is now set */
2077 if (!test)
2078 reload_services(True);
2080 reopen_logs();
2082 load_interfaces();
2085 extern int Client;
2086 if (Client != -1) {
2087 set_socket_options(Client,"SO_KEEPALIVE");
2088 set_socket_options(Client,user_socket_options);
2092 create_mangled_stack(lp_mangledstack());
2094 /* this forces service parameters to be flushed */
2095 become_service(-1,True);
2097 return(ret);
2102 /****************************************************************************
2103 this prevents zombie child processes
2104 ****************************************************************************/
2105 static int sig_hup()
2107 BlockSignals(True,SIGHUP);
2108 DEBUG(0,("Got SIGHUP\n"));
2109 reload_services(False);
2110 #ifndef DONT_REINSTALL_SIG
2111 signal(SIGHUP,SIGNAL_CAST sig_hup);
2112 #endif
2113 BlockSignals(False,SIGHUP);
2114 return(0);
2117 /****************************************************************************
2118 Setup the groups a user belongs to.
2119 ****************************************************************************/
2120 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2121 int **p_igroups, gid_t **p_groups)
2123 if (-1 == initgroups(user,gid))
2125 if (getuid() == 0)
2127 DEBUG(0,("Unable to initgroups!\n"));
2128 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2129 DEBUG(0,("This is probably a problem with the account %s\n",user));
2132 else
2134 int i,ngroups;
2135 int *igroups;
2136 gid_t grp = 0;
2137 ngroups = getgroups(0,&grp);
2138 if (ngroups <= 0)
2139 ngroups = 32;
2140 igroups = (int *)malloc(sizeof(int)*ngroups);
2141 for (i=0;i<ngroups;i++)
2142 igroups[i] = 0x42424242;
2143 ngroups = getgroups(ngroups,(gid_t *)igroups);
2145 if (igroups[0] == 0x42424242)
2146 ngroups = 0;
2148 *p_ngroups = ngroups;
2150 /* The following bit of code is very strange. It is due to the
2151 fact that some OSes use int* and some use gid_t* for
2152 getgroups, and some (like SunOS) use both, one in prototypes,
2153 and one in man pages and the actual code. Thus we detect it
2154 dynamically using some very ugly code */
2155 if (ngroups > 0)
2157 /* does getgroups return ints or gid_t ?? */
2158 static BOOL groups_use_ints = True;
2160 if (groups_use_ints &&
2161 ngroups == 1 &&
2162 SVAL(igroups,2) == 0x4242)
2163 groups_use_ints = False;
2165 for (i=0;groups_use_ints && i<ngroups;i++)
2166 if (igroups[i] == 0x42424242)
2167 groups_use_ints = False;
2169 if (groups_use_ints)
2171 *p_igroups = igroups;
2172 *p_groups = (gid_t *)igroups;
2174 else
2176 gid_t *groups = (gid_t *)igroups;
2177 igroups = (int *)malloc(sizeof(int)*ngroups);
2178 for (i=0;i<ngroups;i++)
2179 igroups[i] = groups[i];
2180 *p_igroups = igroups;
2181 *p_groups = (gid_t *)groups;
2184 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2185 for (i=0;i<ngroups;i++)
2186 DEBUG(3,("%d ",igroups[i]));
2187 DEBUG(3,("\n"));
2189 return 0;
2192 /****************************************************************************
2193 make a connection to a service
2194 ****************************************************************************/
2195 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2197 int cnum;
2198 int snum;
2199 struct passwd *pass = NULL;
2200 connection_struct *pcon;
2201 BOOL guest = False;
2202 BOOL force = False;
2203 static BOOL first_connection = True;
2205 strlower(service);
2207 snum = find_service(service);
2208 if (snum < 0)
2210 if (strequal(service,"IPC$"))
2212 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2213 return(-3);
2216 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2217 return(-2);
2220 if (strequal(service,HOMES_NAME))
2222 if (*user && Get_Pwnam(user,True))
2223 return(make_connection(user,user,password,pwlen,dev,vuid));
2225 if (validated_username(vuid))
2227 strcpy(user,validated_username(vuid));
2228 return(make_connection(user,user,password,pwlen,dev,vuid));
2232 if (!lp_snum_ok(snum) || !check_access(snum)) {
2233 return(-4);
2236 /* you can only connect to the IPC$ service as an ipc device */
2237 if (strequal(service,"IPC$"))
2238 strcpy(dev,"IPC");
2240 if (*dev == '?' || !*dev)
2242 if (lp_print_ok(snum))
2243 strcpy(dev,"LPT1:");
2244 else
2245 strcpy(dev,"A:");
2248 /* if the request is as a printer and you can't print then refuse */
2249 strupper(dev);
2250 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2251 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2252 return(-6);
2255 /* lowercase the user name */
2256 strlower(user);
2258 /* add it as a possible user name */
2259 add_session_user(service);
2261 /* shall we let them in? */
2262 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2264 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2265 return(-1);
2268 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2269 if (cnum < 0)
2271 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2272 return(-1);
2275 pcon = &Connections[cnum];
2276 bzero((char *)pcon,sizeof(*pcon));
2278 /* find out some info about the user */
2279 pass = Get_Pwnam(user,True);
2281 if (pass == NULL)
2283 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2284 return(-7);
2287 pcon->read_only = lp_readonly(snum);
2290 pstring list;
2291 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2292 string_sub(list,"%S",service);
2294 if (user_in_list(user,list))
2295 pcon->read_only = True;
2297 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2298 string_sub(list,"%S",service);
2300 if (user_in_list(user,list))
2301 pcon->read_only = False;
2304 /* admin user check */
2305 if (user_in_list(user,lp_admin_users(snum)) &&
2306 !pcon->read_only)
2308 pcon->admin_user = True;
2309 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2311 else
2312 pcon->admin_user = False;
2314 pcon->force_user = force;
2315 pcon->vuid = vuid;
2316 pcon->uid = pass->pw_uid;
2317 pcon->gid = pass->pw_gid;
2318 pcon->num_files_open = 0;
2319 pcon->lastused = time(NULL);
2320 pcon->service = snum;
2321 pcon->used = True;
2322 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2323 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2324 pcon->dirptr = NULL;
2325 string_set(&pcon->dirpath,"");
2326 string_set(&pcon->user,user);
2328 #if HAVE_GETGRNAM
2329 if (*lp_force_group(snum))
2331 struct group *gptr;
2332 pstring gname;
2334 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2335 /* default service may be a group name */
2336 string_sub(gname,"%S",service);
2337 gptr = (struct group *)getgrnam(gname);
2339 if (gptr)
2341 pcon->gid = gptr->gr_gid;
2342 DEBUG(3,("Forced group %s\n",gname));
2344 else
2345 DEBUG(1,("Couldn't find group %s\n",gname));
2347 #endif
2349 if (*lp_force_user(snum))
2351 struct passwd *pass2;
2352 fstring fuser;
2353 strcpy(fuser,lp_force_user(snum));
2354 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2355 if (pass2)
2357 pcon->uid = pass2->pw_uid;
2358 string_set(&pcon->user,fuser);
2359 strcpy(user,fuser);
2360 pcon->force_user = True;
2361 DEBUG(3,("Forced user %s\n",fuser));
2363 else
2364 DEBUG(1,("Couldn't find user %s\n",fuser));
2368 pstring s;
2369 strcpy(s,lp_pathname(snum));
2370 standard_sub(cnum,s);
2371 string_set(&pcon->connectpath,s);
2372 DEBUG(3,("Connect path is %s\n",s));
2375 /* groups stuff added by ih */
2376 pcon->ngroups = 0;
2377 pcon->groups = NULL;
2379 if (!IS_IPC(cnum))
2381 /* Find all the groups this uid is in and store them. Used by become_user() */
2382 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2384 /* check number of connections */
2385 if (!claim_connection(cnum,
2386 lp_servicename(SNUM(cnum)),
2387 lp_max_connections(SNUM(cnum)),False))
2389 DEBUG(1,("too many connections - rejected\n"));
2390 return(-8);
2393 if (lp_status(SNUM(cnum)))
2394 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2396 first_connection = False;
2397 } /* IS_IPC */
2399 pcon->open = True;
2401 /* execute any "root preexec = " line */
2402 if (*lp_rootpreexec(SNUM(cnum)))
2404 pstring cmd;
2405 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2406 standard_sub(cnum,cmd);
2407 DEBUG(5,("cmd=%s\n",cmd));
2408 smbrun(cmd,NULL,False);
2411 if (!become_user(cnum,pcon->vuid))
2413 DEBUG(0,("Can't become connected user!\n"));
2414 pcon->open = False;
2415 if (!IS_IPC(cnum)) {
2416 yield_connection(cnum,
2417 lp_servicename(SNUM(cnum)),
2418 lp_max_connections(SNUM(cnum)));
2419 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2421 return(-1);
2424 if (ChDir(pcon->connectpath) != 0)
2426 DEBUG(0,("Can't change directory to %s (%s)\n",
2427 pcon->connectpath,strerror(errno)));
2428 pcon->open = False;
2429 unbecome_user();
2430 if (!IS_IPC(cnum)) {
2431 yield_connection(cnum,
2432 lp_servicename(SNUM(cnum)),
2433 lp_max_connections(SNUM(cnum)));
2434 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2436 return(-5);
2439 string_set(&pcon->origpath,pcon->connectpath);
2441 #if SOFTLINK_OPTIMISATION
2442 /* resolve any soft links early */
2444 pstring s;
2445 strcpy(s,pcon->connectpath);
2446 GetWd(s);
2447 string_set(&pcon->connectpath,s);
2448 ChDir(pcon->connectpath);
2450 #endif
2452 num_connections_open++;
2453 add_session_user(user);
2455 /* execute any "preexec = " line */
2456 if (*lp_preexec(SNUM(cnum)))
2458 pstring cmd;
2459 strcpy(cmd,lp_preexec(SNUM(cnum)));
2460 standard_sub(cnum,cmd);
2461 smbrun(cmd,NULL,False);
2464 /* we've finished with the sensitive stuff */
2465 unbecome_user();
2468 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2469 timestring(),
2470 remote_machine,
2471 client_addr(),
2472 lp_servicename(SNUM(cnum)),user,
2473 pcon->uid,
2474 pcon->gid,
2475 (int)getpid()));
2478 return(cnum);
2482 /****************************************************************************
2483 find first available file slot
2484 ****************************************************************************/
2485 int find_free_file(void )
2487 int i;
2488 /* we start at 1 here for an obscure reason I can't now remember,
2489 but I think is important :-) */
2490 for (i=1;i<MAX_OPEN_FILES;i++)
2491 if (!Files[i].open)
2492 return(i);
2493 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2494 return(-1);
2497 /****************************************************************************
2498 find first available connection slot, starting from a random position.
2499 The randomisation stops problems with the server dieing and clients
2500 thinking the server is still available.
2501 ****************************************************************************/
2502 static int find_free_connection(int hash )
2504 int i;
2505 BOOL used=False;
2506 hash = (hash % (MAX_CONNECTIONS-2))+1;
2508 again:
2510 for (i=hash+1;i!=hash;)
2512 if (!Connections[i].open && Connections[i].used == used)
2514 DEBUG(3,("found free connection number %d\n",i));
2515 return(i);
2517 i++;
2518 if (i == MAX_CONNECTIONS)
2519 i = 1;
2522 if (!used)
2524 used = !used;
2525 goto again;
2528 DEBUG(1,("ERROR! Out of connection structures\n"));
2529 return(-1);
2533 /****************************************************************************
2534 reply for the core protocol
2535 ****************************************************************************/
2536 int reply_corep(char *outbuf)
2538 int outsize = set_message(outbuf,1,0,True);
2540 Protocol = PROTOCOL_CORE;
2542 return outsize;
2546 /****************************************************************************
2547 reply for the coreplus protocol
2548 ****************************************************************************/
2549 int reply_coreplus(char *outbuf)
2551 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2552 int outsize = set_message(outbuf,13,0,True);
2553 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2554 readbraw and writebraw (possibly) */
2555 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2556 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2558 Protocol = PROTOCOL_COREPLUS;
2560 return outsize;
2564 /****************************************************************************
2565 reply for the lanman 1.0 protocol
2566 ****************************************************************************/
2567 int reply_lanman1(char *outbuf)
2569 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2570 int secword=0;
2571 BOOL doencrypt = SMBENCRYPT();
2572 time_t t = time(NULL);
2574 if (lp_security()>=SEC_USER) secword |= 1;
2575 if (doencrypt) secword |= 2;
2577 set_message(outbuf,13,doencrypt?8:0,True);
2578 SSVAL(outbuf,smb_vwv1,secword);
2579 #ifdef SMB_PASSWD
2580 /* Create a token value and add it to the outgoing packet. */
2581 if (doencrypt)
2582 generate_next_challenge(smb_buf(outbuf));
2583 #endif
2585 Protocol = PROTOCOL_LANMAN1;
2587 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2588 DEBUG(3,("using password server validation\n"));
2589 #ifdef SMB_PASSWD
2590 if (doencrypt) set_challenge(smb_buf(outbuf));
2591 #endif
2594 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2595 SSVAL(outbuf,smb_vwv2,maxxmit);
2596 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2597 SSVAL(outbuf,smb_vwv4,1);
2598 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2599 readbraw writebraw (possibly) */
2600 SIVAL(outbuf,smb_vwv6,getpid());
2601 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2603 put_dos_date(outbuf,smb_vwv8,t);
2605 return (smb_len(outbuf)+4);
2609 /****************************************************************************
2610 reply for the lanman 2.0 protocol
2611 ****************************************************************************/
2612 int reply_lanman2(char *outbuf)
2614 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2615 int secword=0;
2616 BOOL doencrypt = SMBENCRYPT();
2617 time_t t = time(NULL);
2619 if (lp_security()>=SEC_USER) secword |= 1;
2620 if (doencrypt) secword |= 2;
2622 set_message(outbuf,13,doencrypt?8:0,True);
2623 SSVAL(outbuf,smb_vwv1,secword);
2624 #ifdef SMB_PASSWD
2625 /* Create a token value and add it to the outgoing packet. */
2626 if (doencrypt)
2627 generate_next_challenge(smb_buf(outbuf));
2628 #endif
2630 SIVAL(outbuf,smb_vwv6,getpid());
2632 Protocol = PROTOCOL_LANMAN2;
2634 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2635 DEBUG(3,("using password server validation\n"));
2636 #ifdef SMB_PASSWD
2637 if (doencrypt) set_challenge(smb_buf(outbuf));
2638 #endif
2641 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2642 SSVAL(outbuf,smb_vwv2,maxxmit);
2643 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2644 SSVAL(outbuf,smb_vwv4,1);
2645 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2646 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2647 put_dos_date(outbuf,smb_vwv8,t);
2649 return (smb_len(outbuf)+4);
2652 /****************************************************************************
2653 reply for the nt protocol
2654 ****************************************************************************/
2655 int reply_nt1(char *outbuf)
2657 int capabilities=0x300; /* has dual names + lock_and_read */
2658 int secword=0;
2659 BOOL doencrypt = SMBENCRYPT();
2660 time_t t = time(NULL);
2662 if (lp_security()>=SEC_USER) secword |= 1;
2663 if (doencrypt) secword |= 2;
2665 set_message(outbuf,17,doencrypt?8:0,True);
2666 CVAL(outbuf,smb_vwv1) = secword;
2667 #ifdef SMB_PASSWD
2668 /* Create a token value and add it to the outgoing packet. */
2669 if (doencrypt) {
2670 generate_next_challenge(smb_buf(outbuf));
2671 /* Tell the nt machine how long the challenge is. */
2672 SSVALS(outbuf,smb_vwv16+1,8);
2674 #endif
2676 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2678 Protocol = PROTOCOL_NT1;
2680 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2681 DEBUG(3,("using password server validation\n"));
2682 #ifdef SMB_PASSWD
2683 if (doencrypt) set_challenge(smb_buf(outbuf));
2684 #endif
2687 if (lp_readraw() && lp_writeraw())
2688 capabilities |= 1;
2690 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2691 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2692 SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
2693 SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
2694 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2695 put_long_date(outbuf+smb_vwv11+1,t);
2696 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2698 return (smb_len(outbuf)+4);
2702 /* these are the protocol lists used for auto architecture detection:
2704 WinNT 3.51:
2705 protocol [PC NETWORK PROGRAM 1.0]
2706 protocol [XENIX CORE]
2707 protocol [MICROSOFT NETWORKS 1.03]
2708 protocol [LANMAN1.0]
2709 protocol [Windows for Workgroups 3.1a]
2710 protocol [LM1.2X002]
2711 protocol [LANMAN2.1]
2712 protocol [NT LM 0.12]
2714 Win95:
2715 protocol [PC NETWORK PROGRAM 1.0]
2716 protocol [XENIX CORE]
2717 protocol [MICROSOFT NETWORKS 1.03]
2718 protocol [LANMAN1.0]
2719 protocol [Windows for Workgroups 3.1a]
2720 protocol [LM1.2X002]
2721 protocol [LANMAN2.1]
2722 protocol [NT LM 0.12]
2724 OS/2:
2725 protocol [PC NETWORK PROGRAM 1.0]
2726 protocol [XENIX CORE]
2727 protocol [LANMAN1.0]
2728 protocol [LM1.2X002]
2729 protocol [LANMAN2.1]
2733 * Modified to recognize the architecture of the remote machine better.
2735 * This appears to be the matrix of which protocol is used by which
2736 * MS product.
2737 Protocol WfWg Win95 WinNT OS/2
2738 PC NETWORK PROGRAM 1.0 1 1 1 1
2739 XENIX CORE 2 2
2740 MICROSOFT NETWORKS 3.0 2 2
2741 DOS LM1.2X002 3 3
2742 MICROSOFT NETWORKS 1.03 3
2743 DOS LANMAN2.1 4 4
2744 LANMAN1.0 4 3
2745 Windows for Workgroups 3.1a 5 5 5
2746 LM1.2X002 6 4
2747 LANMAN2.1 7 5
2748 NT LM 0.12 6 8
2750 * tim@fsg.com 09/29/95
2753 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2754 #define ARCH_WIN95 0x2
2755 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2756 #define ARCH_WINNT 0x8
2757 #define ARCH_SAMBA 0x10
2759 #define ARCH_ALL 0x1F
2761 /* List of supported protocols, most desired first */
2762 struct {
2763 char *proto_name;
2764 char *short_name;
2765 int (*proto_reply_fn)(char *);
2766 int protocol_level;
2767 } supported_protocols[] = {
2768 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2769 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2770 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2771 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2772 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2773 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2774 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2775 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2776 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2777 {NULL,NULL},
2781 /****************************************************************************
2782 reply to a negprot
2783 ****************************************************************************/
2784 static int reply_negprot(char *inbuf,char *outbuf)
2786 extern fstring remote_arch;
2787 int outsize = set_message(outbuf,1,0,True);
2788 int Index=0;
2789 int choice= -1;
2790 int protocol;
2791 char *p;
2792 int bcc = SVAL(smb_buf(inbuf),-2);
2793 int arch = ARCH_ALL;
2795 p = smb_buf(inbuf)+1;
2796 while (p < (smb_buf(inbuf) + bcc))
2798 Index++;
2799 DEBUG(3,("Requested protocol [%s]\n",p));
2800 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2801 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2802 else if (strcsequal(p,"DOS LM1.2X002"))
2803 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2804 else if (strcsequal(p,"DOS LANMAN2.1"))
2805 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2806 else if (strcsequal(p,"NT LM 0.12"))
2807 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2808 else if (strcsequal(p,"LANMAN2.1"))
2809 arch &= ( ARCH_WINNT | ARCH_OS2 );
2810 else if (strcsequal(p,"LM1.2X002"))
2811 arch &= ( ARCH_WINNT | ARCH_OS2 );
2812 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2813 arch &= ARCH_WINNT;
2814 else if (strcsequal(p,"XENIX CORE"))
2815 arch &= ( ARCH_WINNT | ARCH_OS2 );
2816 else if (strcsequal(p,"Samba")) {
2817 arch = ARCH_SAMBA;
2818 break;
2821 p += strlen(p) + 2;
2824 switch ( arch ) {
2825 case ARCH_SAMBA:
2826 strcpy(remote_arch,"Samba");
2827 break;
2828 case ARCH_WFWG:
2829 strcpy(remote_arch,"WfWg");
2830 break;
2831 case ARCH_WIN95:
2832 strcpy(remote_arch,"Win95");
2833 break;
2834 case ARCH_WINNT:
2835 strcpy(remote_arch,"WinNT");
2836 break;
2837 case ARCH_OS2:
2838 strcpy(remote_arch,"OS2");
2839 break;
2840 default:
2841 strcpy(remote_arch,"UNKNOWN");
2842 break;
2845 /* possibly reload - change of architecture */
2846 reload_services(True);
2848 /* a special case to stop password server loops */
2849 if (Index == 1 && strequal(remote_machine,myhostname) &&
2850 lp_security()==SEC_SERVER)
2851 exit_server("Password server loop!");
2853 /* Check for protocols, most desirable first */
2854 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2856 p = smb_buf(inbuf)+1;
2857 Index = 0;
2858 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2859 while (p < (smb_buf(inbuf) + bcc))
2861 if (strequal(p,supported_protocols[protocol].proto_name))
2862 choice = Index;
2863 Index++;
2864 p += strlen(p) + 2;
2866 if(choice != -1)
2867 break;
2870 SSVAL(outbuf,smb_vwv0,choice);
2871 if(choice != -1) {
2872 extern fstring remote_proto;
2873 strcpy(remote_proto,supported_protocols[protocol].short_name);
2874 reload_services(True);
2875 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
2876 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
2878 else {
2879 DEBUG(0,("No protocol supported !\n"));
2881 SSVAL(outbuf,smb_vwv0,choice);
2883 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
2885 return(outsize);
2889 /****************************************************************************
2890 close all open files for a connection
2891 ****************************************************************************/
2892 static void close_open_files(int cnum)
2894 int i;
2895 for (i=0;i<MAX_OPEN_FILES;i++)
2896 if( Files[i].cnum == cnum && Files[i].open) {
2897 close_file(i);
2903 /****************************************************************************
2904 close a cnum
2905 ****************************************************************************/
2906 void close_cnum(int cnum, uint16 vuid)
2908 DirCacheFlush(SNUM(cnum));
2910 unbecome_user();
2912 if (!OPEN_CNUM(cnum))
2914 DEBUG(0,("Can't close cnum %d\n",cnum));
2915 return;
2918 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
2919 timestring(),
2920 remote_machine,client_addr(),
2921 lp_servicename(SNUM(cnum))));
2923 yield_connection(cnum,
2924 lp_servicename(SNUM(cnum)),
2925 lp_max_connections(SNUM(cnum)));
2927 if (lp_status(SNUM(cnum)))
2928 yield_connection(cnum,"STATUS.",MAXSTATUS);
2930 close_open_files(cnum);
2931 dptr_closecnum(cnum);
2933 /* execute any "postexec = " line */
2934 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
2936 pstring cmd;
2937 strcpy(cmd,lp_postexec(SNUM(cnum)));
2938 standard_sub(cnum,cmd);
2939 smbrun(cmd,NULL,False);
2940 unbecome_user();
2943 unbecome_user();
2944 /* execute any "root postexec = " line */
2945 if (*lp_rootpostexec(SNUM(cnum)))
2947 pstring cmd;
2948 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
2949 standard_sub(cnum,cmd);
2950 smbrun(cmd,NULL,False);
2953 Connections[cnum].open = False;
2954 num_connections_open--;
2955 if (Connections[cnum].ngroups && Connections[cnum].groups)
2957 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
2958 free(Connections[cnum].groups);
2959 free(Connections[cnum].igroups);
2960 Connections[cnum].groups = NULL;
2961 Connections[cnum].igroups = NULL;
2962 Connections[cnum].ngroups = 0;
2965 string_set(&Connections[cnum].user,"");
2966 string_set(&Connections[cnum].dirpath,"");
2967 string_set(&Connections[cnum].connectpath,"");
2971 /****************************************************************************
2972 simple routines to do connection counting
2973 ****************************************************************************/
2974 BOOL yield_connection(int cnum,char *name,int max_connections)
2976 struct connect_record crec;
2977 pstring fname;
2978 FILE *f;
2979 int mypid = getpid();
2980 int i;
2982 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
2984 if (max_connections <= 0)
2985 return(True);
2987 bzero(&crec,sizeof(crec));
2989 strcpy(fname,lp_lockdir());
2990 standard_sub(cnum,fname);
2991 trim_string(fname,"","/");
2993 strcat(fname,"/");
2994 strcat(fname,name);
2995 strcat(fname,".LCK");
2997 f = fopen(fname,"r+");
2998 if (!f)
3000 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3001 return(False);
3004 fseek(f,0,SEEK_SET);
3006 /* find a free spot */
3007 for (i=0;i<max_connections;i++)
3009 if (fread(&crec,sizeof(crec),1,f) != 1)
3011 DEBUG(2,("Entry not found in lock file %s\n",fname));
3012 fclose(f);
3013 return(False);
3015 if (crec.pid == mypid && crec.cnum == cnum)
3016 break;
3019 if (crec.pid != mypid || crec.cnum != cnum)
3021 fclose(f);
3022 DEBUG(2,("Entry not found in lock file %s\n",fname));
3023 return(False);
3026 bzero((void *)&crec,sizeof(crec));
3028 /* remove our mark */
3029 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3030 fwrite(&crec,sizeof(crec),1,f) != 1)
3032 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3033 fclose(f);
3034 return(False);
3037 DEBUG(3,("Yield successful\n"));
3039 fclose(f);
3040 return(True);
3044 /****************************************************************************
3045 simple routines to do connection counting
3046 ****************************************************************************/
3047 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3049 struct connect_record crec;
3050 pstring fname;
3051 FILE *f;
3052 int snum = SNUM(cnum);
3053 int i,foundi= -1;
3054 int total_recs;
3056 if (max_connections <= 0)
3057 return(True);
3059 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3061 strcpy(fname,lp_lockdir());
3062 standard_sub(cnum,fname);
3063 trim_string(fname,"","/");
3065 if (!directory_exist(fname,NULL))
3066 mkdir(fname,0755);
3068 strcat(fname,"/");
3069 strcat(fname,name);
3070 strcat(fname,".LCK");
3072 if (!file_exist(fname,NULL))
3074 int oldmask = umask(022);
3075 f = fopen(fname,"w");
3076 if (f) fclose(f);
3077 umask(oldmask);
3080 total_recs = file_size(fname) / sizeof(crec);
3082 f = fopen(fname,"r+");
3084 if (!f)
3086 DEBUG(1,("couldn't open lock file %s\n",fname));
3087 return(False);
3090 /* find a free spot */
3091 for (i=0;i<max_connections;i++)
3094 if (i>=total_recs ||
3095 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3096 fread(&crec,sizeof(crec),1,f) != 1)
3098 if (foundi < 0) foundi = i;
3099 break;
3102 if (Clear && crec.pid && !process_exists(crec.pid))
3104 fseek(f,i*sizeof(crec),SEEK_SET);
3105 bzero((void *)&crec,sizeof(crec));
3106 fwrite(&crec,sizeof(crec),1,f);
3107 if (foundi < 0) foundi = i;
3108 continue;
3110 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3112 foundi=i;
3113 if (!Clear) break;
3117 if (foundi < 0)
3119 DEBUG(3,("no free locks in %s\n",fname));
3120 fclose(f);
3121 return(False);
3124 /* fill in the crec */
3125 bzero((void *)&crec,sizeof(crec));
3126 crec.magic = 0x280267;
3127 crec.pid = getpid();
3128 crec.cnum = cnum;
3129 crec.uid = Connections[cnum].uid;
3130 crec.gid = Connections[cnum].gid;
3131 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3132 crec.start = time(NULL);
3134 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3135 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3137 /* make our mark */
3138 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3139 fwrite(&crec,sizeof(crec),1,f) != 1)
3141 fclose(f);
3142 return(False);
3145 fclose(f);
3146 return(True);
3149 #if DUMP_CORE
3150 /*******************************************************************
3151 prepare to dump a core file - carefully!
3152 ********************************************************************/
3153 static BOOL dump_core(void)
3155 char *p;
3156 pstring dname;
3157 strcpy(dname,debugf);
3158 if ((p=strrchr(dname,'/'))) *p=0;
3159 strcat(dname,"/corefiles");
3160 mkdir(dname,0700);
3161 sys_chown(dname,getuid(),getgid());
3162 chmod(dname,0700);
3163 if (chdir(dname)) return(False);
3164 umask(~(0700));
3166 #ifndef NO_GETRLIMIT
3167 #ifdef RLIMIT_CORE
3169 struct rlimit rlp;
3170 getrlimit(RLIMIT_CORE, &rlp);
3171 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3172 setrlimit(RLIMIT_CORE, &rlp);
3173 getrlimit(RLIMIT_CORE, &rlp);
3174 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3176 #endif
3177 #endif
3180 DEBUG(0,("Dumping core in %s\n",dname));
3181 return(True);
3183 #endif
3185 /****************************************************************************
3186 exit the server
3187 ****************************************************************************/
3188 void exit_server(char *reason)
3190 static int firsttime=1;
3191 int i;
3193 if (!firsttime) exit(0);
3194 firsttime = 0;
3196 unbecome_user();
3197 DEBUG(2,("Closing connections\n"));
3198 for (i=0;i<MAX_CONNECTIONS;i++)
3199 if (Connections[i].open)
3200 close_cnum(i,-1);
3201 #ifdef DFS_AUTH
3202 if (dcelogin_atmost_once)
3203 dfs_unlogin();
3204 #endif
3205 if (!reason) {
3206 int oldlevel = DEBUGLEVEL;
3207 DEBUGLEVEL = 10;
3208 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3209 if (last_inbuf)
3210 show_msg(last_inbuf);
3211 DEBUGLEVEL = oldlevel;
3212 DEBUG(0,("===============================================================\n"));
3213 #if DUMP_CORE
3214 if (dump_core()) return;
3215 #endif
3218 #if FAST_SHARE_MODES
3219 stop_share_mode_mgmt();
3220 #endif
3222 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3223 exit(0);
3226 /****************************************************************************
3227 do some standard substitutions in a string
3228 ****************************************************************************/
3229 void standard_sub(int cnum,char *s)
3231 if (!strchr(s,'%')) return;
3233 if (VALID_CNUM(cnum))
3235 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3236 string_sub(s,"%P",Connections[cnum].connectpath);
3237 string_sub(s,"%u",Connections[cnum].user);
3238 if (strstr(s,"%H")) {
3239 char *home = get_home_dir(Connections[cnum].user);
3240 if (home) string_sub(s,"%H",home);
3242 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3244 standard_sub_basic(s);
3248 These flags determine some of the permissions required to do an operation
3250 Note that I don't set NEED_WRITE on some write operations because they
3251 are used by some brain-dead clients when printing, and I don't want to
3252 force write permissions on print services.
3254 #define AS_USER (1<<0)
3255 #define NEED_WRITE (1<<1)
3256 #define TIME_INIT (1<<2)
3257 #define CAN_IPC (1<<3)
3258 #define AS_GUEST (1<<5)
3262 define a list of possible SMB messages and their corresponding
3263 functions. Any message that has a NULL function is unimplemented -
3264 please feel free to contribute implementations!
3266 struct smb_message_struct
3268 int code;
3269 char *name;
3270 int (*fn)();
3271 int flags;
3272 #if PROFILING
3273 unsigned long time;
3274 #endif
3276 smb_messages[] = {
3278 /* CORE PROTOCOL */
3280 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3281 {SMBtcon,"SMBtcon",reply_tcon,0},
3282 {SMBtdis,"SMBtdis",reply_tdis,0},
3283 {SMBexit,"SMBexit",reply_exit,0},
3284 {SMBioctl,"SMBioctl",reply_ioctl,0},
3285 {SMBecho,"SMBecho",reply_echo,0},
3286 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3287 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3288 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3289 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3290 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3291 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3292 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3293 {SMBopen,"SMBopen",reply_open,AS_USER},
3295 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3296 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3297 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3299 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3300 {SMBread,"SMBread",reply_read,AS_USER},
3301 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3302 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3303 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3304 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3305 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3306 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3308 /* this is a Pathworks specific call, allowing the
3309 changing of the root path */
3310 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3312 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3313 {SMBflush,"SMBflush",reply_flush,AS_USER},
3314 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3315 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3316 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3317 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3318 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3319 {SMBlock,"SMBlock",reply_lock,AS_USER},
3320 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3322 /* CORE+ PROTOCOL FOLLOWS */
3324 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3325 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3326 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3327 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3328 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3330 /* LANMAN1.0 PROTOCOL FOLLOWS */
3332 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3333 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3334 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3335 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3336 {SMBwritec,"SMBwritec",NULL,AS_USER},
3337 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3338 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3339 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3340 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3341 {SMBioctls,"SMBioctls",NULL,AS_USER},
3342 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3343 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3345 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3346 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3347 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3348 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3350 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3351 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3352 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3354 /* LANMAN2.0 PROTOCOL FOLLOWS */
3355 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3356 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3357 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3358 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3360 /* messaging routines */
3361 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3362 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3363 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3364 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3366 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3368 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3369 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3370 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3371 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3374 /****************************************************************************
3375 return a string containing the function name of a SMB command
3376 ****************************************************************************/
3377 char *smb_fn_name(int type)
3379 static char *unknown_name = "SMBunknown";
3380 static int num_smb_messages =
3381 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3382 int match;
3384 for (match=0;match<num_smb_messages;match++)
3385 if (smb_messages[match].code == type)
3386 break;
3388 if (match == num_smb_messages)
3389 return(unknown_name);
3391 return(smb_messages[match].name);
3395 /****************************************************************************
3396 do a switch on the message type, and return the response size
3397 ****************************************************************************/
3398 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3400 static int pid= -1;
3401 int outsize = 0;
3402 static int num_smb_messages =
3403 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3404 int match;
3406 #if PROFILING
3407 struct timeval msg_start_time;
3408 struct timeval msg_end_time;
3409 static unsigned long total_time = 0;
3411 GetTimeOfDay(&msg_start_time);
3412 #endif
3414 if (pid == -1)
3415 pid = getpid();
3417 errno = 0;
3418 last_message = type;
3420 /* make sure this is an SMB packet */
3421 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3423 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3424 return(-1);
3427 for (match=0;match<num_smb_messages;match++)
3428 if (smb_messages[match].code == type)
3429 break;
3431 if (match == num_smb_messages)
3433 DEBUG(0,("Unknown message type %d!\n",type));
3434 outsize = reply_unknown(inbuf,outbuf);
3436 else
3438 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3439 if (smb_messages[match].fn)
3441 int cnum = SVAL(inbuf,smb_tid);
3442 int flags = smb_messages[match].flags;
3443 uint16 session_tag = SVAL(inbuf,smb_uid);
3445 /* does this protocol need to be run as root? */
3446 if (!(flags & AS_USER))
3447 unbecome_user();
3449 /* does this protocol need to be run as the connected user? */
3450 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3451 if (flags & AS_GUEST)
3452 flags &= ~AS_USER;
3453 else
3454 return(ERROR(ERRSRV,ERRinvnid));
3456 /* this code is to work around a bug is MS client 3 without
3457 introducing a security hole - it needs to be able to do
3458 print queue checks as guest if it isn't logged in properly */
3459 if (flags & AS_USER)
3460 flags &= ~AS_GUEST;
3462 /* does it need write permission? */
3463 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3464 return(ERROR(ERRSRV,ERRaccess));
3466 /* ipc services are limited */
3467 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3468 return(ERROR(ERRSRV,ERRaccess));
3470 /* load service specific parameters */
3471 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3472 return(ERROR(ERRSRV,ERRaccess));
3474 /* does this protocol need to be run as guest? */
3475 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3476 return(ERROR(ERRSRV,ERRaccess));
3478 last_inbuf = inbuf;
3480 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3482 else
3484 outsize = reply_unknown(inbuf,outbuf);
3488 #if PROFILING
3489 GetTimeOfDay(&msg_end_time);
3490 if (!(smb_messages[match].flags & TIME_INIT))
3492 smb_messages[match].time = 0;
3493 smb_messages[match].flags |= TIME_INIT;
3496 unsigned long this_time =
3497 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3498 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3499 smb_messages[match].time += this_time;
3500 total_time += this_time;
3502 DEBUG(2,("TIME %s %d usecs %g pct\n",
3503 smb_fn_name(type),smb_messages[match].time,
3504 (100.0*smb_messages[match].time) / total_time));
3505 #endif
3507 return(outsize);
3511 /****************************************************************************
3512 construct a chained reply and add it to the already made reply
3513 **************************************************************************/
3514 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3516 static char *orig_inbuf;
3517 static char *orig_outbuf;
3518 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3519 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3520 char *inbuf2, *outbuf2;
3521 int outsize2;
3522 char inbuf_saved[smb_wct];
3523 char outbuf_saved[smb_wct];
3524 extern int chain_size;
3525 int wct = CVAL(outbuf,smb_wct);
3526 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3528 /* maybe its not chained */
3529 if (smb_com2 == 0xFF) {
3530 CVAL(outbuf,smb_vwv0) = 0xFF;
3531 return outsize;
3534 if (chain_size == 0) {
3535 /* this is the first part of the chain */
3536 orig_inbuf = inbuf;
3537 orig_outbuf = outbuf;
3540 /* we need to tell the client where the next part of the reply will be */
3541 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3542 CVAL(outbuf,smb_vwv0) = smb_com2;
3544 /* remember how much the caller added to the chain, only counting stuff
3545 after the parameter words */
3546 chain_size += outsize - smb_wct;
3548 /* work out pointers into the original packets. The
3549 headers on these need to be filled in */
3550 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3551 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3553 /* remember the original command type */
3554 smb_com1 = CVAL(orig_inbuf,smb_com);
3556 /* save the data which will be overwritten by the new headers */
3557 memcpy(inbuf_saved,inbuf2,smb_wct);
3558 memcpy(outbuf_saved,outbuf2,smb_wct);
3560 /* give the new packet the same header as the last part of the SMB */
3561 memmove(inbuf2,inbuf,smb_wct);
3563 /* create the in buffer */
3564 CVAL(inbuf2,smb_com) = smb_com2;
3566 /* create the out buffer */
3567 bzero(outbuf2,smb_size);
3568 set_message(outbuf2,0,0,True);
3569 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3571 memcpy(outbuf2+4,inbuf2+4,4);
3572 CVAL(outbuf2,smb_rcls) = SUCCESS;
3573 CVAL(outbuf2,smb_reh) = 0;
3574 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3575 means a reply */
3576 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3577 SSVAL(outbuf2,smb_err,SUCCESS);
3578 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3579 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3580 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3581 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3583 DEBUG(3,("Chained message\n"));
3584 show_msg(inbuf2);
3586 /* process the request */
3587 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3588 bufsize-chain_size);
3590 /* copy the new reply and request headers over the old ones, but
3591 preserve the smb_com field */
3592 memmove(orig_outbuf,outbuf2,smb_wct);
3593 CVAL(orig_outbuf,smb_com) = smb_com1;
3595 /* restore the saved data, being careful not to overwrite any
3596 data from the reply header */
3597 memcpy(inbuf2,inbuf_saved,smb_wct);
3599 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3600 if (ofs < 0) ofs = 0;
3601 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3604 return outsize2;
3609 /****************************************************************************
3610 construct a reply to the incoming packet
3611 ****************************************************************************/
3612 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3614 int type = CVAL(inbuf,smb_com);
3615 int outsize = 0;
3616 int msg_type = CVAL(inbuf,0);
3617 extern int chain_size;
3619 smb_last_time = time(NULL);
3621 chain_size = 0;
3622 chain_fnum = -1;
3624 bzero(outbuf,smb_size);
3626 if (msg_type != 0)
3627 return(reply_special(inbuf,outbuf));
3629 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3630 set_message(outbuf,0,0,True);
3632 memcpy(outbuf+4,inbuf+4,4);
3633 CVAL(outbuf,smb_rcls) = SUCCESS;
3634 CVAL(outbuf,smb_reh) = 0;
3635 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3636 means a reply */
3637 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3638 SSVAL(outbuf,smb_err,SUCCESS);
3639 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3640 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3641 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3642 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3644 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3646 outsize += chain_size;
3648 if(outsize > 4)
3649 smb_setlen(outbuf,outsize - 4);
3650 return(outsize);
3654 /****************************************************************************
3655 process commands from the client
3656 ****************************************************************************/
3657 static void process(void)
3659 static int trans_num = 0;
3660 int nread;
3661 extern int Client;
3663 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3664 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3665 if ((InBuffer == NULL) || (OutBuffer == NULL))
3666 return;
3668 InBuffer += SMB_ALIGNMENT;
3669 OutBuffer += SMB_ALIGNMENT;
3671 #if PRIME_NMBD
3672 DEBUG(3,("priming nmbd\n"));
3674 struct in_addr ip;
3675 ip = *interpret_addr2("localhost");
3676 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3677 *OutBuffer = 0;
3678 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3680 #endif
3682 while (True)
3684 int32 len;
3685 int msg_type;
3686 int msg_flags;
3687 int type;
3688 int deadtime = lp_deadtime()*60;
3689 int counter;
3690 int last_keepalive=0;
3692 if (deadtime <= 0)
3693 deadtime = DEFAULT_SMBD_TIMEOUT;
3695 if (lp_readprediction())
3696 do_read_prediction();
3699 extern pstring share_del_pending;
3700 if (*share_del_pending) {
3701 unbecome_user();
3702 if (!unlink(share_del_pending))
3703 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3704 else
3705 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3706 share_del_pending[0] = 0;
3710 if (share_mode_pending) {
3711 unbecome_user();
3712 check_share_modes();
3713 share_mode_pending=False;
3716 errno = 0;
3718 for (counter=SMBD_SELECT_LOOP;
3719 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3720 counter += SMBD_SELECT_LOOP)
3722 int i;
3723 time_t t;
3724 BOOL allidle = True;
3725 extern int keepalive;
3727 if (smb_read_error == READ_EOF) {
3728 DEBUG(3,("end of file from client\n"));
3729 return;
3732 if (smb_read_error == READ_ERROR) {
3733 DEBUG(3,("receive_smb error (%s) exiting\n",
3734 strerror(errno)));
3735 return;
3738 t = time(NULL);
3740 /* become root again if waiting */
3741 unbecome_user();
3743 /* check for smb.conf reload */
3744 if (!(counter%SMBD_RELOAD_CHECK))
3745 reload_services(True);
3747 /* check the share modes every 10 secs */
3748 if (!(counter%SHARE_MODES_CHECK))
3749 check_share_modes();
3751 /* clean the share modes every 5 minutes */
3752 if (!(counter%SHARE_MODES_CLEAN))
3753 clean_share_modes();
3755 /* automatic timeout if all connections are closed */
3756 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3757 DEBUG(2,("%s Closing idle connection\n",timestring()));
3758 return;
3761 if (keepalive && (counter-last_keepalive)>keepalive) {
3762 extern int password_client;
3763 if (!send_keepalive(Client)) {
3764 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3765 return;
3767 /* also send a keepalive to the password server if its still
3768 connected */
3769 if (password_client != -1)
3770 send_keepalive(password_client);
3771 last_keepalive = counter;
3774 /* check for connection timeouts */
3775 for (i=0;i<MAX_CONNECTIONS;i++)
3776 if (Connections[i].open)
3778 /* close dirptrs on connections that are idle */
3779 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3780 dptr_idlecnum(i);
3782 if (Connections[i].num_files_open > 0 ||
3783 (t-Connections[i].lastused)<deadtime)
3784 allidle = False;
3787 if (allidle && num_connections_open>0) {
3788 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3789 return;
3793 msg_type = CVAL(InBuffer,0);
3794 msg_flags = CVAL(InBuffer,1);
3795 type = CVAL(InBuffer,smb_com);
3797 len = smb_len(InBuffer);
3799 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3801 nread = len + 4;
3803 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3805 #ifdef WITH_VTP
3806 if(trans_num == 1 && VT_Check(InBuffer)) {
3807 VT_Process();
3808 return;
3810 #endif
3813 if (msg_type == 0)
3814 show_msg(InBuffer);
3816 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
3818 if(nread > 0) {
3819 if (CVAL(OutBuffer,0) == 0)
3820 show_msg(OutBuffer);
3822 if (nread != smb_len(OutBuffer) + 4)
3824 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3825 nread,
3826 smb_len(OutBuffer)));
3828 else
3829 send_smb(Client,OutBuffer);
3831 trans_num++;
3836 /****************************************************************************
3837 initialise connect, service and file structs
3838 ****************************************************************************/
3839 static void init_structs(void )
3841 int i;
3842 get_myname(myhostname,NULL);
3844 for (i=0;i<MAX_CONNECTIONS;i++)
3846 Connections[i].open = False;
3847 Connections[i].num_files_open=0;
3848 Connections[i].lastused=0;
3849 Connections[i].used=False;
3850 string_init(&Connections[i].user,"");
3851 string_init(&Connections[i].dirpath,"");
3852 string_init(&Connections[i].connectpath,"");
3853 string_init(&Connections[i].origpath,"");
3856 for (i=0;i<MAX_OPEN_FILES;i++)
3858 Files[i].open = False;
3859 string_init(&Files[i].name,"");
3863 for (i=0;i<MAX_OPEN_FILES;i++)
3865 file_fd_struct *fd_ptr = &FileFd[i];
3866 fd_ptr->ref_count = 0;
3867 fd_ptr->dev = (int32)-1;
3868 fd_ptr->inode = (int32)-1;
3869 fd_ptr->fd = -1;
3870 fd_ptr->fd_readonly = -1;
3871 fd_ptr->fd_writeonly = -1;
3872 fd_ptr->real_open_flags = -1;
3875 init_dptrs();
3878 /****************************************************************************
3879 usage on the program
3880 ****************************************************************************/
3881 static void usage(char *pname)
3883 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3885 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
3886 printf("Version %s\n",VERSION);
3887 printf("\t-D become a daemon\n");
3888 printf("\t-p port listen on the specified port\n");
3889 printf("\t-d debuglevel set the debuglevel\n");
3890 printf("\t-l log basename. Basename for log/debug files\n");
3891 printf("\t-s services file. Filename of services file\n");
3892 printf("\t-P passive only\n");
3893 printf("\t-a overwrite log file, don't append\n");
3894 printf("\n");
3898 /****************************************************************************
3899 main program
3900 ****************************************************************************/
3901 int main(int argc,char *argv[])
3903 extern BOOL append_log;
3904 /* shall I run as a daemon */
3905 BOOL is_daemon = False;
3906 int port = SMB_PORT;
3907 int opt;
3908 extern char *optarg;
3909 char pidFile[100] = { 0 };
3911 #ifdef NEED_AUTH_PARAMETERS
3912 set_auth_parameters(argc,argv);
3913 #endif
3915 #ifdef SecureWare
3916 setluid(0);
3917 #endif
3919 append_log = True;
3921 TimeInit();
3923 strcpy(debugf,SMBLOGFILE);
3925 setup_logging(argv[0],False);
3927 charset_initialise();
3929 /* make absolutely sure we run as root - to handle cases whre people
3930 are crazy enough to have it setuid */
3931 #ifdef USE_SETRES
3932 setresuid(0,0,0);
3933 #else
3934 setuid(0);
3935 seteuid(0);
3936 setuid(0);
3937 seteuid(0);
3938 #endif
3940 fault_setup(exit_server);
3941 signal(SIGTERM , SIGNAL_CAST dflt_sig);
3943 /* we want total control over the permissions on created files,
3944 so set our umask to 0 */
3945 umask(0);
3947 GetWd(OriginalDir);
3949 init_uid();
3951 /* this is for people who can't start the program correctly */
3952 while (argc > 1 && (*argv[1] != '-'))
3954 argv++;
3955 argc--;
3958 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
3959 switch (opt)
3961 case 'f':
3962 strncpy(pidFile, optarg, sizeof(pidFile));
3963 break;
3964 case 'O':
3965 strcpy(user_socket_options,optarg);
3966 break;
3967 case 'i':
3968 strcpy(scope,optarg);
3969 break;
3970 case 'P':
3972 extern BOOL passive;
3973 passive = True;
3975 break;
3976 case 's':
3977 strcpy(servicesf,optarg);
3978 break;
3979 case 'l':
3980 strcpy(debugf,optarg);
3981 break;
3982 case 'a':
3984 extern BOOL append_log;
3985 append_log = !append_log;
3987 break;
3988 case 'D':
3989 is_daemon = True;
3990 break;
3991 case 'd':
3992 if (*optarg == 'A')
3993 DEBUGLEVEL = 10000;
3994 else
3995 DEBUGLEVEL = atoi(optarg);
3996 break;
3997 case 'p':
3998 port = atoi(optarg);
3999 break;
4000 case 'h':
4001 usage(argv[0]);
4002 exit(0);
4003 break;
4004 default:
4005 usage(argv[0]);
4006 exit(1);
4009 reopen_logs();
4011 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4012 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4014 #ifndef NO_GETRLIMIT
4015 #ifdef RLIMIT_NOFILE
4017 struct rlimit rlp;
4018 getrlimit(RLIMIT_NOFILE, &rlp);
4019 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4020 setrlimit(RLIMIT_NOFILE, &rlp);
4021 getrlimit(RLIMIT_NOFILE, &rlp);
4022 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4024 #endif
4025 #endif
4028 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4029 getuid(),getgid(),geteuid(),getegid()));
4031 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4033 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4034 exit(1);
4037 init_structs();
4039 if (!reload_services(False))
4040 return(-1);
4042 #ifndef NO_SIGNAL_TEST
4043 signal(SIGHUP,SIGNAL_CAST sig_hup);
4044 #endif
4046 DEBUG(3,("%s loaded services\n",timestring()));
4048 if (!is_daemon && !is_a_socket(0))
4050 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4051 is_daemon = True;
4054 if (is_daemon)
4056 DEBUG(3,("%s becoming a daemon\n",timestring()));
4057 become_daemon();
4060 if (*pidFile)
4062 int fd;
4063 char buf[20];
4065 if ((fd = open(pidFile,
4066 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4068 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4069 exit(1);
4071 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4073 DEBUG(0,("ERROR: smbd is already running\n"));
4074 exit(1);
4076 sprintf(buf, "%u\n", (unsigned int) getpid());
4077 if (write(fd, buf, strlen(buf)) < 0)
4079 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4080 exit(1);
4082 /* Leave pid file open & locked for the duration... */
4085 if (!open_sockets(is_daemon,port))
4086 exit(1);
4088 #if FAST_SHARE_MODES
4089 if (!start_share_mode_mgmt())
4090 exit(1);
4091 #endif
4093 /* possibly reload the services file. */
4094 reload_services(True);
4096 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4098 if (*lp_rootdir())
4100 if (sys_chroot(lp_rootdir()) == 0)
4101 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4104 process();
4105 close_sockets();
4107 exit_server("normal exit");
4108 return(0);